diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java
index 468f87658c..a00fe2dca8 100644
--- a/core/src/main/java/bisq/core/trade/Trade.java
+++ b/core/src/main/java/bisq/core/trade/Trade.java
@@ -597,7 +597,13 @@ public abstract class Trade implements Tradable, Model {
trade.setLockTime(proto.getLockTime());
trade.setLastRefreshRequestDate(proto.getLastRefreshRequestDate());
trade.setCounterCurrencyExtraData(ProtoUtil.stringOrNullFromProto(proto.getCounterCurrencyExtraData()));
- trade.setAssetTxProofResult(ProtoUtil.enumFromProto(AssetTxProofResult.class, proto.getAssetTxProofResult()));
+
+ AssetTxProofResult persistedAssetTxProofResult = ProtoUtil.enumFromProto(AssetTxProofResult.class, proto.getAssetTxProofResult());
+ // We do not want to show the user the last pending state when he starts up the app again, so we clear it.
+ if (persistedAssetTxProofResult == AssetTxProofResult.PENDING) {
+ persistedAssetTxProofResult = null;
+ }
+ trade.setAssetTxProofResult(persistedAssetTxProofResult);
trade.chatMessages.addAll(proto.getChatMessageList().stream()
.map(ChatMessage::fromPayloadProto)
@@ -884,6 +890,7 @@ public abstract class Trade implements Tradable, Model {
public void setAssetTxProofResult(@Nullable AssetTxProofResult assetTxProofResult) {
this.assetTxProofResult = assetTxProofResult;
assetTxProofResultUpdateProperty.set(assetTxProofResultUpdateProperty.get() + 1);
+ persist();
}
diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/DevTestXmrTxProofHttpClient.java b/core/src/main/java/bisq/core/trade/txproof/xmr/DevTestXmrTxProofHttpClient.java
new file mode 100644
index 0000000000..cd9825187c
--- /dev/null
+++ b/core/src/main/java/bisq/core/trade/txproof/xmr/DevTestXmrTxProofHttpClient.java
@@ -0,0 +1,199 @@
+/*
+ * This file is part of Bisq.
+ *
+ * Bisq is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bisq is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bisq. If not, see .
+ */
+
+package bisq.core.trade.txproof.xmr;
+
+import bisq.core.trade.txproof.AssetTxProofHttpClient;
+
+import bisq.network.Socks5ProxyProvider;
+import bisq.network.http.HttpClientImpl;
+
+import bisq.common.app.DevEnv;
+
+import javax.inject.Inject;
+
+import java.io.IOException;
+
+import java.util.Date;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.annotation.Nullable;
+
+import static bisq.core.trade.txproof.xmr.XmrTxProofParser.MAX_DATE_TOLERANCE;
+
+/**
+ * This should help to test error scenarios in dev testing the app. This is additional to unit test which test the
+ * correct data but do not test the context of the results and how it behaves in the UI.
+ *
+ * You have to change the binding in TradeModule to
+ * bind(AssetTxProofHttpClient.class).to(DevTestXmrTxProofHttpClient.class); to use that class.
+ *
+ * This class can be removed once done testing, but as multiple devs are testing its useful to share it for now.
+ */
+@Slf4j
+public class DevTestXmrTxProofHttpClient extends HttpClientImpl implements AssetTxProofHttpClient {
+ enum ApiInvalidDetails {
+ EMPTY_JSON,
+ MISSING_DATA,
+ MISSING_STATUS,
+ UNHANDLED_STATUS,
+ MISSING_ADDRESS,
+ MISSING_TX_ID,
+ MISSING_VIEW_KEY,
+ MISSING_TS,
+ MISSING_CONF,
+ EXCEPTION
+ }
+
+ @Inject
+ public DevTestXmrTxProofHttpClient(@Nullable Socks5ProxyProvider socks5ProxyProvider) {
+ super(socks5ProxyProvider);
+ }
+
+ static int counter;
+
+ @Override
+ public String requestWithGET(String param,
+ @Nullable String headerKey,
+ @Nullable String headerValue) throws IOException {
+
+ XmrTxProofRequest.Result result = XmrTxProofRequest.Result.PENDING;
+ XmrTxProofRequest.Detail detail = XmrTxProofRequest.Detail.TX_NOT_FOUND;
+ ApiInvalidDetails apiInvalidDetails = ApiInvalidDetails.EXCEPTION;
+
+ int delay = counter == 0 ? 2000 : 100;
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if (counter >= 2) {
+ detail = XmrTxProofRequest.Detail.PENDING_CONFIRMATIONS.numConfirmations(counter - 2);
+ }
+ counter++;
+ switch (result) {
+ case PENDING:
+ switch (detail) {
+ case TX_NOT_FOUND:
+ return validJson().replace("success",
+ "fail");
+ case PENDING_CONFIRMATIONS:
+ return validJson().replace("201287",
+ String.valueOf(detail.getNumConfirmations()));
+ }
+ break;
+ case SUCCESS:
+ return validJson();
+ case FAILED:
+ switch (detail) {
+ case TX_HASH_INVALID:
+ return validJson().replace("5e665addf6d7c6300670e8a89564ed12b5c1a21c336408e2835668f9a6a0d802",
+ "-");
+ case TX_KEY_INVALID:
+ return validJson().replace("f3ce66c9d395e5e460c8802b2c3c1fff04e508434f9738ee35558aac4678c906",
+ "-");
+ case ADDRESS_INVALID:
+ return validJson().replace("5e665addf6d7c6300670e8a89564ed12b5c1a21c336408e2835668f9a6a0d802",
+ "-");
+ case NO_MATCH_FOUND:
+ return validJson().replace("match\": true",
+ "match\": false");
+ case AMOUNT_NOT_MATCHING:
+ return validJson().replace("8902597360000",
+ "18902597360000");
+ case TRADE_DATE_NOT_MATCHING:
+ DevEnv.setDevMode(false);
+ long date = (new Date(1574922644 * 1000L).getTime() - (MAX_DATE_TOLERANCE * 1000L + 1)) / 1000;
+ String replace = validJson().replace("1574922644",
+ String.valueOf(date));
+ return replace;
+ }
+ case ERROR:
+ switch (detail) {
+ /* case CONNECTION_FAILURE:
+ break;*/
+ case API_INVALID:
+ switch (apiInvalidDetails) {
+ case EMPTY_JSON:
+ return null;
+ case MISSING_DATA:
+ return validJson().replace("data",
+ "missing");
+ case MISSING_STATUS:
+ return validJson().replace("status",
+ "missing");
+ case UNHANDLED_STATUS:
+ return validJson().replace("success",
+ "missing");
+ case MISSING_ADDRESS:
+ return validJson().replace("address",
+ "missing");
+ case MISSING_TX_ID:
+ return validJson().replace("tx_hash",
+ "missing");
+ case MISSING_VIEW_KEY:
+ return validJson().replace("viewkey",
+ "missing");
+ case MISSING_TS:
+ return validJson().replace("tx_timestamp",
+ "missing");
+ case MISSING_CONF:
+ return validJson().replace("tx_confirmations",
+ "missing");
+ case EXCEPTION:
+ return validJson().replace("} ",
+ "");
+ }
+ break;
+ /* case NO_RESULTS_TIMEOUT:
+ break;*/
+ }
+ }
+ return validJson();
+ }
+
+ private String validJson() {
+ return "{\n" +
+ " \"data\": {\n" +
+ " \"address\": \"590f7263428051068bb45cdfcf93407c15b6e291d20c92d0251fcfbf53cc745cdf53319f7d6d7a8e21ea39041aabf31d220a32a875e3ca2087a777f1201c0571\",\n" +
+ " \"outputs\": [\n" +
+ " {\n" +
+ " \"amount\": 8902597360000,\n" +
+ " \"match\": true,\n" +
+ " \"output_idx\": 0,\n" +
+ " \"output_pubkey\": \"2b6d2296f2591c198cd1aa47de9a5d74270963412ed30bbcc63b8eff29f0d43e\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"amount\": 0,\n" +
+ " \"match\": false,\n" +
+ " \"output_idx\": 1,\n" +
+ " \"output_pubkey\": \"f53271624847507d80b746e91e689e88bc41678d55246275f5ad3c0f7e8a9ced\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"tx_confirmations\": 201287,\n" +
+ " \"tx_hash\": \"5e665addf6d7c6300670e8a89564ed12b5c1a21c336408e2835668f9a6a0d802\",\n" +
+ " \"tx_prove\": true,\n" +
+ " \"tx_timestamp\": 1574922644,\n" +
+ " \"viewkey\": \"f3ce66c9d395e5e460c8802b2c3c1fff04e508434f9738ee35558aac4678c906\"\n" +
+ " },\n" +
+ " \"status\": \"success\"\n" +
+ "} ";
+ }
+
+}
diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofParser.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofParser.java
index ae223d2269..dda5f924c8 100644
--- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofParser.java
+++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofParser.java
@@ -35,6 +35,8 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class XmrTxProofParser implements AssetTxProofParser {
+ public static final long MAX_DATE_TOLERANCE = TimeUnit.HOURS.toSeconds(2);
+
XmrTxProofParser() {
}
@@ -110,7 +112,7 @@ public class XmrTxProofParser implements AssetTxProofParser TimeUnit.HOURS.toSeconds(2) && !DevEnv.isDevMode()) {
+ if (difference > MAX_DATE_TOLERANCE && !DevEnv.isDevMode()) {
log.warn("tx_timestamp {}, tradeDate: {}, difference {}",
jsonTimestamp.getAsLong(), tradeDateSeconds, difference);
return XmrTxProofRequest.Result.FAILED.with(XmrTxProofRequest.Detail.TRADE_DATE_NOT_MATCHING);
diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequest.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequest.java
index f0b84d6060..c853af2410 100644
--- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequest.java
+++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequest.java
@@ -87,7 +87,6 @@ class XmrTxProofRequest implements AssetTxProofRequest
// Error states
CONNECTION_FAILURE,
- API_FAILURE,
API_INVALID,
// Failure states
@@ -194,8 +193,13 @@ class XmrTxProofRequest implements AssetTxProofRequest
"&txprove=1";
log.info("Param {} for {}", param, this);
String json = httpClient.requestWithGET(param, "User-Agent", "bisq/" + Version.VERSION);
- String prettyJson = new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(json));
- log.info("Response json from {}\n{}", this, prettyJson);
+ try {
+ String prettyJson = new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(json));
+ log.info("Response json from {}\n{}", this, prettyJson);
+ } catch (Throwable error) {
+ log.error("Pretty rint caused a {}}: raw josn={}", error, json);
+ }
+
Result result = parser.parse(model, json);
log.info("Result from {}\n{}", this, result);
return result;
diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/test/DevTestXmrTxProofHttpClient.java b/core/src/main/java/bisq/core/trade/txproof/xmr/test/DevTestXmrTxProofHttpClient.java
deleted file mode 100644
index 48de7c2750..0000000000
--- a/core/src/main/java/bisq/core/trade/txproof/xmr/test/DevTestXmrTxProofHttpClient.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is part of Bisq.
- *
- * Bisq is free software: you can redistribute it and/or modify it
- * under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * Bisq is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with Bisq. If not, see .
- */
-
-package bisq.core.trade.txproof.xmr.test;
-
-import bisq.core.trade.txproof.AssetTxProofHttpClient;
-
-import bisq.network.Socks5ProxyProvider;
-import bisq.network.http.HttpClientImpl;
-
-import javax.inject.Inject;
-
-import java.io.IOException;
-
-import lombok.extern.slf4j.Slf4j;
-
-import javax.annotation.Nullable;
-
-/**
- * This should help to test error scenarios in dev testing the app. This is additional to unit test which test the
- * correct data but do not test the context of the results and how it behaves in the UI.
- *
- * You have to change the binding in TradeModule to
- * bind(AssetTxProofHttpClient.class).to(DevTestXmrTxProofHttpClient.class); to use that class.
- *
- * This class can be removed once done testing, but as multiple devs are testing its useful to share it for now.
- */
-@Slf4j
-public class DevTestXmrTxProofHttpClient extends HttpClientImpl implements AssetTxProofHttpClient {
- enum TestCase {
- SUCCESS,
- INVALID_ADDRESS,
- STATUS_FAIL
- }
-
- @Inject
- public DevTestXmrTxProofHttpClient(@Nullable Socks5ProxyProvider socks5ProxyProvider) {
- super(socks5ProxyProvider);
- }
-
- @Override
- public String requestWithGET(String param,
- @Nullable String headerKey,
- @Nullable String headerValue) throws IOException {
- TestCase testCase = TestCase.SUCCESS;
- switch (testCase) {
- case SUCCESS:
- return validJson();
- case INVALID_ADDRESS:
- return validJson().replace("590f7263428051068bb45cdfcf93407c15b6e291d20c92d0251fcfbf53cc745cdf53319f7d6d7a8e21ea39041aabf31d220a32a875e3ca2087a777f1201c0571",
- "invalidAddress");
- case STATUS_FAIL:
- return validJson().replace("success",
- "fail");
- default:
- return testCase.toString();
- }
- }
-
- private String validJson() {
- return "{\n" +
- " \"data\": {\n" +
- " \"address\": \"590f7263428051068bb45cdfcf93407c15b6e291d20c92d0251fcfbf53cc745cdf53319f7d6d7a8e21ea39041aabf31d220a32a875e3ca2087a777f1201c0571\",\n" +
- " \"outputs\": [\n" +
- " {\n" +
- " \"amount\": 8902597360000,\n" +
- " \"match\": true,\n" +
- " \"output_idx\": 0,\n" +
- " \"output_pubkey\": \"2b6d2296f2591c198cd1aa47de9a5d74270963412ed30bbcc63b8eff29f0d43e\"\n" +
- " },\n" +
- " {\n" +
- " \"amount\": 0,\n" +
- " \"match\": false,\n" +
- " \"output_idx\": 1,\n" +
- " \"output_pubkey\": \"f53271624847507d80b746e91e689e88bc41678d55246275f5ad3c0f7e8a9ced\"\n" +
- " }\n" +
- " ],\n" +
- " \"tx_confirmations\": 201287,\n" +
- " \"tx_hash\": \"5e665addf6d7c6300670e8a89564ed12b5c1a21c336408e2835668f9a6a0d802\",\n" +
- " \"tx_prove\": true,\n" +
- " \"tx_timestamp\": 1574922644,\n" +
- " \"viewkey\": \"f3ce66c9d395e5e460c8802b2c3c1fff04e508434f9738ee35558aac4678c906\"\n" +
- " },\n" +
- " \"status\": \"success\"\n" +
- "} ";
- }
-
-}