From 3d43ae1f20b344e49b9005f53602629922f9e2f1 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Jul 2022 16:07:29 -0400 Subject: [PATCH] confirm payment sent and received off main thread --- .../core/trade/protocol/BuyerProtocol.java | 54 ++++++++------- .../core/trade/protocol/SellerProtocol.java | 48 ++++++------- .../steps/buyer/BuyerStep2View.java | 67 ++++++++++--------- .../steps/seller/SellerStep3View.java | 3 + 4 files changed, 90 insertions(+), 82 deletions(-) diff --git a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java index e23aba99f3..2ceb6b2cd0 100644 --- a/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/BuyerProtocol.java @@ -126,32 +126,34 @@ public abstract class BuyerProtocol extends DisputeProtocol { public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { System.out.println("BuyerProtocol.onPaymentStarted()"); - synchronized (trade) { - latchTrade(); - this.errorMessageHandler = errorMessageHandler; - BuyerEvent event = BuyerEvent.PAYMENT_SENT; - expect(phase(Trade.Phase.DEPOSIT_UNLOCKED) - .with(event) - .preCondition(trade.confirmPermitted())) - .setup(tasks(ApplyFilter.class, - getVerifyPeersFeePaymentClass(), - //UpdateMultisigWithTradingPeer.class, // TODO (woodser): can use this to test protocol with updated multisig from peer. peer should attempt to send updated multisig hex earlier as part of protocol. cannot use with countdown latch because response comes back in a separate thread and blocks on trade - BuyerPreparesPaymentSentMessage.class, - //BuyerSetupPayoutTxListener.class, - BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background - .using(new TradeTaskRunner(trade, - () -> { - this.errorMessageHandler = null; - handleTaskRunnerSuccess(event); - resultHandler.handleResult(); - }, - (errorMessage) -> { - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT)) - .executeTasks(); - awaitTradeLatch(); - } + new Thread(() -> { + synchronized (trade) { + latchTrade(); + this.errorMessageHandler = errorMessageHandler; + BuyerEvent event = BuyerEvent.PAYMENT_SENT; + expect(phase(Trade.Phase.DEPOSIT_UNLOCKED) + .with(event) + .preCondition(trade.confirmPermitted())) + .setup(tasks(ApplyFilter.class, + getVerifyPeersFeePaymentClass(), + //UpdateMultisigWithTradingPeer.class, // TODO (woodser): can use this to test protocol with updated multisig from peer. peer should attempt to send updated multisig hex earlier as part of protocol. cannot use with countdown latch because response comes back in a separate thread and blocks on trade + BuyerPreparesPaymentSentMessage.class, + //BuyerSetupPayoutTxListener.class, + BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background + .using(new TradeTaskRunner(trade, + () -> { + this.errorMessageHandler = null; + handleTaskRunnerSuccess(event); + resultHandler.handleResult(); + }, + (errorMessage) -> { + handleTaskRunnerFault(event, errorMessage); + }))) + .run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT)) + .executeTasks(true); + awaitTradeLatch(); + } + }).start(); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java index 949f92d56f..269bef3922 100644 --- a/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java +++ b/core/src/main/java/bisq/core/trade/protocol/SellerProtocol.java @@ -124,29 +124,31 @@ public abstract class SellerProtocol extends DisputeProtocol { public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { log.info("SellerProtocol.onPaymentReceived()"); - synchronized (trade) { - latchTrade(); - this.errorMessageHandler = errorMessageHandler; - SellerEvent event = SellerEvent.PAYMENT_RECEIVED; - expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED) - .with(event) - .preCondition(trade.confirmPermitted())) - .setup(tasks( - ApplyFilter.class, - getVerifyPeersFeePaymentClass(), - SellerPreparesPaymentReceivedMessage.class, - SellerSendsPaymentReceivedMessage.class) - .using(new TradeTaskRunner(trade, () -> { - this.errorMessageHandler = null; - handleTaskRunnerSuccess(event); - resultHandler.handleResult(); - }, (errorMessage) -> { - handleTaskRunnerFault(event, errorMessage); - }))) - .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT)) - .executeTasks(); - awaitTradeLatch(); - } + new Thread(() -> { + synchronized (trade) { + latchTrade(); + this.errorMessageHandler = errorMessageHandler; + SellerEvent event = SellerEvent.PAYMENT_RECEIVED; + expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED) + .with(event) + .preCondition(trade.confirmPermitted())) + .setup(tasks( + ApplyFilter.class, + getVerifyPeersFeePaymentClass(), + SellerPreparesPaymentReceivedMessage.class, + SellerSendsPaymentReceivedMessage.class) + .using(new TradeTaskRunner(trade, () -> { + this.errorMessageHandler = null; + handleTaskRunnerSuccess(event); + resultHandler.handleResult(); + }, (errorMessage) -> { + handleTaskRunnerFault(event, errorMessage); + }))) + .run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT)) + .executeTasks(true); + awaitTradeLatch(); + } + }).start(); } @Override 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 2a6435f77c..ab1140516c 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 @@ -159,41 +159,42 @@ public class BuyerStep2View extends TradeStepView { showPopup(); } else if (state.ordinal() <= Trade.State.BUYER_SEND_FAILED_PAYMENT_SENT_MSG.ordinal()) { if (!trade.hasFailed()) { - UserThread.execute(() -> { - switch (state) { - case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT: - case BUYER_SENT_PAYMENT_SENT_MSG: - busyAnimation.play(); - statusLabel.setText(Res.get("shared.sendingConfirmation")); - model.setMessageStateProperty(MessageState.SENT); - timeoutTimer = UserThread.runAfter(() -> { - busyAnimation.stop(); - statusLabel.setText(Res.get("shared.sendingConfirmationAgain")); - }, 10); - break; - case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG: - busyAnimation.stop(); - statusLabel.setText(Res.get("shared.messageArrived")); - model.setMessageStateProperty(MessageState.ARRIVED); - break; - case BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG: - busyAnimation.stop(); - statusLabel.setText(Res.get("shared.messageStoredInMailbox")); - model.setMessageStateProperty(MessageState.STORED_IN_MAILBOX); - break; - case BUYER_SEND_FAILED_PAYMENT_SENT_MSG: - // We get a popup and the trade closed, so we dont need to show anything here - busyAnimation.stop(); - statusLabel.setText(""); - model.setMessageStateProperty(MessageState.FAILED); - break; - default: - log.warn("Unexpected case: State={}, tradeId={} " + state.name(), trade.getId()); + switch (state) { + case BUYER_CONFIRMED_IN_UI_PAYMENT_SENT: + busyAnimation.play(); + statusLabel.setText("Confirming payment sent..."); + break; + case BUYER_SENT_PAYMENT_SENT_MSG: + busyAnimation.play(); + statusLabel.setText(Res.get("shared.sendingConfirmation")); + model.setMessageStateProperty(MessageState.SENT); + timeoutTimer = UserThread.runAfter(() -> { busyAnimation.stop(); statusLabel.setText(Res.get("shared.sendingConfirmationAgain")); - break; - } - }); + }, 10); + break; + case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG: + busyAnimation.stop(); + statusLabel.setText(Res.get("shared.messageArrived")); + model.setMessageStateProperty(MessageState.ARRIVED); + break; + case BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG: + busyAnimation.stop(); + statusLabel.setText(Res.get("shared.messageStoredInMailbox")); + model.setMessageStateProperty(MessageState.STORED_IN_MAILBOX); + break; + case BUYER_SEND_FAILED_PAYMENT_SENT_MSG: + // We get a popup and the trade closed, so we dont need to show anything here + busyAnimation.stop(); + statusLabel.setText(""); + model.setMessageStateProperty(MessageState.FAILED); + break; + default: + log.warn("Unexpected case: State={}, tradeId={} " + state.name(), trade.getId()); + busyAnimation.stop(); + statusLabel.setText(Res.get("shared.sendingConfirmationAgain")); + break; + } } else { log.warn("Trade contains error message {}", trade.getErrorMessage()); statusLabel.setText(""); 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 3ed7b7e68d..6ee5e26b22 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 @@ -120,6 +120,9 @@ public class SellerStep3View extends TradeStepView { if (!trade.hasFailed()) { switch (state) { case SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT: + busyAnimation.play(); + statusLabel.setText(Res.get("Confirming payment received...")); + break; case SELLER_PUBLISHED_PAYOUT_TX: case SELLER_SENT_PAYOUT_TX_PUBLISHED_MSG: case SELLER_SENT_PAYMENT_RECEIVED_MSG: