diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java
index 5364de7f7d8..094007abd40 100644
--- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java
+++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java
@@ -28,5 +28,4 @@ protected final void verifyExpectedTradeStateAndPhase(TradeInfo trade,
assertEquals(expectedState.name(), trade.getState());
assertEquals(expectedPhase.name(), trade.getPhase());
}
-
}
diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java
index 040cee5a18d..4aba67fc715 100644
--- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java
+++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBTCOfferTest.java
@@ -31,6 +31,7 @@
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
+import static bisq.cli.TradeFormat.format;
import static bisq.core.trade.Trade.Phase.DEPOSIT_CONFIRMED;
import static bisq.core.trade.Trade.Phase.DEPOSIT_PUBLISHED;
import static bisq.core.trade.Trade.Phase.FIAT_SENT;
@@ -39,6 +40,7 @@
import static bisq.core.trade.Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN;
import static bisq.core.trade.Trade.State.SELLER_PUBLISHED_DEPOSIT_TX;
import static bisq.core.trade.Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG;
+import static java.lang.System.out;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
@@ -85,10 +87,12 @@ public void testTakeAlicesBuyOffer() {
trade = getTrade(bobdaemon, trade.getTradeId());
verifyExpectedTradeStateAndPhase(trade, SELLER_PUBLISHED_DEPOSIT_TX, DEPOSIT_PUBLISHED);
+ out.println(format(trade));
genBtcBlocksThenWait(1, 2250);
trade = getTrade(bobdaemon, trade.getTradeId());
verifyExpectedTradeStateAndPhase(trade, DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN, DEPOSIT_CONFIRMED);
+ out.println(format(trade));
} catch (StatusRuntimeException e) {
fail(e);
}
@@ -107,6 +111,7 @@ public void testAlicesConfirmPaymentStarted() {
trade = getTrade(alicedaemon, tradeId);
assertEquals(OFFER_FEE_PAID.name(), trade.getOffer().getState());
verifyExpectedTradeStateAndPhase(trade, BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG, FIAT_SENT);
+ out.println(format(trade));
} catch (StatusRuntimeException e) {
fail(e);
}
@@ -125,5 +130,6 @@ public void testBobsConfirmPaymentReceived() {
// TODO is this a bug? Why is offer.state == available?
assertEquals(AVAILABLE.name(), trade.getOffer().getState());
verifyExpectedTradeStateAndPhase(trade, SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG, PAYOUT_PUBLISHED);
+ out.println(format(trade));
}
}
diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java
index 5347159daae..658b4083231 100644
--- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java
+++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBTCOfferTest.java
@@ -31,6 +31,7 @@
import static bisq.apitest.config.BisqAppConfig.alicedaemon;
import static bisq.apitest.config.BisqAppConfig.bobdaemon;
+import static bisq.cli.TradeFormat.format;
import static bisq.core.trade.Trade.Phase.DEPOSIT_CONFIRMED;
import static bisq.core.trade.Trade.Phase.DEPOSIT_PUBLISHED;
import static bisq.core.trade.Trade.Phase.FIAT_SENT;
@@ -39,6 +40,7 @@
import static bisq.core.trade.Trade.State.BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG;
import static bisq.core.trade.Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN;
import static bisq.core.trade.Trade.State.SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG;
+import static java.lang.System.out;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
@@ -86,10 +88,12 @@ public void testTakeAlicesSellOffer() {
trade = getTrade(bobdaemon, trade.getTradeId());
verifyExpectedTradeStateAndPhase(trade, BUYER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG, DEPOSIT_PUBLISHED);
+ out.println(format(trade));
genBtcBlocksThenWait(1, 2250);
trade = getTrade(bobdaemon, trade.getTradeId());
verifyExpectedTradeStateAndPhase(trade, DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN, DEPOSIT_CONFIRMED);
+ out.println(format(trade));
} catch (StatusRuntimeException e) {
fail(e);
@@ -110,6 +114,8 @@ public void testBobsConfirmPaymentStarted() {
// TODO is this a bug? Why is offer.state == available?
assertEquals(AVAILABLE.name(), trade.getOffer().getState());
verifyExpectedTradeStateAndPhase(trade, BUYER_SAW_ARRIVED_FIAT_PAYMENT_INITIATED_MSG, FIAT_SENT);
+
+ out.println(format(trade));
} catch (StatusRuntimeException e) {
fail(e);
}
@@ -127,5 +133,6 @@ public void testAlicesConfirmPaymentReceived() {
trade = getTrade(alicedaemon, tradeId);
assertEquals(OFFER_FEE_PAID.name(), trade.getOffer().getState());
verifyExpectedTradeStateAndPhase(trade, SELLER_SAW_ARRIVED_PAYOUT_TX_PUBLISHED_MSG, PAYOUT_PUBLISHED);
+ out.println(format(trade));
}
}
diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java
index d8f66dabbef..f72fd26eb58 100644
--- a/cli/src/main/java/bisq/cli/CliMain.java
+++ b/cli/src/main/java/bisq/cli/CliMain.java
@@ -27,6 +27,7 @@
import bisq.proto.grpc.GetOfferRequest;
import bisq.proto.grpc.GetOffersRequest;
import bisq.proto.grpc.GetPaymentAccountsRequest;
+import bisq.proto.grpc.GetTradeRequest;
import bisq.proto.grpc.GetVersionRequest;
import bisq.proto.grpc.LockWalletRequest;
import bisq.proto.grpc.RegisterDisputeAgentRequest;
@@ -74,6 +75,7 @@ private enum Method {
getoffer,
getoffers,
takeoffer,
+ gettrade,
confirmpaymentstarted,
confirmpaymentreceived,
createpaymentacct,
@@ -275,6 +277,25 @@ public static void run(String[] args) {
out.printf("trade '%s' successfully taken", reply.getTrade().getShortId());
return;
}
+ case gettrade: {
+ if (nonOptionArgs.size() < 2)
+ throw new IllegalArgumentException("incorrect parameter count, expecting trade id, [,showcontract = true|false]");
+
+ var tradeId = nonOptionArgs.get(1);
+ var showContract = false;
+ if (nonOptionArgs.size() == 3)
+ showContract = Boolean.getBoolean(nonOptionArgs.get(2));
+
+ var request = GetTradeRequest.newBuilder()
+ .setTradeId(tradeId)
+ .build();
+ var reply = tradesService.getTrade(request);
+ if (showContract)
+ out.println(reply.getTrade().getContractAsJson());
+ else
+ out.println(TradeFormat.format(reply.getTrade()));
+ return;
+ }
case confirmpaymentstarted: {
if (nonOptionArgs.size() < 2)
throw new IllegalArgumentException("incorrect parameter count, expecting trade id");
@@ -427,6 +448,7 @@ private static void printHelp(OptionParser parser, PrintStream stream) {
stream.format(rowFormat, "getoffer", "offer id", "Get current offer with id");
stream.format(rowFormat, "getoffers", "buy | sell, currency code", "Get current offers");
stream.format(rowFormat, "takeoffer", "offer id", "Take offer with id");
+ stream.format(rowFormat, "gettrade", "trade id [,showcontract]", "Get trade summary or full contract");
stream.format(rowFormat, "confirmpaymentstarted", "trade id", "Confirm payment started");
stream.format(rowFormat, "confirmpaymentreceived", "trade id", "Confirm payment received");
stream.format(rowFormat, "createpaymentacct", "account name, account number, currency code", "Create PerfectMoney dummy account");
diff --git a/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java b/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java
new file mode 100644
index 00000000000..03500e4f47a
--- /dev/null
+++ b/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java
@@ -0,0 +1,55 @@
+/*
+ * 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.cli;
+
+import static com.google.common.base.Strings.padEnd;
+import static com.google.common.base.Strings.padStart;
+
+class ColumnHeaderConstants {
+
+ // For inserting 2 spaces between column headers.
+ static final String COL_HEADER_DELIMITER = " ";
+
+ // Table column header format specs, right padded with two spaces. In some cases
+ // such as COL_HEADER_CREATION_DATE, COL_HEADER_VOLUME and COL_HEADER_UUID, the
+ // expected max data string length is accounted for. In others, the column header length
+ // are expected to be greater than any column value length.
+ static final String COL_HEADER_ADDRESS = padEnd("Address", 34, ' ');
+ static final String COL_HEADER_AMOUNT = padEnd("BTC(min - max)", 24, ' ');
+ static final String COL_HEADER_BALANCE = padStart("Balance", 12, ' ');
+ static final String COL_HEADER_CONFIRMATIONS = "Confirmations";
+ static final String COL_HEADER_CREATION_DATE = padEnd("Creation Date (UTC)", 20, ' ');
+ static final String COL_HEADER_CURRENCY = "Currency";
+ static final String COL_HEADER_DIRECTION = "Buy/Sell";
+ static final String COL_HEADER_NAME = "Name";
+ static final String COL_HEADER_PAYMENT_METHOD = "Payment Method";
+ static final String COL_HEADER_PRICE = "Price in %-3s for 1 BTC";
+ static final String COL_HEADER_TRADE_AMOUNT = padStart("Amount(%-3s)", 12, ' ');
+ static final String COL_HEADER_TRADE_DEPOSIT_CONFIRMED = "Deposit Confirmed";
+ static final String COL_HEADER_TRADE_DEPOSIT_PUBLISHED = "Deposit Published";
+ static final String COL_HEADER_TRADE_FIAT_SENT = "Fiat Sent";
+ static final String COL_HEADER_TRADE_FIAT_RECEIVED = "Fiat Received";
+ static final String COL_HEADER_TRADE_PAYOUT_PUBLISHED = "Payout Published";
+ static final String COL_HEADER_TRADE_WITHDRAWN = "Withdrawn";
+ static final String COL_HEADER_TRADE_ROLE = "My Role";
+ static final String COL_HEADER_TRADE_SHORT_ID = "ID";
+ static final String COL_HEADER_TRADE_TX_FEE = "Tx Fee(%-3s)";
+ static final String COL_HEADER_TRADE_TAKER_FEE = "Taker Fee(%-3s)";
+ static final String COL_HEADER_VOLUME = padEnd("%-3s(min - max)", 15, ' ');
+ static final String COL_HEADER_UUID = padEnd("ID", 52, ' ');
+}
diff --git a/cli/src/main/java/bisq/cli/TableFormat.java b/cli/src/main/java/bisq/cli/TableFormat.java
index 7d02af562f5..e9868f336e4 100644
--- a/cli/src/main/java/bisq/cli/TableFormat.java
+++ b/cli/src/main/java/bisq/cli/TableFormat.java
@@ -29,12 +29,12 @@
import java.util.TimeZone;
import java.util.stream.Collectors;
+import static bisq.cli.ColumnHeaderConstants.*;
import static bisq.cli.CurrencyFormat.formatAmountRange;
import static bisq.cli.CurrencyFormat.formatOfferPrice;
import static bisq.cli.CurrencyFormat.formatSatoshis;
import static bisq.cli.CurrencyFormat.formatVolumeRange;
import static com.google.common.base.Strings.padEnd;
-import static com.google.common.base.Strings.padStart;
import static java.lang.String.format;
import static java.util.Collections.max;
import static java.util.Comparator.comparing;
@@ -42,28 +42,8 @@
class TableFormat {
- private static final TimeZone TZ_UTC = getTimeZone("UTC");
- private static final SimpleDateFormat DATE_FORMAT_ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
-
- // For inserting 2 spaces between column headers.
- private static final String COL_HEADER_DELIMITER = " ";
-
- // Table column header format specs, right padded with two spaces. In some cases
- // such as COL_HEADER_CREATION_DATE, COL_HEADER_VOLUME and COL_HEADER_UUID, the
- // expected max data string length is accounted for. In others, the column header length
- // are expected to be greater than any column value length.
- private static final String COL_HEADER_ADDRESS = padEnd("Address", 34, ' ');
- private static final String COL_HEADER_AMOUNT = padEnd("BTC(min - max)", 24, ' ');
- private static final String COL_HEADER_BALANCE = padStart("Balance", 12, ' ');
- private static final String COL_HEADER_CONFIRMATIONS = "Confirmations";
- private static final String COL_HEADER_CREATION_DATE = padEnd("Creation Date (UTC)", 20, ' ');
- private static final String COL_HEADER_CURRENCY = "Currency";
- private static final String COL_HEADER_DIRECTION = "Buy/Sell"; // TODO "Take Offer to
- private static final String COL_HEADER_NAME = "Name";
- private static final String COL_HEADER_PAYMENT_METHOD = "Payment Method";
- private static final String COL_HEADER_PRICE = "Price in %-3s for 1 BTC";
- private static final String COL_HEADER_VOLUME = padEnd("%-3s(min - max)", 15, ' ');
- private static final String COL_HEADER_UUID = padEnd("ID", 52, ' ');
+ static final TimeZone TZ_UTC = getTimeZone("UTC");
+ static final SimpleDateFormat DATE_FORMAT_ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static String formatAddressBalanceTbl(List addressBalanceInfo) {
String headerLine = (COL_HEADER_ADDRESS + COL_HEADER_DELIMITER
diff --git a/cli/src/main/java/bisq/cli/TradeFormat.java b/cli/src/main/java/bisq/cli/TradeFormat.java
new file mode 100644
index 00000000000..ab9075fe341
--- /dev/null
+++ b/cli/src/main/java/bisq/cli/TradeFormat.java
@@ -0,0 +1,118 @@
+/*
+ * 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.cli;
+
+import bisq.proto.grpc.TradeInfo;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.function.Supplier;
+
+import static bisq.cli.ColumnHeaderConstants.*;
+import static bisq.cli.CurrencyFormat.formatOfferPrice;
+import static bisq.cli.CurrencyFormat.formatSatoshis;
+import static com.google.common.base.Strings.padEnd;
+
+@VisibleForTesting
+public class TradeFormat {
+
+ @VisibleForTesting
+ public static String format(TradeInfo tradeInfo) {
+ // Some column values might be longer than header, so we need to calculated them.
+ int shortIdColWidth = Math.max(COL_HEADER_TRADE_SHORT_ID.length(), tradeInfo.getShortId().length());
+ int roleColWidth = Math.max(COL_HEADER_TRADE_ROLE.length(), tradeInfo.getRole().length());
+
+ // We only show taker fee under its header when user is the taker.
+ boolean isTaker = tradeInfo.getRole().toLowerCase().contains("taker");
+ Supplier takerFeeHeaderFormat = () -> isTaker ?
+ padEnd(COL_HEADER_TRADE_TAKER_FEE, 12, ' ') + COL_HEADER_DELIMITER
+ : "";
+ Supplier takerFeeHeader = () -> isTaker ?
+ "%" + (COL_HEADER_TRADE_TAKER_FEE.length() + 1) + "s"
+ : "";
+
+ String headersFormat = padEnd(COL_HEADER_TRADE_SHORT_ID, shortIdColWidth, ' ') + COL_HEADER_DELIMITER
+ + padEnd(COL_HEADER_TRADE_ROLE, roleColWidth, ' ') + COL_HEADER_DELIMITER
+ + COL_HEADER_PRICE + COL_HEADER_DELIMITER // includes %s -> currencyCode
+ + padEnd(COL_HEADER_TRADE_AMOUNT, 12, ' ') + COL_HEADER_DELIMITER
+ + padEnd(COL_HEADER_TRADE_TX_FEE, 12, ' ') + COL_HEADER_DELIMITER
+ + takerFeeHeaderFormat.get()
+ + COL_HEADER_TRADE_DEPOSIT_PUBLISHED + COL_HEADER_DELIMITER
+ + COL_HEADER_TRADE_DEPOSIT_CONFIRMED + COL_HEADER_DELIMITER
+ + COL_HEADER_TRADE_FIAT_SENT + COL_HEADER_DELIMITER
+ + COL_HEADER_TRADE_FIAT_RECEIVED + COL_HEADER_DELIMITER
+ + COL_HEADER_TRADE_PAYOUT_PUBLISHED + COL_HEADER_DELIMITER
+ + COL_HEADER_TRADE_WITHDRAWN + COL_HEADER_DELIMITER
+ + "%n";
+
+ String counterCurrencyCode = tradeInfo.getOffer().getCounterCurrencyCode();
+ String baseCurrencyCode = tradeInfo.getOffer().getBaseCurrencyCode();
+ String headerLine = isTaker
+ ? String.format(headersFormat, counterCurrencyCode, baseCurrencyCode, baseCurrencyCode, baseCurrencyCode)
+ : String.format(headersFormat, counterCurrencyCode, baseCurrencyCode, baseCurrencyCode);
+
+ String colDataFormat = "%-" + shortIdColWidth + "s" // left justify
+ + " %-" + (roleColWidth + COL_HEADER_DELIMITER.length()) + "s" // left justify
+ + "%" + (COL_HEADER_PRICE.length() - 1) + "s" // right justify
+ + "%" + (COL_HEADER_TRADE_AMOUNT.length() + 1) + "s" // right justify
+ + "%" + (COL_HEADER_TRADE_TX_FEE.length() + 1) + "s" // right justify
+ + takerFeeHeader.get() // right justify
+ + " %-" + COL_HEADER_TRADE_DEPOSIT_PUBLISHED.length() + "s" // left justify
+ + " %-" + COL_HEADER_TRADE_DEPOSIT_CONFIRMED.length() + "s" // left justify
+ + " %-" + COL_HEADER_TRADE_FIAT_SENT.length() + "s" // left justify
+ + " %-" + COL_HEADER_TRADE_FIAT_RECEIVED.length() + "s" // left justify
+ + " %-" + COL_HEADER_TRADE_PAYOUT_PUBLISHED.length() + "s" // left justify
+ + " %-" + COL_HEADER_TRADE_WITHDRAWN.length() + "s"; // left justify
+
+ return headerLine +
+ (isTaker
+ ? formatTradeForTaker(colDataFormat, tradeInfo)
+ : formatTradeForMaker(colDataFormat, tradeInfo));
+ }
+
+ private static String formatTradeForMaker(String format, TradeInfo tradeInfo) {
+ return String.format(format,
+ tradeInfo.getShortId(),
+ tradeInfo.getRole(),
+ formatOfferPrice(tradeInfo.getTradePrice()),
+ formatSatoshis(tradeInfo.getTradeAmountAsLong()),
+ formatSatoshis(tradeInfo.getTxFeeAsLong()),
+ tradeInfo.getIsDepositPublished() ? "YES" : "NO",
+ tradeInfo.getIsDepositConfirmed() ? "YES" : "NO",
+ tradeInfo.getIsFiatSent() ? "YES" : "NO",
+ tradeInfo.getIsFiatReceived() ? "YES" : "NO",
+ tradeInfo.getIsPayoutPublished() ? "YES" : "NO",
+ tradeInfo.getIsWithdrawn() ? "YES" : "NO");
+ }
+
+ private static String formatTradeForTaker(String format, TradeInfo tradeInfo) {
+ return String.format(format,
+ tradeInfo.getShortId(),
+ tradeInfo.getRole(),
+ formatOfferPrice(tradeInfo.getTradePrice()),
+ formatSatoshis(tradeInfo.getTradeAmountAsLong()),
+ formatSatoshis(tradeInfo.getTxFeeAsLong()),
+ formatSatoshis(tradeInfo.getTakerFeeAsLong()),
+ tradeInfo.getIsDepositPublished() ? "YES" : "NO",
+ tradeInfo.getIsDepositConfirmed() ? "YES" : "NO",
+ tradeInfo.getIsFiatSent() ? "YES" : "NO",
+ tradeInfo.getIsFiatReceived() ? "YES" : "NO",
+ tradeInfo.getIsPayoutPublished() ? "YES" : "NO",
+ tradeInfo.getIsWithdrawn() ? "YES" : "NO");
+ }
+}
diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java
index 01f70d312f4..05886dd6e9e 100644
--- a/core/src/main/java/bisq/core/api/CoreApi.java
+++ b/core/src/main/java/bisq/core/api/CoreApi.java
@@ -193,6 +193,10 @@ public Trade getTrade(String tradeId) {
return coreTradesService.getTrade(tradeId);
}
+ public String getTradeRole(String tradeId) {
+ return coreTradesService.getTradeRole(tradeId);
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////
// Wallets
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java
index d0200a78ce5..85877488315 100644
--- a/core/src/main/java/bisq/core/api/CoreTradesService.java
+++ b/core/src/main/java/bisq/core/api/CoreTradesService.java
@@ -21,6 +21,7 @@
import bisq.core.offer.takeoffer.TakeOfferModel;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
+import bisq.core.trade.TradeUtil;
import bisq.core.trade.protocol.BuyerProtocol;
import bisq.core.trade.protocol.SellerProtocol;
import bisq.core.user.User;
@@ -38,14 +39,17 @@ class CoreTradesService {
private final TakeOfferModel takeOfferModel;
private final TradeManager tradeManager;
+ private final TradeUtil tradeUtil;
private final User user;
@Inject
public CoreTradesService(TakeOfferModel takeOfferModel,
TradeManager tradeManager,
+ TradeUtil tradeUtil,
User user) {
this.takeOfferModel = takeOfferModel;
this.tradeManager = tradeManager;
+ this.tradeUtil = tradeUtil;
this.user = user;
}
@@ -57,6 +61,7 @@ void takeOffer(Offer offer,
throw new IllegalArgumentException(format("payment account with id '%s' not found", paymentAccountId));
var useSavingsWallet = true;
+ //noinspection ConstantConditions
takeOfferModel.initModel(offer, paymentAccount, useSavingsWallet);
log.info("Initiating take {} offer, {}",
offer.isBuyOffer() ? "buy" : "sell",
@@ -111,6 +116,10 @@ void confirmPaymentReceived(String tradeId) {
}
}
+ String getTradeRole(String tradeId) {
+ return tradeUtil.getRole(getTrade(tradeId));
+ }
+
Trade getTrade(String tradeId) {
return tradeManager.getTradeById(tradeId).orElseThrow(() ->
new IllegalArgumentException(format("trade with id '%s' not found", tradeId)));
diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java
index ad2389e438a..219045b2762 100644
--- a/core/src/main/java/bisq/core/api/model/OfferInfo.java
+++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java
@@ -125,13 +125,9 @@ public bisq.proto.grpc.OfferInfo toProtoMessage() {
.build();
}
+ @SuppressWarnings({"unused", "SameReturnValue"})
public static OfferInfo fromProto(bisq.proto.grpc.OfferInfo proto) {
- /*
- TODO?
- return new OfferInfo(proto.getOfferPayload().getId(),
- proto.getOfferPayload().getDate());
- */
- return null;
+ return null; // TODO
}
/*
diff --git a/core/src/main/java/bisq/core/api/model/TradeInfo.java b/core/src/main/java/bisq/core/api/model/TradeInfo.java
index 33b8059f9b5..1a717a7672e 100644
--- a/core/src/main/java/bisq/core/api/model/TradeInfo.java
+++ b/core/src/main/java/bisq/core/api/model/TradeInfo.java
@@ -21,6 +21,8 @@
import bisq.common.Payload;
+import java.util.Objects;
+
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -37,6 +39,17 @@ public class TradeInfo implements Payload {
private final OfferInfo offer;
private final String tradeId;
private final String shortId;
+ private final long date;
+ private final String role;
+ private final boolean isCurrencyForTakerFeeBtc;
+ private final long txFeeAsLong;
+ private final long takerFeeAsLong;
+ private final String takerFeeTxId;
+ private final String depositTxId;
+ private final String payoutTxId;
+ private final long tradeAmountAsLong;
+ private final long tradePrice;
+ private final String tradingPeerNodeAddress;
private final String state;
private final String phase;
private final String tradePeriodState;
@@ -46,11 +59,23 @@ public class TradeInfo implements Payload {
private final boolean isFiatReceived;
private final boolean isPayoutPublished;
private final boolean isWithdrawn;
+ private final String contractAsJson;
public TradeInfo(TradeInfoBuilder builder) {
this.offer = builder.offer;
this.tradeId = builder.tradeId;
this.shortId = builder.shortId;
+ this.date = builder.date;
+ this.role = builder.role;
+ this.isCurrencyForTakerFeeBtc = builder.isCurrencyForTakerFeeBtc;
+ this.txFeeAsLong = builder.txFeeAsLong;
+ this.takerFeeAsLong = builder.takerFeeAsLong;
+ this.takerFeeTxId = builder.takerFeeTxId;
+ this.depositTxId = builder.depositTxId;
+ this.payoutTxId = builder.payoutTxId;
+ this.tradeAmountAsLong = builder.tradeAmountAsLong;
+ this.tradePrice = builder.tradePrice;
+ this.tradingPeerNodeAddress = builder.tradingPeerNodeAddress;
this.state = builder.state;
this.phase = builder.phase;
this.tradePeriodState = builder.tradePeriodState;
@@ -60,13 +85,31 @@ public TradeInfo(TradeInfoBuilder builder) {
this.isFiatReceived = builder.isFiatReceived;
this.isPayoutPublished = builder.isPayoutPublished;
this.isWithdrawn = builder.isWithdrawn;
+ this.contractAsJson = builder.contractAsJson;
}
public static TradeInfo toTradeInfo(Trade trade) {
+ return toTradeInfo(trade, null);
+ }
+
+ public static TradeInfo toTradeInfo(Trade trade, String role) {
return new TradeInfo.TradeInfoBuilder()
.withOffer(toOfferInfo(trade.getOffer()))
.withTradeId(trade.getId())
.withShortId(trade.getShortId())
+ .withDate(trade.getDate().getTime())
+ .withRole(role == null ? "" : role)
+ .withIsCurrencyForTakerFeeBtc(trade.isCurrencyForTakerFeeBtc())
+ .withTxFeeAsLong(trade.getTxFeeAsLong())
+ .withTakerFeeAsLong(trade.getTakerFeeAsLong())
+ .withTakerFeeAsLong(trade.getTakerFeeAsLong())
+ .withTakerFeeTxId(trade.getTakerFeeTxId())
+ .withDepositTxId(trade.getDepositTxId())
+ .withPayoutTxId(trade.getPayoutTxId())
+ .withTradeAmountAsLong(trade.getTradeAmountAsLong())
+ .withTradePrice(trade.getTradePrice().getValue())
+ .withTradingPeerNodeAddress(Objects.requireNonNull(
+ trade.getTradingPeerNodeAddress()).getHostNameWithoutPostFix())
.withState(trade.getState().name())
.withPhase(trade.getPhase().name())
.withTradePeriodState(trade.getTradePeriodState().name())
@@ -76,6 +119,7 @@ public static TradeInfo toTradeInfo(Trade trade) {
.withIsFiatReceived(trade.isFiatReceived())
.withIsPayoutPublished(trade.isPayoutPublished())
.withIsWithdrawn(trade.isWithdrawn())
+ .withContractAsJson(trade.getContractAsJson())
.build();
}
@@ -89,6 +133,17 @@ public bisq.proto.grpc.TradeInfo toProtoMessage() {
.setOffer(offer.toProtoMessage())
.setTradeId(tradeId)
.setShortId(shortId)
+ .setDate(date)
+ .setRole(role)
+ .setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc)
+ .setTxFeeAsLong(txFeeAsLong)
+ .setTakerFeeAsLong(takerFeeAsLong)
+ .setTakerFeeTxId(takerFeeTxId == null ? "" : takerFeeTxId)
+ .setDepositTxId(depositTxId == null ? "" : depositTxId)
+ .setPayoutTxId(payoutTxId == null ? "" : payoutTxId)
+ .setTradeAmountAsLong(tradeAmountAsLong)
+ .setTradePrice(tradePrice)
+ .setTradingPeerNodeAddress(tradingPeerNodeAddress)
.setState(state)
.setPhase(phase)
.setTradePeriodState(tradePeriodState)
@@ -98,12 +153,13 @@ public bisq.proto.grpc.TradeInfo toProtoMessage() {
.setIsFiatReceived(isFiatReceived)
.setIsPayoutPublished(isPayoutPublished)
.setIsWithdrawn(isWithdrawn)
+ .setContractAsJson(contractAsJson == null ? "" : contractAsJson)
.build();
}
+ @SuppressWarnings({"unused", "SameReturnValue"})
public static TradeInfo fromProto(bisq.proto.grpc.TradeInfo proto) {
- // TODO
- return null;
+ return null; // TODO
}
/*
@@ -116,6 +172,17 @@ public static class TradeInfoBuilder {
private OfferInfo offer;
private String tradeId;
private String shortId;
+ private long date;
+ private String role;
+ private boolean isCurrencyForTakerFeeBtc;
+ private long txFeeAsLong;
+ private long takerFeeAsLong;
+ private String takerFeeTxId;
+ private String depositTxId;
+ private String payoutTxId;
+ private long tradeAmountAsLong;
+ private long tradePrice;
+ private String tradingPeerNodeAddress;
private String state;
private String phase;
private String tradePeriodState;
@@ -125,6 +192,7 @@ public static class TradeInfoBuilder {
private boolean isFiatReceived;
private boolean isPayoutPublished;
private boolean isWithdrawn;
+ private String contractAsJson;
public TradeInfoBuilder withOffer(OfferInfo offer) {
this.offer = offer;
@@ -141,6 +209,61 @@ public TradeInfoBuilder withShortId(String shortId) {
return this;
}
+ public TradeInfoBuilder withDate(long date) {
+ this.date = date;
+ return this;
+ }
+
+ public TradeInfoBuilder withRole(String role) {
+ this.role = role;
+ return this;
+ }
+
+ public TradeInfoBuilder withIsCurrencyForTakerFeeBtc(boolean isCurrencyForTakerFeeBtc) {
+ this.isCurrencyForTakerFeeBtc = isCurrencyForTakerFeeBtc;
+ return this;
+ }
+
+ public TradeInfoBuilder withTxFeeAsLong(long txFeeAsLong) {
+ this.txFeeAsLong = txFeeAsLong;
+ return this;
+ }
+
+ public TradeInfoBuilder withTakerFeeAsLong(long takerFeeAsLong) {
+ this.takerFeeAsLong = takerFeeAsLong;
+ return this;
+ }
+
+ public TradeInfoBuilder withTakerFeeTxId(String takerFeeTxId) {
+ this.takerFeeTxId = takerFeeTxId;
+ return this;
+ }
+
+ public TradeInfoBuilder withDepositTxId(String depositTxId) {
+ this.depositTxId = depositTxId;
+ return this;
+ }
+
+ public TradeInfoBuilder withPayoutTxId(String payoutTxId) {
+ this.payoutTxId = payoutTxId;
+ return this;
+ }
+
+ public TradeInfoBuilder withTradeAmountAsLong(long tradeAmountAsLong) {
+ this.tradeAmountAsLong = tradeAmountAsLong;
+ return this;
+ }
+
+ public TradeInfoBuilder withTradePrice(long tradePrice) {
+ this.tradePrice = tradePrice;
+ return this;
+ }
+
+ public TradeInfoBuilder withTradePeriodState(String tradePeriodState) {
+ this.tradePeriodState = tradePeriodState;
+ return this;
+ }
+
public TradeInfoBuilder withState(String state) {
this.state = state;
return this;
@@ -151,8 +274,8 @@ public TradeInfoBuilder withPhase(String phase) {
return this;
}
- public TradeInfoBuilder withTradePeriodState(String tradePeriodState) {
- this.tradePeriodState = tradePeriodState;
+ public TradeInfoBuilder withTradingPeerNodeAddress(String tradingPeerNodeAddress) {
+ this.tradingPeerNodeAddress = tradingPeerNodeAddress;
return this;
}
@@ -186,6 +309,11 @@ public TradeInfoBuilder withIsWithdrawn(boolean isWithdrawn) {
return this;
}
+ public TradeInfoBuilder withContractAsJson(String contractAsJson) {
+ this.contractAsJson = contractAsJson;
+ return this;
+ }
+
public TradeInfo build() {
return new TradeInfo(this);
}
@@ -196,6 +324,17 @@ public String toString() {
return "TradeInfo{" +
" tradeId='" + tradeId + '\'' + "\n" +
", shortId='" + shortId + '\'' + "\n" +
+ ", date='" + date + '\'' + "\n" +
+ ", role='" + role + '\'' + "\n" +
+ ", isCurrencyForTakerFeeBtc='" + isCurrencyForTakerFeeBtc + '\'' + "\n" +
+ ", txFeeAsLong='" + txFeeAsLong + '\'' + "\n" +
+ ", takerFeeAsLong='" + takerFeeAsLong + '\'' + "\n" +
+ ", takerFeeTxId='" + takerFeeTxId + '\'' + "\n" +
+ ", depositTxId='" + depositTxId + '\'' + "\n" +
+ ", payoutTxId='" + payoutTxId + '\'' + "\n" +
+ ", tradeAmountAsLong='" + tradeAmountAsLong + '\'' + "\n" +
+ ", tradePrice='" + tradePrice + '\'' + "\n" +
+ ", tradingPeerNodeAddress='" + tradingPeerNodeAddress + '\'' + "\n" +
", state='" + state + '\'' + "\n" +
", phase='" + phase + '\'' + "\n" +
", tradePeriodState='" + tradePeriodState + '\'' + "\n" +
@@ -206,6 +345,7 @@ public String toString() {
", isPayoutPublished=" + isPayoutPublished + "\n" +
", isWithdrawn=" + isWithdrawn + "\n" +
", offer=" + offer + "\n" +
+ ", contractAsJson=" + contractAsJson + "\n" +
'}';
}
}
diff --git a/core/src/main/java/bisq/core/offer/OfferUtil.java b/core/src/main/java/bisq/core/offer/OfferUtil.java
index 373df679073..84e783f5b14 100644
--- a/core/src/main/java/bisq/core/offer/OfferUtil.java
+++ b/core/src/main/java/bisq/core/offer/OfferUtil.java
@@ -261,6 +261,10 @@ public boolean isBsqForTakerFeeAvailable(@Nullable Coin amount) {
return !availableBalance.subtract(takerFee).isNegative();
}
+ public boolean isBlockChainPaymentMethod(Offer offer) {
+ return offer != null && offer.getPaymentMethod().isAsset();
+ }
+
public Optional getFeeInUserFiatCurrency(Coin makerFee,
boolean isCurrencyForMakerFeeBtc,
CoinFormatter bsqFormatter) {
diff --git a/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java b/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java
index efd0523ec19..c48b3c8ad4c 100644
--- a/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java
+++ b/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java
@@ -1,3 +1,20 @@
+/*
+ * 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.offer.takeoffer;
import bisq.core.account.witness.AccountAgeWitnessService;
@@ -20,6 +37,8 @@
import javax.inject.Inject;
import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -141,12 +160,19 @@ private void calculateTxFees() {
// Payout tx: 371 bytes
// Disputed payout tx: 408 bytes
- // Request actual fees:
- log.info("Start requestTxFee: txFeeFromFeeService={}", txFeeFromFeeService);
- feeService.requestFees(() -> {
- txFeePerByteFromFeeService = feeService.getTxFeePerByte();
- txFeeFromFeeService = offerUtil.getTxFeeBySize(txFeePerByteFromFeeService, feeTxSize);
- });
+ txFeePerByteFromFeeService = getTxFeePerByte();
+ txFeeFromFeeService = offerUtil.getTxFeeBySize(txFeePerByteFromFeeService, feeTxSize);
+ log.info("{} txFeePerByte = {}", feeService.getClass().getSimpleName(), txFeePerByteFromFeeService);
+ }
+
+ private Coin getTxFeePerByte() {
+ try {
+ CompletableFuture feeRequestFuture = CompletableFuture.runAsync(feeService::requestFees);
+ feeRequestFuture.get(); // Block until async fee request is complete.
+ return feeService.getTxFeePerByte();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new IllegalStateException("Could not request fees from fee service.", e);
+ }
}
private void calculateTotalToPay() {
diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java
index 0d8d02a2414..d8278018d56 100644
--- a/core/src/main/java/bisq/core/trade/TradeManager.java
+++ b/core/src/main/java/bisq/core/trade/TradeManager.java
@@ -120,6 +120,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
private final P2PService p2PService;
private final PriceFeedService priceFeedService;
private final TradeStatisticsManager tradeStatisticsManager;
+ private final TradeUtil tradeUtil;
@Getter
private final ArbitratorManager arbitratorManager;
private final MediatorManager mediatorManager;
@@ -157,6 +158,7 @@ public TradeManager(User user,
P2PService p2PService,
PriceFeedService priceFeedService,
TradeStatisticsManager tradeStatisticsManager,
+ TradeUtil tradeUtil,
ArbitratorManager arbitratorManager,
MediatorManager mediatorManager,
ProcessModelServiceProvider processModelServiceProvider,
@@ -175,6 +177,7 @@ public TradeManager(User user,
this.p2PService = p2PService;
this.priceFeedService = priceFeedService;
this.tradeStatisticsManager = tradeStatisticsManager;
+ this.tradeUtil = tradeUtil;
this.arbitratorManager = arbitratorManager;
this.mediatorManager = mediatorManager;
this.processModelServiceProvider = processModelServiceProvider;
@@ -634,7 +637,7 @@ private boolean unFailTrade(Trade trade) {
// the relevant entries are changed, otherwise it's not added and no address entries are changed
private boolean recoverAddresses(Trade trade) {
// Find addresses associated with this trade.
- var entries = TradeUtils.getAvailableAddresses(trade, btcWalletService, keyRing);
+ var entries = tradeUtil.getAvailableAddresses(trade);
if (entries == null)
return false;
diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java
new file mode 100644
index 00000000000..cd4fd074aad
--- /dev/null
+++ b/core/src/main/java/bisq/core/trade/TradeUtil.java
@@ -0,0 +1,228 @@
+/*
+ * 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;
+
+import bisq.core.btc.wallet.BtcWalletService;
+import bisq.core.locale.Res;
+import bisq.core.offer.Offer;
+
+import bisq.common.crypto.KeyRing;
+import bisq.common.util.Tuple2;
+import bisq.common.util.Utilities;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import java.util.Date;
+import java.util.Objects;
+
+import lombok.extern.slf4j.Slf4j;
+
+import javax.annotation.Nullable;
+
+import static bisq.core.locale.CurrencyUtil.getCurrencyPair;
+import static bisq.core.locale.CurrencyUtil.isFiatCurrency;
+import static bisq.core.util.FormattingUtils.formatDurationAsWords;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
+
+/**
+ * This class contains trade utility methods.
+ */
+@Slf4j
+@Singleton
+public class TradeUtil {
+
+ private final BtcWalletService btcWalletService;
+ private final KeyRing keyRing;
+
+ @Inject
+ public TradeUtil(BtcWalletService btcWalletService, KeyRing keyRing) {
+ this.btcWalletService = btcWalletService;
+ this.keyRing = keyRing;
+ }
+
+ /**
+ * Returns if and only if both are AVAILABLE,
+ * otherwise null.
+ * @param trade the trade being queried for MULTI_SIG, TRADE_PAYOUT addresses
+ * @return Tuple2 tuple containing MULTI_SIG, TRADE_PAYOUT addresses for trade
+ */
+ public Tuple2 getAvailableAddresses(Trade trade) {
+ var addresses = getTradeAddresses(trade);
+ if (addresses == null)
+ return null;
+
+ if (btcWalletService.getAvailableAddressEntries().stream()
+ .noneMatch(e -> Objects.equals(e.getAddressString(), addresses.first)))
+ return null;
+
+ if (btcWalletService.getAvailableAddressEntries().stream()
+ .noneMatch(e -> Objects.equals(e.getAddressString(), addresses.second)))
+ return null;
+
+ return new Tuple2<>(addresses.first, addresses.second);
+ }
+
+ /**
+ * Returns addresses as strings if they're known by the
+ * wallet.
+ * @param trade the trade being queried for MULTI_SIG, TRADE_PAYOUT addresses
+ * @return Tuple2 tuple containing MULTI_SIG, TRADE_PAYOUT addresses for trade
+ */
+ public Tuple2 getTradeAddresses(Trade trade) {
+ var contract = trade.getContract();
+ if (contract == null)
+ return null;
+
+ // Get multisig address
+ var isMyRoleBuyer = contract.isMyRoleBuyer(keyRing.getPubKeyRing());
+ var multiSigPubKey = isMyRoleBuyer
+ ? contract.getBuyerMultiSigPubKey()
+ : contract.getSellerMultiSigPubKey();
+ if (multiSigPubKey == null)
+ return null;
+
+ var multiSigPubKeyString = Utilities.bytesAsHexString(multiSigPubKey);
+ var multiSigAddress = btcWalletService.getAddressEntryListAsImmutableList().stream()
+ .filter(e -> e.getKeyPair().getPublicKeyAsHex().equals(multiSigPubKeyString))
+ .findAny()
+ .orElse(null);
+ if (multiSigAddress == null)
+ return null;
+
+ // Get payout address
+ var payoutAddress = isMyRoleBuyer
+ ? contract.getBuyerPayoutAddressString()
+ : contract.getSellerPayoutAddressString();
+ var payoutAddressEntry = btcWalletService.getAddressEntryListAsImmutableList().stream()
+ .filter(e -> Objects.equals(e.getAddressString(), payoutAddress))
+ .findAny()
+ .orElse(null);
+ if (payoutAddressEntry == null)
+ return null;
+
+ return new Tuple2<>(multiSigAddress.getAddressString(), payoutAddress);
+ }
+
+ public long getRemainingTradeDuration(Trade trade) {
+ return trade.getMaxTradePeriodDate() != null
+ ? trade.getMaxTradePeriodDate().getTime() - new Date().getTime()
+ : getMaxTradePeriod(trade);
+ }
+
+ public long getMaxTradePeriod(Trade trade) {
+ return trade.getOffer() != null
+ ? trade.getOffer().getPaymentMethod().getMaxTradePeriod()
+ : 0;
+ }
+
+ public double getRemainingTradeDurationAsPercentage(Trade trade) {
+ long maxPeriod = getMaxTradePeriod(trade);
+ long remaining = getRemainingTradeDuration(trade);
+ if (maxPeriod != 0) {
+ return 1 - (double) remaining / (double) maxPeriod;
+ } else
+ return 0;
+ }
+
+ public String getRemainingTradeDurationAsWords(Trade trade) {
+ return formatDurationAsWords(Math.max(0, getRemainingTradeDuration(trade)));
+ }
+
+ @Nullable
+ public Date getHalfTradePeriodDate(Trade trade) {
+ return trade != null ? trade.getHalfTradePeriodDate() : null;
+ }
+
+ public Date getDateForOpenDispute(Trade trade) {
+ return new Date(new Date().getTime() + getRemainingTradeDuration(trade));
+ }
+
+ public String getMarketDescription(Trade trade) {
+ if (trade == null)
+ return "";
+
+ checkNotNull(trade.getOffer());
+ checkNotNull(trade.getOffer().getCurrencyCode());
+ return getCurrencyPair(trade.getOffer().getCurrencyCode());
+ }
+
+ public String getPaymentMethodNameWithCountryCode(Trade trade) {
+ String paymentMethodDescription = "";
+ if (trade != null) {
+ Offer offer = trade.getOffer();
+ checkNotNull(offer);
+ checkNotNull(offer.getPaymentMethod());
+ paymentMethodDescription = offer.getPaymentMethodNameWithCountryCode();
+ }
+ return paymentMethodDescription;
+ }
+
+ /**
+ * Returns a string describing a trader's role for a given trade.
+ * @param trade Trade
+ * @return String describing a trader's role for a given trade
+ */
+ public String getRole(Trade trade) {
+ Contract contract = trade.getContract();
+ if (contract == null)
+ throw new IllegalStateException(format("could not get role because no contract was found for trade '%s'",
+ trade.getShortId()));
+
+ Offer offer = trade.getOffer();
+ if (offer == null)
+ throw new IllegalStateException(format("could not get role because no offer was found for trade '%s'",
+ trade.getShortId()));
+
+ return getRole(contract.isBuyerMakerAndSellerTaker(),
+ offer.isMyOffer(keyRing),
+ offer.getCurrencyCode());
+ }
+
+ /**
+ * Returns a string describing a trader's role.
+ *
+ * @param isBuyerMakerAndSellerTaker boolean
+ * @param isMaker boolean
+ * @param currencyCode String
+ * @return String describing a trader's role
+ */
+ public String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) {
+ if (isFiatCurrency(currencyCode)) {
+ String baseCurrencyCode = Res.getBaseCurrencyCode();
+ if (isBuyerMakerAndSellerTaker)
+ return isMaker
+ ? Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.buyer"))
+ : Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.seller"));
+ else
+ return isMaker
+ ? Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.seller"))
+ : Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.buyer"));
+ } else {
+ if (isBuyerMakerAndSellerTaker)
+ return isMaker
+ ? Res.get("formatter.asMaker", currencyCode, Res.get("shared.seller"))
+ : Res.get("formatter.asTaker", currencyCode, Res.get("shared.buyer"));
+ else
+ return isMaker
+ ? Res.get("formatter.asMaker", currencyCode, Res.get("shared.buyer"))
+ : Res.get("formatter.asTaker", currencyCode, Res.get("shared.seller"));
+ }
+ }
+}
diff --git a/core/src/main/java/bisq/core/trade/TradeUtils.java b/core/src/main/java/bisq/core/trade/TradeUtils.java
deleted file mode 100644
index 10a5da8fdf8..00000000000
--- a/core/src/main/java/bisq/core/trade/TradeUtils.java
+++ /dev/null
@@ -1,79 +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;
-
-import bisq.core.btc.wallet.BtcWalletService;
-
-import bisq.common.crypto.KeyRing;
-import bisq.common.util.Tuple2;
-import bisq.common.util.Utilities;
-
-import java.util.Objects;
-
-public class TradeUtils {
-
- // Returns if both are AVAILABLE, otherwise null
- static Tuple2 getAvailableAddresses(Trade trade, BtcWalletService btcWalletService,
- KeyRing keyRing) {
- var addresses = getTradeAddresses(trade, btcWalletService, keyRing);
- if (addresses == null)
- return null;
-
- if (btcWalletService.getAvailableAddressEntries().stream()
- .noneMatch(e -> Objects.equals(e.getAddressString(), addresses.first)))
- return null;
- if (btcWalletService.getAvailableAddressEntries().stream()
- .noneMatch(e -> Objects.equals(e.getAddressString(), addresses.second)))
- return null;
-
- return new Tuple2<>(addresses.first, addresses.second);
- }
-
- // Returns addresses as strings if they're known by the wallet
- public static Tuple2 getTradeAddresses(Trade trade, BtcWalletService btcWalletService,
- KeyRing keyRing) {
- var contract = trade.getContract();
- if (contract == null)
- return null;
-
- // Get multisig address
- var isMyRoleBuyer = contract.isMyRoleBuyer(keyRing.getPubKeyRing());
- var multiSigPubKey = isMyRoleBuyer ? contract.getBuyerMultiSigPubKey() : contract.getSellerMultiSigPubKey();
- if (multiSigPubKey == null)
- return null;
- var multiSigPubKeyString = Utilities.bytesAsHexString(multiSigPubKey);
- var multiSigAddress = btcWalletService.getAddressEntryListAsImmutableList().stream()
- .filter(e -> e.getKeyPair().getPublicKeyAsHex().equals(multiSigPubKeyString))
- .findAny()
- .orElse(null);
- if (multiSigAddress == null)
- return null;
-
- // Get payout address
- var payoutAddress = isMyRoleBuyer ?
- contract.getBuyerPayoutAddressString() : contract.getSellerPayoutAddressString();
- var payoutAddressEntry = btcWalletService.getAddressEntryListAsImmutableList().stream()
- .filter(e -> Objects.equals(e.getAddressString(), payoutAddress))
- .findAny()
- .orElse(null);
- if (payoutAddressEntry == null)
- return null;
-
- return new Tuple2<>(multiSigAddress.getAddressString(), payoutAddress);
- }
-}
diff --git a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java
index a584f6b783f..4782ef080d2 100644
--- a/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java
+++ b/core/src/main/java/bisq/core/trade/failed/FailedTradesManager.java
@@ -24,7 +24,7 @@
import bisq.core.trade.DumpDelayedPayoutTx;
import bisq.core.trade.TradableList;
import bisq.core.trade.Trade;
-import bisq.core.trade.TradeUtils;
+import bisq.core.trade.TradeUtil;
import bisq.common.crypto.KeyRing;
import bisq.common.persistence.PersistenceManager;
@@ -50,6 +50,7 @@ public class FailedTradesManager implements PersistedDataHost {
private final PriceFeedService priceFeedService;
private final BtcWalletService btcWalletService;
private final PersistenceManager> persistenceManager;
+ private final TradeUtil tradeUtil;
private final DumpDelayedPayoutTx dumpDelayedPayoutTx;
@Setter
private Function unFailTradeCallback;
@@ -59,12 +60,14 @@ public FailedTradesManager(KeyRing keyRing,
PriceFeedService priceFeedService,
BtcWalletService btcWalletService,
PersistenceManager> persistenceManager,
+ TradeUtil tradeUtil,
DumpDelayedPayoutTx dumpDelayedPayoutTx) {
this.keyRing = keyRing;
this.priceFeedService = priceFeedService;
this.btcWalletService = btcWalletService;
this.dumpDelayedPayoutTx = dumpDelayedPayoutTx;
this.persistenceManager = persistenceManager;
+ this.tradeUtil = tradeUtil;
this.persistenceManager.initialize(failedTrades, "FailedTrades", PersistenceManager.Source.PRIVATE);
}
@@ -127,7 +130,7 @@ public void unFailTrade(Trade trade) {
}
public String checkUnFail(Trade trade) {
- var addresses = TradeUtils.getTradeAddresses(trade, btcWalletService, keyRing);
+ var addresses = tradeUtil.getTradeAddresses(trade);
if (addresses == null) {
return "Addresses not found";
}
diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java
index 0ffbd71f044..e23651bb207 100644
--- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java
+++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java
@@ -56,8 +56,9 @@ public void getTrade(GetTradeRequest req,
StreamObserver responseObserver) {
try {
Trade trade = coreApi.getTrade(req.getTradeId());
+ String role = coreApi.getTradeRole(req.getTradeId());
var reply = GetTradeReply.newBuilder()
- .setTrade(toTradeInfo(trade).toProtoMessage())
+ .setTrade(toTradeInfo(trade, role).toProtoMessage())
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java
index fa000d8e6f7..bce37344b80 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java
@@ -35,6 +35,7 @@
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
+import bisq.core.offer.OfferUtil;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.support.SupportType;
import bisq.core.support.dispute.Dispute;
@@ -107,6 +108,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
public final Navigation navigation;
public final WalletPasswordWindow walletPasswordWindow;
private final NotificationCenter notificationCenter;
+ private final OfferUtil offerUtil;
final ObservableList list = FXCollections.observableArrayList();
private final ListChangeListener tradesListChangeListener;
@@ -142,7 +144,8 @@ public PendingTradesDataModel(TradeManager tradeManager,
DaoFacade daoFacade,
Navigation navigation,
WalletPasswordWindow walletPasswordWindow,
- NotificationCenter notificationCenter) {
+ NotificationCenter notificationCenter,
+ OfferUtil offerUtil) {
this.tradeManager = tradeManager;
this.btcWalletService = btcWalletService;
this.pubKeyRing = pubKeyRing;
@@ -157,6 +160,7 @@ public PendingTradesDataModel(TradeManager tradeManager,
this.navigation = navigation;
this.walletPasswordWindow = walletPasswordWindow;
this.notificationCenter = notificationCenter;
+ this.offerUtil = offerUtil;
tradesListChangeListener = change -> onListChanged();
notificationCenter.setSelectItemByTradeIdConsumer(this::selectItemByTradeId);
@@ -253,7 +257,7 @@ Offer getOffer() {
}
private boolean isBuyOffer() {
- return getOffer() != null && getOffer().getDirection() == OfferPayload.Direction.BUY;
+ return getOffer() != null && offerUtil.isBuyOffer(getOffer().getDirection());
}
boolean isBuyer() {
@@ -348,11 +352,6 @@ Coin getTradeFeeAsBsq() {
}
}
- public String getCurrencyCode() {
- return getOffer() != null ? getOffer().getCurrencyCode() : "";
- }
-
-
@Nullable
public PaymentAccountPayload getSellersPaymentAccountPayload() {
if (getTrade() != null && getTrade().getContract() != null)
@@ -555,26 +554,7 @@ private void doOpenDispute(boolean isSupportTicket, Transaction depositTx) {
}
trade.setDisputeState(Trade.DisputeState.MEDIATION_REQUESTED);
- disputeManager.sendOpenNewDisputeMessage(dispute,
- false,
- resultHandler,
- (errorMessage, throwable) -> {
- if ((throwable instanceof DisputeAlreadyOpenException)) {
- errorMessage += "\n\n" + Res.get("portfolio.pending.openAgainDispute.msg");
- new Popup().warning(errorMessage)
- .actionButtonText(Res.get("portfolio.pending.openAgainDispute.button"))
- .onAction(() -> disputeManager.sendOpenNewDisputeMessage(dispute,
- true,
- resultHandler,
- (e, t) -> {
- log.error(e);
- }))
- .closeButtonText(Res.get("shared.cancel"))
- .show();
- } else {
- new Popup().warning(errorMessage).show();
- }
- });
+ sendOpenDisputeMessage(disputeManager, resultHandler, dispute);
} else if (useRefundAgent) {
resultHandler = () -> navigation.navigateTo(MainView.class, SupportView.class, RefundClientView.class);
@@ -643,35 +623,13 @@ private void doOpenDispute(boolean isSupportTicket, Transaction depositTx) {
dispute.setDonationAddressOfDelayedPayoutTx(donationAddressString.get());
dispute.setDelayedPayoutTxId(delayedPayoutTx.getTxId().toString());
-
trade.setDisputeState(Trade.DisputeState.REFUND_REQUESTED);
((DisputeProtocol) tradeManager.getTradeProtocol(trade)).onPublishDelayedPayoutTx(() -> {
log.info("DelayedPayoutTx published and message sent to peer");
- disputeManager.sendOpenNewDisputeMessage(dispute,
- false,
- resultHandler,
- (errorMessage, throwable) -> {
- if ((throwable instanceof DisputeAlreadyOpenException)) {
- errorMessage += "\n\n" + Res.get("portfolio.pending.openAgainDispute.msg");
- new Popup().warning(errorMessage)
- .actionButtonText(Res.get("portfolio.pending.openAgainDispute.button"))
- .onAction(() -> disputeManager.sendOpenNewDisputeMessage(dispute,
- true,
- resultHandler,
- (e, t) -> {
- log.error(e);
- }))
- .closeButtonText(Res.get("shared.cancel"))
- .show();
- } else {
- new Popup().warning(errorMessage).show();
- }
- });
+ sendOpenDisputeMessage(disputeManager, resultHandler, dispute);
},
- errorMessage -> {
- new Popup().error(errorMessage).show();
- });
+ errorMessage -> new Popup().error(errorMessage).show());
} else {
log.warn("Invalid dispute state {}", disputeState.name());
@@ -694,5 +652,28 @@ public void onMoveInvalidTradeToFailedTrades(Trade trade) {
public boolean isSignWitnessTrade() {
return accountAgeWitnessService.isSignWitnessTrade(selectedTrade);
}
+
+ private void sendOpenDisputeMessage(DisputeManager extends DisputeList> disputeManager,
+ ResultHandler resultHandler,
+ Dispute dispute) {
+ disputeManager.sendOpenNewDisputeMessage(dispute,
+ false,
+ resultHandler,
+ (errorMessage, throwable) -> {
+ if ((throwable instanceof DisputeAlreadyOpenException)) {
+ errorMessage += "\n\n" + Res.get("portfolio.pending.openAgainDispute.msg");
+ new Popup().warning(errorMessage)
+ .actionButtonText(Res.get("portfolio.pending.openAgainDispute.button"))
+ .onAction(() -> disputeManager.sendOpenNewDisputeMessage(dispute,
+ true,
+ resultHandler,
+ (e, t) -> log.error(e)))
+ .closeButtonText(Res.get("shared.cancel"))
+ .show();
+ } else {
+ new Popup().warning(errorMessage).show();
+ }
+ });
+ }
}
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
index 35934419fdf..6a9b4dff06c 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
@@ -24,13 +24,13 @@
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.btc.wallet.Restrictions;
-import bisq.core.locale.CurrencyUtil;
-import bisq.core.locale.Res;
import bisq.core.network.MessageState;
import bisq.core.offer.Offer;
+import bisq.core.offer.OfferUtil;
import bisq.core.provider.fee.FeeService;
import bisq.core.trade.Contract;
import bisq.core.trade.Trade;
+import bisq.core.trade.TradeUtil;
import bisq.core.trade.closed.ClosedTradableManager;
import bisq.core.user.User;
import bisq.core.util.FormattingUtils;
@@ -97,6 +97,8 @@ enum SellerState implements State {
final AccountAgeWitnessService accountAgeWitnessService;
public final P2PService p2PService;
private final ClosedTradableManager closedTradableManager;
+ private final OfferUtil offerUtil;
+ private final TradeUtil tradeUtil;
public final ClockWatcher clockWatcher;
@Getter
private final User user;
@@ -120,6 +122,8 @@ public PendingTradesViewModel(PendingTradesDataModel dataModel,
BtcAddressValidator btcAddressValidator,
P2PService p2PService,
ClosedTradableManager closedTradableManager,
+ OfferUtil offerUtil,
+ TradeUtil tradeUtil,
AccountAgeWitnessService accountAgeWitnessService,
ClockWatcher clockWatcher,
User user) {
@@ -130,6 +134,8 @@ public PendingTradesViewModel(PendingTradesDataModel dataModel,
this.btcAddressValidator = btcAddressValidator;
this.p2PService = p2PService;
this.closedTradableManager = closedTradableManager;
+ this.offerUtil = offerUtil;
+ this.tradeUtil = tradeUtil;
this.accountAgeWitnessService = accountAgeWitnessService;
this.clockWatcher = clockWatcher;
this.user = user;
@@ -199,55 +205,30 @@ ReadOnlyObjectProperty getSellerState() {
}
public String getPayoutAmount() {
- return dataModel.getTrade() != null ? btcFormatter.formatCoinWithCode(dataModel.getTrade().getPayoutAmount()) : "";
+ return dataModel.getTrade() != null
+ ? btcFormatter.formatCoinWithCode(dataModel.getTrade().getPayoutAmount())
+ : "";
}
String getMarketLabel(PendingTradesListItem item) {
- if ((item == null))
- return "";
-
- checkNotNull(item.getTrade().getOffer());
- checkNotNull(item.getTrade().getOffer().getCurrencyCode());
- return CurrencyUtil.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode());
- }
-
- private long getMaxTradePeriod() {
- return dataModel.getOffer() != null ? dataModel.getOffer().getPaymentMethod().getMaxTradePeriod() : 0;
- }
-
- @Nullable
- private Date getMaxTradePeriodDate() {
- return dataModel.getTrade() != null ? dataModel.getTrade().getMaxTradePeriodDate() : null;
- }
-
- @Nullable
- private Date getHalfTradePeriodDate() {
- return dataModel.getTrade() != null ? dataModel.getTrade().getHalfTradePeriodDate() : null;
- }
-
- private long getRemainingTradeDuration() {
- return getMaxTradePeriodDate() != null ? getMaxTradePeriodDate().getTime() - new Date().getTime() : getMaxTradePeriod();
+ return item == null ? "" : tradeUtil.getMarketDescription(item.getTrade());
}
public String getRemainingTradeDurationAsWords() {
- return FormattingUtils.formatDurationAsWords(Math.max(0, getRemainingTradeDuration()));
+ return tradeUtil.getRemainingTradeDurationAsWords(dataModel.getTrade());
}
public double getRemainingTradeDurationAsPercentage() {
- long maxPeriod = getMaxTradePeriod();
- long remaining = getRemainingTradeDuration();
- if (maxPeriod != 0) {
- return 1 - (double) remaining / (double) maxPeriod;
- } else
- return 0;
+ return tradeUtil.getRemainingTradeDurationAsPercentage(dataModel.getTrade());
}
public String getDateForOpenDispute() {
- return DisplayUtils.formatDateTime(new Date(new Date().getTime() + getRemainingTradeDuration()));
+ return DisplayUtils.formatDateTime(tradeUtil.getDateForOpenDispute(dataModel.getTrade()));
}
public boolean showWarning() {
- return getHalfTradePeriodDate() != null && new Date().after(getHalfTradePeriodDate());
+ Date halfTradePeriodDate = tradeUtil.getHalfTradePeriodDate(dataModel.getTrade());
+ return halfTradePeriodDate != null && new Date().after(halfTradePeriodDate);
}
public boolean showDispute() {
@@ -263,36 +244,36 @@ String getMyRole(PendingTradesListItem item) {
Offer offer = trade.getOffer();
checkNotNull(offer);
checkNotNull(offer.getCurrencyCode());
- return getRole(contract.isBuyerMakerAndSellerTaker(), dataModel.isMaker(offer), offer.getCurrencyCode());
+ return tradeUtil.getRole(contract.isBuyerMakerAndSellerTaker(),
+ dataModel.isMaker(offer),
+ offer.getCurrencyCode());
} else {
return "";
}
}
String getPaymentMethod(PendingTradesListItem item) {
- String result = "";
- if (item != null) {
- Offer offer = item.getTrade().getOffer();
- checkNotNull(offer);
- checkNotNull(offer.getPaymentMethod());
- result = offer.getPaymentMethodNameWithCountryCode();
- }
- return result;
+ return item == null ? "" : tradeUtil.getPaymentMethodNameWithCountryCode(item.getTrade());
}
// summary
public String getTradeVolume() {
- return dataModel.getTrade() != null ? btcFormatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount()) : "";
+ return dataModel.getTrade() != null
+ ? btcFormatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount())
+ : "";
}
public String getFiatVolume() {
- return dataModel.getTrade() != null ? DisplayUtils.formatVolumeWithCode(dataModel.getTrade().getTradeVolume()) : "";
+ return dataModel.getTrade() != null
+ ? DisplayUtils.formatVolumeWithCode(dataModel.getTrade().getTradeVolume())
+ : "";
}
public String getTxFee() {
if (trade != null && trade.getTradeAmount() != null) {
Coin txFee = dataModel.getTxFee();
- String percentage = GUIUtil.getPercentageOfTradeAmount(txFee, trade.getTradeAmount(),
+ String percentage = GUIUtil.getPercentageOfTradeAmount(txFee,
+ trade.getTradeAmount(),
Coin.ZERO);
return btcFormatter.formatCoinWithCode(txFee) + percentage;
} else {
@@ -344,7 +325,7 @@ public String getSecurityDeposit() {
}
public boolean isBlockChainMethod() {
- return dataModel.getOffer() != null && dataModel.getOffer().getPaymentMethod().isAsset();
+ return offerUtil.isBlockChainPaymentMethod(dataModel.getOffer());
}
public int getNumPastTrades(Trade trade) {
@@ -363,6 +344,12 @@ public int getNumPastTrades(Trade trade) {
.size();
}
+ @Nullable
+ private Date getMaxTradePeriodDate() {
+ return dataModel.getTrade() != null
+ ? dataModel.getTrade().getMaxTradePeriodDate()
+ : null;
+ }
///////////////////////////////////////////////////////////////////////////////////////////
// States
@@ -479,29 +466,4 @@ private void onTradeStateChanged(Trade.State tradeState) {
break;
}
}
-
- private static String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) {
- if (CurrencyUtil.isFiatCurrency(currencyCode)) {
- String baseCurrencyCode = Res.getBaseCurrencyCode();
- if (isBuyerMakerAndSellerTaker)
- return isMaker ?
- Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.buyer")) :
- Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.seller"));
- else
- return isMaker ?
- Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.seller")) :
- Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.buyer"));
- } else {
- if (isBuyerMakerAndSellerTaker)
- return isMaker ?
- Res.get("formatter.asMaker", currencyCode, Res.get("shared.seller")) :
- Res.get("formatter.asTaker", currencyCode, Res.get("shared.buyer"));
- else
- return isMaker ?
- Res.get("formatter.asMaker", currencyCode, Res.get("shared.buyer")) :
- Res.get("formatter.asTaker", currencyCode, Res.get("shared.seller"));
- }
-
- }
-
}
diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto
index 38ddd4a9dbb..041f1278ea2 100644
--- a/proto/src/main/proto/grpc.proto
+++ b/proto/src/main/proto/grpc.proto
@@ -217,15 +217,27 @@ message TradeInfo {
OfferInfo offer = 1;
string tradeId = 2;
string shortId = 3;
- string state = 4;
- string phase = 5;
- string tradePeriodState = 6;
- bool isDepositPublished = 7;
- bool isDepositConfirmed = 8;
- bool isFiatSent = 9;
- bool isFiatReceived = 10;
- bool isPayoutPublished = 11;
- bool isWithdrawn = 12;
+ uint64 date = 4;
+ string role = 5;
+ bool isCurrencyForTakerFeeBtc = 6;
+ uint64 txFeeAsLong = 7;
+ uint64 takerFeeAsLong = 8;
+ string takerFeeTxId = 9;
+ string depositTxId = 10;
+ string payoutTxId = 11;
+ uint64 tradeAmountAsLong = 12;
+ uint64 tradePrice = 13;
+ string tradingPeerNodeAddress = 14;
+ string state = 15;
+ string phase = 16;
+ string tradePeriodState = 17;
+ bool isDepositPublished = 18;
+ bool isDepositConfirmed = 19;
+ bool isFiatSent = 20;
+ bool isFiatReceived = 21;
+ bool isPayoutPublished = 22;
+ bool isWithdrawn = 23;
+ string contractAsJson = 24;
}
///////////////////////////////////////////////////////////////////////////////////////////