From cb65de6d2e1497eb8eaf86404fc3285729aba87c Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 23 Oct 2020 12:47:06 -0300 Subject: [PATCH 01/10] Block on tx-fee-request in core TakeOfferModel init Added license comment too. --- .../core/offer/takeoffer/TakeOfferModel.java | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) 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() { From ab20225cd2d50003a8f7f45feca6227a2370a9fb Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:25:20 -0300 Subject: [PATCH 02/10] Add compiler warning suppression, remove comment --- core/src/main/java/bisq/core/api/model/OfferInfo.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 } /* From 63cf4369904855013ac5b8e37de43462c02e1551 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 24 Oct 2020 16:27:03 -0300 Subject: [PATCH 03/10] Add fields to grpc TradeInfo proto & wrapper --- .../java/bisq/core/api/model/TradeInfo.java | 133 +++++++++++++++++- proto/src/main/proto/grpc.proto | 29 ++-- 2 files changed, 149 insertions(+), 13 deletions(-) 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..6e4adeca4ae 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,16 @@ public class TradeInfo implements Payload { private final OfferInfo offer; private final String tradeId; private final String shortId; + private final long date; + 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 +58,22 @@ 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.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,6 +83,7 @@ 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) { @@ -67,6 +91,18 @@ public static TradeInfo toTradeInfo(Trade trade) { .withOffer(toOfferInfo(trade.getOffer())) .withTradeId(trade.getId()) .withShortId(trade.getShortId()) + .withDate(trade.getDate().getTime()) + .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 +112,7 @@ public static TradeInfo toTradeInfo(Trade trade) { .withIsFiatReceived(trade.isFiatReceived()) .withIsPayoutPublished(trade.isPayoutPublished()) .withIsWithdrawn(trade.isWithdrawn()) + .withContractAsJson(trade.getContractAsJson()) .build(); } @@ -89,6 +126,16 @@ public bisq.proto.grpc.TradeInfo toProtoMessage() { .setOffer(offer.toProtoMessage()) .setTradeId(tradeId) .setShortId(shortId) + .setDate(date) + .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 +145,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 +164,16 @@ public static class TradeInfoBuilder { private OfferInfo offer; private String tradeId; private String shortId; + private long date; + 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 +183,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 +200,56 @@ public TradeInfoBuilder withShortId(String shortId) { return this; } + public TradeInfoBuilder withDate(long date) { + this.date = date; + 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 +260,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 +295,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 +310,16 @@ public String toString() { return "TradeInfo{" + " tradeId='" + tradeId + '\'' + "\n" + ", shortId='" + shortId + '\'' + "\n" + + ", date='" + date + '\'' + "\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 +330,7 @@ public String toString() { ", isPayoutPublished=" + isPayoutPublished + "\n" + ", isWithdrawn=" + isWithdrawn + "\n" + ", offer=" + offer + "\n" + + ", contractAsJson=" + contractAsJson + "\n" + '}'; } } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 38ddd4a9dbb..68121d00596 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -217,15 +217,26 @@ 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; + bool isCurrencyForTakerFeeBtc = 5; + uint64 txFeeAsLong = 6; + uint64 takerFeeAsLong = 7; + string takerFeeTxId = 8; + string depositTxId = 9; + string payoutTxId = 10; + uint64 tradeAmountAsLong = 11; + uint64 tradePrice = 12; + string tradingPeerNodeAddress = 13; + string state = 14; + string phase = 15; + string tradePeriodState = 16; + bool isDepositPublished = 17; + bool isDepositConfirmed = 18; + bool isFiatSent = 19; + bool isFiatReceived = 20; + bool isPayoutPublished = 21; + bool isWithdrawn = 22; + string contractAsJson = 23; } /////////////////////////////////////////////////////////////////////////////////////////// From 296e4f98cb6231ed2226e72d95c1317981a9d008 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:26:10 -0300 Subject: [PATCH 04/10] Replace static TradeUtil with singleton TradeUtil The API is going to need some desktop trade utilities, which should be shared between :desktop and :core.api. --- .../java/bisq/core/trade/TradeManager.java | 5 +- .../trade/{TradeUtils.java => TradeUtil.java} | 60 ++++++++++++++----- .../trade/failed/FailedTradesManager.java | 7 ++- 3 files changed, 55 insertions(+), 17 deletions(-) rename core/src/main/java/bisq/core/trade/{TradeUtils.java => TradeUtil.java} (57%) 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/TradeUtils.java b/core/src/main/java/bisq/core/trade/TradeUtil.java similarity index 57% rename from core/src/main/java/bisq/core/trade/TradeUtils.java rename to core/src/main/java/bisq/core/trade/TradeUtil.java index 10a5da8fdf8..001dbd21217 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtils.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -1,18 +1,18 @@ /* * This file is part of Bisq. * - * Bisq is free software: you can redistribute it and/or modify it + * 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 + * 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 . + * along with bisq. If not, see . */ package bisq.core.trade; @@ -23,20 +23,44 @@ import bisq.common.util.Tuple2; import bisq.common.util.Utilities; +import javax.inject.Inject; +import javax.inject.Singleton; + import java.util.Objects; -public class TradeUtils { +import lombok.extern.slf4j.Slf4j; + +/** + * This class contains trade utility methods. + */ +@Slf4j +@Singleton +public class TradeUtil { + + private final BtcWalletService btcWalletService; + private final KeyRing keyRing; - // Returns if both are AVAILABLE, otherwise null - static Tuple2 getAvailableAddresses(Trade trade, BtcWalletService btcWalletService, - KeyRing keyRing) { - var addresses = getTradeAddresses(trade, btcWalletService, 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; @@ -44,18 +68,25 @@ static Tuple2 getAvailableAddresses(Trade trade, BtcWalletServic 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) { + /** + * 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(); + 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)) @@ -65,8 +96,9 @@ public static Tuple2 getTradeAddresses(Trade trade, BtcWalletSer return null; // Get payout address - var payoutAddress = isMyRoleBuyer ? - contract.getBuyerPayoutAddressString() : contract.getSellerPayoutAddressString(); + var payoutAddress = isMyRoleBuyer + ? contract.getBuyerPayoutAddressString() + : contract.getSellerPayoutAddressString(); var payoutAddressEntry = btcWalletService.getAddressEntryListAsImmutableList().stream() .filter(e -> Objects.equals(e.getAddressString(), payoutAddress)) .findAny() 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"; } From ccd3c99f2e5b9cf276e6b70bceb34e73fb0a6858 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 24 Oct 2020 17:45:01 -0300 Subject: [PATCH 05/10] Fix comment typos --- core/src/main/java/bisq/core/trade/TradeUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index 001dbd21217..c93e5e2be3b 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -1,18 +1,18 @@ /* * This file is part of Bisq. * - * bisq is free software: you can redistribute it and/or modify it + * 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 + * 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 . + * along with Bisq. If not, see . */ package bisq.core.trade; From 24ba9215cd12f65605b23c2f5d53037258afd019 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 25 Oct 2020 10:41:19 -0300 Subject: [PATCH 06/10] Refactor PendingTradesViewModel methods -> TradeUtil & OfferUtil --- .../main/java/bisq/core/offer/OfferUtil.java | 4 + .../main/java/bisq/core/trade/TradeUtil.java | 96 +++++++++++++++ .../pendingtrades/PendingTradesViewModel.java | 112 ++++++------------ 3 files changed, 137 insertions(+), 75 deletions(-) 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/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index c93e5e2be3b..a89dec32459 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -18,6 +18,8 @@ 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; @@ -26,10 +28,18 @@ 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; + /** * This class contains trade utility methods. */ @@ -108,4 +118,90 @@ public Tuple2 getTradeAddresses(Trade trade) { 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. + * + * @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/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..53369839bd0 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) { @@ -362,7 +343,13 @@ public int getNumPastTrades(Trade trade) { .collect(Collectors.toSet()) .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")); - } - - } - } From 36ad1379496d29bf26d6d3c90c4cc50b8c74b928 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 25 Oct 2020 10:54:40 -0300 Subject: [PATCH 07/10] Remove trailing spaces for codacy --- .../main/portfolio/pendingtrades/PendingTradesViewModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 53369839bd0..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 @@ -343,7 +343,7 @@ public int getNumPastTrades(Trade trade) { .collect(Collectors.toSet()) .size(); } - + @Nullable private Date getMaxTradePeriodDate() { return dataModel.getTrade() != null From 95bcb1ef9c74c6fa48f946ebc29b9af55bd1ed70 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 25 Oct 2020 11:27:30 -0300 Subject: [PATCH 08/10] Refactor PendingTradesDataModel methods -> TradeUtil Scope of this refactoring is small; more can be done, but the short term goal is to share trade util logic with core api. - Removed unused method getCurrencyCode() - Made minor style changes - Removed duplicated code block --- .../main/java/bisq/core/trade/TradeUtil.java | 2 + .../pendingtrades/PendingTradesDataModel.java | 83 +++++++------------ 2 files changed, 34 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index a89dec32459..2837e4e9319 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -25,6 +25,8 @@ import bisq.common.util.Tuple2; import bisq.common.util.Utilities; +import org.bitcoinj.core.Coin; + import javax.inject.Inject; import javax.inject.Singleton; 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> 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(); + } + }); + } } From bbd7a31c88907e7c29ce473e5a71603f976ace21 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 25 Oct 2020 11:38:03 -0300 Subject: [PATCH 09/10] Remove unused import --- core/src/main/java/bisq/core/trade/TradeUtil.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index 2837e4e9319..a89dec32459 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -25,8 +25,6 @@ import bisq.common.util.Tuple2; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; - import javax.inject.Inject; import javax.inject.Singleton; From 161dbade0d04dcd7439e3ed94929a4c4ce3fdab0 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sun, 25 Oct 2020 16:22:20 -0300 Subject: [PATCH 10/10] Add getRole(tradeId) to core api API users will need to see their role as maker/taker when looking at trade details. - Add getRole(trade) to TradeUtil. - Add getTradeRole(tradeId) to CoreApi, CoreTradesService. - Add role field to TradeInfo proto and its wrapper class. --- core/src/main/java/bisq/core/api/CoreApi.java | 4 ++ .../java/bisq/core/api/CoreTradesService.java | 9 +++++ .../java/bisq/core/api/model/TradeInfo.java | 15 +++++++ .../main/java/bisq/core/trade/TradeUtil.java | 23 ++++++++++- .../bisq/daemon/grpc/GrpcTradesService.java | 3 +- proto/src/main/proto/grpc.proto | 39 ++++++++++--------- 6 files changed, 72 insertions(+), 21 deletions(-) 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/TradeInfo.java b/core/src/main/java/bisq/core/api/model/TradeInfo.java index 6e4adeca4ae..1a717a7672e 100644 --- a/core/src/main/java/bisq/core/api/model/TradeInfo.java +++ b/core/src/main/java/bisq/core/api/model/TradeInfo.java @@ -40,6 +40,7 @@ public class TradeInfo implements Payload { 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; @@ -65,6 +66,7 @@ public TradeInfo(TradeInfoBuilder builder) { 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; @@ -87,11 +89,16 @@ public TradeInfo(TradeInfoBuilder builder) { } 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()) @@ -127,6 +134,7 @@ public bisq.proto.grpc.TradeInfo toProtoMessage() { .setTradeId(tradeId) .setShortId(shortId) .setDate(date) + .setRole(role) .setIsCurrencyForTakerFeeBtc(isCurrencyForTakerFeeBtc) .setTxFeeAsLong(txFeeAsLong) .setTakerFeeAsLong(takerFeeAsLong) @@ -165,6 +173,7 @@ public static class TradeInfoBuilder { private String tradeId; private String shortId; private long date; + private String role; private boolean isCurrencyForTakerFeeBtc; private long txFeeAsLong; private long takerFeeAsLong; @@ -205,6 +214,11 @@ public TradeInfoBuilder withDate(long date) { return this; } + public TradeInfoBuilder withRole(String role) { + this.role = role; + return this; + } + public TradeInfoBuilder withIsCurrencyForTakerFeeBtc(boolean isCurrencyForTakerFeeBtc) { this.isCurrencyForTakerFeeBtc = isCurrencyForTakerFeeBtc; return this; @@ -311,6 +325,7 @@ public String toString() { " tradeId='" + tradeId + '\'' + "\n" + ", shortId='" + shortId + '\'' + "\n" + ", date='" + date + '\'' + "\n" + + ", role='" + role + '\'' + "\n" + ", isCurrencyForTakerFeeBtc='" + isCurrencyForTakerFeeBtc + '\'' + "\n" + ", txFeeAsLong='" + txFeeAsLong + '\'' + "\n" + ", takerFeeAsLong='" + takerFeeAsLong + '\'' + "\n" + diff --git a/core/src/main/java/bisq/core/trade/TradeUtil.java b/core/src/main/java/bisq/core/trade/TradeUtil.java index a89dec32459..cd4fd074aad 100644 --- a/core/src/main/java/bisq/core/trade/TradeUtil.java +++ b/core/src/main/java/bisq/core/trade/TradeUtil.java @@ -39,6 +39,7 @@ 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. @@ -173,6 +174,27 @@ public String getPaymentMethodNameWithCountryCode(Trade trade) { 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. * @@ -202,6 +224,5 @@ public String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, Strin ? Res.get("formatter.asMaker", currencyCode, Res.get("shared.buyer")) : Res.get("formatter.asTaker", currencyCode, Res.get("shared.seller")); } - } } 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/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 68121d00596..041f1278ea2 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -218,25 +218,26 @@ message TradeInfo { string tradeId = 2; string shortId = 3; uint64 date = 4; - bool isCurrencyForTakerFeeBtc = 5; - uint64 txFeeAsLong = 6; - uint64 takerFeeAsLong = 7; - string takerFeeTxId = 8; - string depositTxId = 9; - string payoutTxId = 10; - uint64 tradeAmountAsLong = 11; - uint64 tradePrice = 12; - string tradingPeerNodeAddress = 13; - string state = 14; - string phase = 15; - string tradePeriodState = 16; - bool isDepositPublished = 17; - bool isDepositConfirmed = 18; - bool isFiatSent = 19; - bool isFiatReceived = 20; - bool isPayoutPublished = 21; - bool isWithdrawn = 22; - string contractAsJson = 23; + 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; } ///////////////////////////////////////////////////////////////////////////////////////////