diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java index ec5d5547937..6f475f6734e 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsMakerProtocol.java @@ -55,6 +55,8 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; + @Slf4j public class BuyerAsMakerProtocol extends TradeProtocol implements BuyerProtocol, MakerProtocol { private final BuyerAsMakerTrade buyerAsMakerTrade; @@ -212,6 +214,9 @@ private void handle() { // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + + "dispute has been opened."); + if (trade.isDepositConfirmed() && !trade.isFiatSent()) { buyerAsMakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsMakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java index 6665c001ec6..4d17d4c47fa 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerAsTakerProtocol.java @@ -59,6 +59,7 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -237,6 +238,9 @@ private void handle() { // User clicked the "bank transfer started" button @Override public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + checkArgument(!wasDisputed(), "A call to onFiatPaymentStarted is not permitted once a " + + "dispute has been opened."); + if (!trade.isFiatSent()) { buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_FIAT_PAYMENT_INITIATED); diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java index 3a5ae4df9b8..29ecde1c005 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsMakerProtocol.java @@ -57,6 +57,8 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; + @Slf4j public class SellerAsMakerProtocol extends TradeProtocol implements SellerProtocol, MakerProtocol { private final SellerAsMakerTrade sellerAsMakerTrade; @@ -204,6 +206,9 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr // User clicked the "bank transfer received" button, so we release the funds for payout @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + + "dispute has been opened."); + if (trade.getPayoutTx() == null) { sellerAsMakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsMakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java index fd42d66b7c0..8979a61b28c 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerAsTakerProtocol.java @@ -56,6 +56,7 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; @Slf4j @@ -196,6 +197,9 @@ private void handle(CounterCurrencyTransferStartedMessage tradeMessage, NodeAddr // User clicked the "bank transfer received" button, so we release the funds for payout @Override public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + checkArgument(!wasDisputed(), "A call to onFiatPaymentReceived is not permitted once a " + + "dispute has been opened."); + if (trade.getPayoutTx() == null) { sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_FIAT_PAYMENT_RECEIPT); TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, diff --git a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java index 4cf78045db2..c561b242741 100644 --- a/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/TradeProtocol.java @@ -345,6 +345,10 @@ protected void handleTaskRunnerFault(@Nullable TradeMessage tradeMessage, String cleanup(); } + protected boolean wasDisputed() { + return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; + } + private void sendAckMessage(@Nullable TradeMessage tradeMessage, boolean result, @Nullable String errorMessage) { // We complete at initial protocol setup with the setup listener tasks. // Other cases are if we start from an UI event the task runner (payment started, confirmed). 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 fb03b413f8a..6d1a288f118 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 @@ -185,7 +185,7 @@ void onSelectItem(PendingTradesListItem item) { } public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - final Trade trade = getTrade(); + Trade trade = getTrade(); checkNotNull(trade, "trade must not be null"); checkArgument(trade instanceof BuyerTrade, "Check failed: trade instanceof BuyerTrade"); ((BuyerTrade) trade).onFiatPaymentStarted(resultHandler, errorMessageHandler); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index dc9a93ec49d..7e1e9ff1190 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -390,7 +390,6 @@ protected void applyOnDisputeOpened() { } private void updateDisputeState(Trade.DisputeState disputeState) { - deactivatePaymentButtons(false); Optional ownDispute; switch (disputeState) { case NO_DISPUTE: @@ -406,7 +405,6 @@ private void updateDisputeState(Trade.DisputeState disputeState) { if (tradeStepInfo != null) tradeStepInfo.setState(TradeStepInfo.State.IN_MEDIATION_SELF_REQUESTED); }); - break; case MEDIATION_STARTED_BY_PEER: if (tradeStepInfo != null) { @@ -435,7 +433,6 @@ private void updateDisputeState(Trade.DisputeState disputeState) { updateMediationResultState(true); break; case REFUND_REQUESTED: - deactivatePaymentButtons(true); if (tradeStepInfo != null) { tradeStepInfo.setFirstHalfOverWarnTextSupplier(this::getFirstHalfOverWarnText); } @@ -449,7 +446,6 @@ private void updateDisputeState(Trade.DisputeState disputeState) { break; case REFUND_REQUEST_STARTED_BY_PEER: - deactivatePaymentButtons(true); if (tradeStepInfo != null) { tradeStepInfo.setFirstHalfOverWarnTextSupplier(this::getFirstHalfOverWarnText); } @@ -462,9 +458,12 @@ private void updateDisputeState(Trade.DisputeState disputeState) { }); break; case REFUND_REQUEST_CLOSED: - deactivatePaymentButtons(true); + break; + default: break; } + + updateConfirmButtonDisableState(isDisputed()); } private void updateMediationResultState(boolean blockOpeningOfResultAcceptedPopup) { @@ -604,7 +603,8 @@ private void openMediationResultPopup(String headLine) { acceptMediationResultPopup.show(); } - protected void deactivatePaymentButtons(boolean isDisabled) { + protected void updateConfirmButtonDisableState(boolean isDisabled) { + // By default do nothing. Only overwritten in certain trade steps } private void updateTradePeriodState(Trade.TradePeriodState tradePeriodState) { @@ -639,6 +639,11 @@ private void updateTradePeriodState(Trade.TradePeriodState tradePeriodState) { } } + protected boolean isDisputed() { + return trade.getDisputeState() != Trade.DisputeState.NO_DISPUTE; + } + + /////////////////////////////////////////////////////////////////////////////////////////// // TradeDurationLimitInfo /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index 562c716ebec..b7783cac737 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -193,6 +193,8 @@ public void activate() { } }); } + + confirmButton.setDisable(isDisputed()); } @Override @@ -387,6 +389,10 @@ protected void applyOnDisputeOpened() { /////////////////////////////////////////////////////////////////////////////////////////// private void onPaymentStarted() { + if (isDisputed()) { + return; + } + if (!model.dataModel.isBootstrappedOrShowPopup()) { return; } @@ -631,7 +637,7 @@ private void showPopup() { } @Override - protected void deactivatePaymentButtons(boolean isDisabled) { + protected void updateConfirmButtonDisableState(boolean isDisabled) { confirmButton.setDisable(isDisabled); } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java index 5e45038ada6..59824075fb1 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java @@ -313,7 +313,7 @@ protected void addContent() { } @Override - protected void deactivatePaymentButtons(boolean isDisabled) { + protected void updateConfirmButtonDisableState(boolean isDisabled) { confirmButton.setDisable(isDisabled); } @@ -364,6 +364,10 @@ protected void applyOnDisputeOpened() { /////////////////////////////////////////////////////////////////////////////////////////// private void onPaymentReceived() { + if (isDisputed()) { + return; + } + // The confirmPaymentReceived call will trigger the trade protocol to do the payout tx. We want to be sure that we // are well connected to the Bitcoin network before triggering the broadcast. if (model.dataModel.isReadyForTxBroadcast()) {