From ef4937bba17c808f9841546d70f66693105a84fd Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Wed, 11 Mar 2015 19:02:18 +0100 Subject: [PATCH] Refactor tasks with taskrunner --- .../pending/PendingTradesDataModel.java | 1 + .../pending/PendingTradesViewModel.java | 4 +- .../trade/takeoffer/TakeOfferDataModel.java | 4 +- .../main/trade/takeoffer/TakeOfferView.java | 3 +- .../main/java/io/bitsquare/trade/Trade.java | 26 +- .../java/io/bitsquare/trade/TradeManager.java | 127 ++--- .../bitsquare/trade/TradeMessageService.java | 6 +- .../io/bitsquare/trade/TradeTaskRunner.java | 56 ++ ...ssageListener.java => MessageHandler.java} | 2 +- .../trade/TradeSharedModel.java} | 26 +- .../trade/taker/SellerTakesOfferModel.java | 341 ++++++++++++ .../trade/taker/SellerTakesOfferProtocol.java | 506 +++++------------- .../taker/tasks/CreateAndSignContract.java | 66 +-- .../trade/taker/tasks/GetPeerAddress.java | 27 +- .../trade/taker/tasks/PayDeposit.java | 54 +- .../trade/taker/tasks/PayTakeOfferFee.java | 32 +- .../trade/taker/tasks/RequestTakeOffer.java | 23 +- .../taker/tasks/SendPayoutTxToOfferer.java | 25 +- .../tasks/SendSignedTakerDepositTxAsHex.java | 65 +-- .../tasks/SendTakeOfferFeePayedMessage.java | 42 +- .../taker/tasks/SignAndPublishPayoutTx.java | 59 +- .../taker/tasks/TakerCommitDepositTx.java | 29 +- .../ValidateBankTransferInitedMessage.java | 58 ++ .../ValidateDepositTxPublishedMessage.java | 52 ++ ...idateRespondToTakeOfferRequestMessage.java | 57 ++ ...dateTakerDepositPaymentRequestMessage.java | 55 ++ .../taker/tasks/VerifyOfferFeePayment.java | 22 +- .../taker/tasks/VerifyOffererAccount.java | 31 +- .../tomp2p/TomP2PTradeMessageService.java | 14 +- .../io/bitsquare/util/tasks/SharedModel.java | 25 + .../java/io/bitsquare/util/tasks/Task.java | 56 ++ .../io/bitsquare/util/tasks/TaskRunner.java | 106 ++++ .../trade/protocol/placeoffer/TaskRunner.java | 136 +++++ 33 files changed, 1417 insertions(+), 719 deletions(-) create mode 100644 gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java rename gui/src/main/java/io/bitsquare/trade/listeners/{ProcessNewMessageListener.java => MessageHandler.java} (95%) rename gui/src/main/java/io/bitsquare/trade/{listeners/SellerTakesOfferProtocolListener.java => protocol/trade/TradeSharedModel.java} (59%) create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferModel.java create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateBankTransferInitedMessage.java create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateDepositTxPublishedMessage.java create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateRespondToTakeOfferRequestMessage.java create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateTakerDepositPaymentRequestMessage.java create mode 100644 gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java create mode 100644 gui/src/main/java/io/bitsquare/util/tasks/Task.java create mode 100644 gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java create mode 100644 gui/src/test/java/io/bitsquare/trade/protocol/placeoffer/TaskRunner.java diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java index c3d148b3fd..dce4638604 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesDataModel.java @@ -167,6 +167,7 @@ class PendingTradesDataModel implements Activatable, DataModel { } void fiatPaymentReceived() { + getTrade().setState(Trade.State.FIAT_PAYMENT_RECEIVED); tradeManager.fiatPaymentReceived(getTrade().getId()); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java index 83d5ca8017..f31c2a9cd9 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pending/PendingTradesViewModel.java @@ -230,11 +230,11 @@ class PendingTradesViewModel extends ActivatableWithDataModel previousTask; + private Class currentTask; + + public void setCurrentTask(Class currentTask) { + this.currentTask = currentTask; + } + + public Class getCurrentTask() { + return currentTask; + } + + public void setPreviousTask(Class previousTask) { + this.previousTask = previousTask; + } + + public Class getPreviousTask() { + return previousTask; + } /////////////////////////////////////////////////////////////////////////////////////////// // Enum @@ -43,9 +62,10 @@ public class Trade implements Serializable { OFFERER_REJECTED, /* For taker only*/ DEPOSIT_PUBLISHED, DEPOSIT_CONFIRMED, - PAYMENT_STARTED, - FAILED, - COMPLETED + FIAT_PAYMENT_STARTED, + FIAT_PAYMENT_RECEIVED, + PAYOUT_PUBLISHED, + FAILED } private final Offer offer; diff --git a/gui/src/main/java/io/bitsquare/trade/TradeManager.java b/gui/src/main/java/io/bitsquare/trade/TradeManager.java index de7d6abb01..429da70aa2 100644 --- a/gui/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/gui/src/main/java/io/bitsquare/trade/TradeManager.java @@ -31,7 +31,6 @@ import io.bitsquare.offer.OpenOffer; import io.bitsquare.persistence.Persistence; import io.bitsquare.trade.handlers.TransactionResultHandler; import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener; -import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener; import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol; import io.bitsquare.trade.protocol.trade.OfferMessage; import io.bitsquare.trade.protocol.trade.TradeMessage; @@ -43,6 +42,7 @@ import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequ import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.IsOfferAvailableResponse; import io.bitsquare.trade.protocol.trade.taker.RequestIsOfferAvailableProtocol; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol; import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage; import io.bitsquare.trade.protocol.trade.taker.messages.RequestIsOfferAvailableMessage; @@ -137,7 +137,7 @@ public class TradeManager { closedTrades.putAll((Map) closedTradesObject); } - tradeMessageService.addHandleNewMessageListener(this::handleNewMessage); + tradeMessageService.addMessageHandler(this::handleNewMessage); } @@ -146,7 +146,7 @@ public class TradeManager { /////////////////////////////////////////////////////////////////////////////////////////// public void cleanup() { - tradeMessageService.removeHandleNewMessageListener(this::handleNewMessage); + tradeMessageService.removeMessageHandler(this::handleNewMessage); } @@ -239,6 +239,11 @@ public class TradeManager { pendingTrades.remove(trade.getId()); persistPendingTrades(); + if (takerAsSellerProtocolMap.containsKey(trade.getId())) + takerAsSellerProtocolMap.remove(trade.getId()); + else if (offererAsBuyerProtocolMap.containsKey(trade.getId())) + offererAsBuyerProtocolMap.remove(trade.getId()); + closedTrades.put(trade.getId(), trade); persistClosedTrades(); } @@ -274,9 +279,9 @@ public class TradeManager { public void onOfferAccepted(Offer offer) { persistPendingTrades(); //TODO do that later - requestRemoveOpenOffer(offer.getId(), + /*requestRemoveOpenOffer(offer.getId(), () -> log.debug("remove offer was successful"), - (message) -> log.error(message)); + (message) -> log.error(message));*/ } @Override @@ -295,7 +300,7 @@ public class TradeManager { @Override public void onPayoutTxPublished(Transaction payoutTx) { trade.setPayoutTx(payoutTx); - trade.setState(Trade.State.COMPLETED); + trade.setState(Trade.State.PAYOUT_PUBLISHED); // We close the trade when the user has withdrawn his trade funds (see #283) //closeTrade(trade); @@ -363,76 +368,48 @@ public class TradeManager { Trade trade = createTrade(offer); trade.setTradeAmount(amount); - SellerTakesOfferProtocolListener listener = new SellerTakesOfferProtocolListener() { - @Override - public void onTakeOfferRequestAccepted() { - persistPendingTrades(); + trade.stateProperty().addListener((ov, oldValue, newValue) -> { + log.debug("trade state = " + newValue); + switch (newValue) { + case OPEN: + break; + case OFFERER_ACCEPTED: + persistPendingTrades(); + break; + case OFFERER_REJECTED: + removeFailedTrade(trade); + break; + case DEPOSIT_PUBLISHED: + persistPendingTrades(); + break; + case DEPOSIT_CONFIRMED: + break; + case FIAT_PAYMENT_STARTED: + persistPendingTrades(); + break; + case FAILED: + removeFailedTrade(trade); + break; + case PAYOUT_PUBLISHED: + persistPendingTrades(); + break; + default: + log.error("Unhandled trade state: " + newValue); + break; } + }); - @Override - public void onTakeOfferRequestRejected() { - removeFailedTrade(trade); - } - - @Override - public void onDepositTxPublished() { - persistPendingTrades(); - } - - @Override - public void onBankTransferInited(String tradeId) { - trade.setState(Trade.State.PAYMENT_STARTED); - persistPendingTrades(); - } - - @Override - public void onPayoutTxPublished(Trade trade, Transaction payoutTx) { - trade.setPayoutTx(payoutTx); - trade.setState(Trade.State.COMPLETED); - // We close the trade when the user has withdrawn his trade funds (see #283) - //closeTrade(trade); - persistPendingTrades(); - } - - @Override - public void onFault(Throwable throwable, SellerTakesOfferProtocol.State state) { - log.error("Error while executing trade process at state: " + state + " / " + throwable); - switch (state) { - case GetPeerAddress: - removeFailedTrade(trade); - break; - case RequestTakeOffer: - removeFailedTrade(trade); - break; - case ValidateRespondToTakeOfferRequestMessage: - // TODO might need further inspection. Removal could be used for sabotage. - //removeFailedTrade(trade); - break; - case PayTakeOfferFee: - removeFailedTrade(trade); - break; - case SendTakeOfferFeePayedMessage: - removeFailedTrade(trade); - break; - case ValidateTakerDepositPaymentRequestMessage: - removeFailedTrade(trade); - break; - - - } - } - - }; - - SellerTakesOfferProtocol sellerTakesOfferProtocol = new SellerTakesOfferProtocol( + SellerTakesOfferModel model = new SellerTakesOfferModel( trade, - listener, tradeMessageService, walletService, blockChainService, signatureService, user); + + SellerTakesOfferProtocol sellerTakesOfferProtocol = new SellerTakesOfferProtocol(model); takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol); + sellerTakesOfferProtocol.start(); return trade; @@ -444,7 +421,7 @@ public class TradeManager { public void fiatPaymentStarted(String tradeId) { if (offererAsBuyerProtocolMap.get(tradeId) != null) { offererAsBuyerProtocolMap.get(tradeId).handleUIEventBankTransferStarted(); - pendingTrades.get(tradeId).setState(Trade.State.PAYMENT_STARTED); + pendingTrades.get(tradeId).setState(Trade.State.FIAT_PAYMENT_STARTED); persistPendingTrades(); } else { @@ -455,7 +432,7 @@ public class TradeManager { } public void fiatPaymentReceived(String tradeId) { - takerAsSellerProtocolMap.get(tradeId).handleUIEventFiatReceived(); + takerAsSellerProtocolMap.get(tradeId).handleFiatReceivedUIEvent(); } public void requestIsOfferAvailable(Offer offer) { @@ -524,29 +501,19 @@ public class TradeManager { createOffererAsBuyerProtocol(tradeId, sender); } else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) { - takerAsSellerProtocolMap.get(tradeId).handleRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage); } else if (tradeMessage instanceof TakeOfferFeePayedMessage) { offererAsBuyerProtocolMap.get(tradeId).handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage); } else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) { - takerAsSellerProtocolMap.get(tradeId).handleTakerDepositPaymentRequestMessage((TakerDepositPaymentRequestMessage) tradeMessage); } else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) { offererAsBuyerProtocolMap.get(tradeId).handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage); } else if (tradeMessage instanceof DepositTxPublishedMessage) { - persistPendingTrades(); - takerAsSellerProtocolMap.get(tradeId).handleDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage); + // persistPendingTrades(); } else if (tradeMessage instanceof BankTransferInitedMessage) { - // Here happened a null pointer. I assume the only possible reason was that we got a null for the - // tradeID - // as the takerAsSellerProtocolMap need to have that trade got added earlier. - // For getting better info we add a check. tradeId is checked above. - if (takerAsSellerProtocolMap.get(tradeId) == null) - log.error("takerAsSellerProtocolMap.get(tradeId) = null. That must not happen."); - takerAsSellerProtocolMap.get(tradeId).handleBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage); } else if (tradeMessage instanceof PayoutTxPublishedMessage) { offererAsBuyerProtocolMap.get(tradeId).handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage); diff --git a/gui/src/main/java/io/bitsquare/trade/TradeMessageService.java b/gui/src/main/java/io/bitsquare/trade/TradeMessageService.java index c4e70997a3..b632dd6896 100644 --- a/gui/src/main/java/io/bitsquare/trade/TradeMessageService.java +++ b/gui/src/main/java/io/bitsquare/trade/TradeMessageService.java @@ -21,7 +21,7 @@ import io.bitsquare.network.Message; import io.bitsquare.network.MessageBroker; import io.bitsquare.network.Peer; import io.bitsquare.trade.listeners.GetPeerAddressListener; -import io.bitsquare.trade.listeners.ProcessNewMessageListener; +import io.bitsquare.trade.listeners.MessageHandler; import io.bitsquare.trade.listeners.SendMessageListener; import java.security.PublicKey; @@ -34,9 +34,9 @@ public interface TradeMessageService extends MessageBroker { void sendMessage(Peer peer, Message message, SendMessageListener listener); - void addHandleNewMessageListener(ProcessNewMessageListener listener); + void addMessageHandler(MessageHandler listener); - void removeHandleNewMessageListener(ProcessNewMessageListener listener); + void removeMessageHandler(MessageHandler listener); void getPeerAddress(PublicKey messagePublicKey, GetPeerAddressListener getPeerAddressListener); } diff --git a/gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java b/gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java new file mode 100644 index 0000000000..45e650702b --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java @@ -0,0 +1,56 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade; + +import io.bitsquare.trade.protocol.trade.TradeSharedModel; +import io.bitsquare.util.handlers.FaultHandler; +import io.bitsquare.util.handlers.ResultHandler; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.jetbrains.annotations.NotNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TradeTaskRunner extends TaskRunner { + private static final Logger log = LoggerFactory.getLogger(TradeTaskRunner.class); + + public TradeTaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { + super(sharedModel, resultHandler, faultHandler); + } + + @Override + protected void setCurrentTask(Class task) { + super.setCurrentTask(task); + sharedModel.getTrade().setCurrentTask(task); + } + + @Override + protected void setPreviousTask(Class task) { + super.setPreviousTask(task); + if (task != null) + sharedModel.getTrade().setPreviousTask(task); + } + + @Override + public void handleFault(String message, @NotNull Throwable throwable) { + sharedModel.getTrade().setState(Trade.State.FAILED); + super.handleFault(message, throwable); + } +} diff --git a/gui/src/main/java/io/bitsquare/trade/listeners/ProcessNewMessageListener.java b/gui/src/main/java/io/bitsquare/trade/listeners/MessageHandler.java similarity index 95% rename from gui/src/main/java/io/bitsquare/trade/listeners/ProcessNewMessageListener.java rename to gui/src/main/java/io/bitsquare/trade/listeners/MessageHandler.java index 51c3a7bb22..d365c2ed9d 100644 --- a/gui/src/main/java/io/bitsquare/trade/listeners/ProcessNewMessageListener.java +++ b/gui/src/main/java/io/bitsquare/trade/listeners/MessageHandler.java @@ -20,6 +20,6 @@ package io.bitsquare.trade.listeners; import io.bitsquare.network.Message; import io.bitsquare.network.Peer; -public interface ProcessNewMessageListener { +public interface MessageHandler { void handleMessage(Message message, Peer sender); } diff --git a/gui/src/main/java/io/bitsquare/trade/listeners/SellerTakesOfferProtocolListener.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/TradeSharedModel.java similarity index 59% rename from gui/src/main/java/io/bitsquare/trade/listeners/SellerTakesOfferProtocolListener.java rename to gui/src/main/java/io/bitsquare/trade/protocol/trade/TradeSharedModel.java index 6055c3e3c8..89e33ee58b 100644 --- a/gui/src/main/java/io/bitsquare/trade/listeners/SellerTakesOfferProtocolListener.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/TradeSharedModel.java @@ -15,24 +15,24 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.listeners; +package io.bitsquare.trade.protocol.trade; import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol; +import io.bitsquare.util.tasks.SharedModel; -import org.bitcoinj.core.Transaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public interface SellerTakesOfferProtocolListener { - void onDepositTxPublished(); +public class TradeSharedModel extends SharedModel { + private static final Logger log = LoggerFactory.getLogger(TradeSharedModel.class); - void onBankTransferInited(String tradeId); + public Trade getTrade() { + return trade; + } - void onPayoutTxPublished(Trade trade, Transaction payoutTx); - - void onFault(Throwable throwable, SellerTakesOfferProtocol.State state); - - void onTakeOfferRequestAccepted(); - - void onTakeOfferRequestRejected(); + protected final Trade trade; + public TradeSharedModel(Trade trade) { + this.trade = trade; + } } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferModel.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferModel.java new file mode 100644 index 0000000000..404410fbec --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferModel.java @@ -0,0 +1,341 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.trade.taker; + +import io.bitsquare.bank.BankAccount; +import io.bitsquare.btc.BlockChainService; +import io.bitsquare.btc.WalletService; +import io.bitsquare.crypto.SignatureService; +import io.bitsquare.network.Peer; +import io.bitsquare.offer.Offer; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.TradeMessageService; +import io.bitsquare.trade.protocol.trade.TradeMessage; +import io.bitsquare.trade.protocol.trade.TradeSharedModel; +import io.bitsquare.user.User; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.core.ECKey; +import org.bitcoinj.core.Transaction; + +import java.security.PublicKey; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SellerTakesOfferModel extends TradeSharedModel { + private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferModel.class); + private Transaction payoutTx; + private String payoutTxAsHex; + + public void setPayoutTx(Transaction payoutTx) { + this.payoutTx = payoutTx; + } + + public Transaction getPayoutTx() { + return payoutTx; + } + + public void setPayoutTxAsHex(String payoutTxAsHex) { + this.payoutTxAsHex = payoutTxAsHex; + } + + public String getPayoutTxAsHex() { + return payoutTxAsHex; + } + + public enum State { + Init, + GetPeerAddress, + RequestTakeOffer, + + ValidateRespondToTakeOfferRequestMessage, + PayTakeOfferFee, + SendTakeOfferFeePayedMessage, + + ValidateTakerDepositPaymentRequestMessage, + VerifyOffererAccount, + CreateAndSignContract, + PayDeposit, + SendSignedTakerDepositTxAsHex, + + ValidateDepositTxPublishedMessage, + TakerCommitDepositTx, + handleBankTransferInitedMessage, + SignAndPublishPayoutTx, + SendPayoutTxToOfferer + } + + // provided data + private final TradeMessageService tradeMessageService; + private final WalletService walletService; + private final BlockChainService blockChainService; + private final SignatureService signatureService; + + // derived + private final Offer offer; + private final String tradeId; + private final BankAccount bankAccount; + private final String accountId; + private final PublicKey messagePublicKey; + private final Coin tradeAmount; + private final String tradePubKeyAsHex; + private final ECKey accountKey; + private final PublicKey offererMessagePublicKey; + private final Coin securityDeposit; + private final String arbitratorPubKey; + + + // written/read by task + private Peer peer; + + // written by messages, read by tasks + private String peersAccountId; + private BankAccount peersBankAccount; + private String peersPubKey; + private String preparedPeersDepositTxAsHex; + private long peersTxOutIndex; + + private String depositTxAsHex; + private String offererSignatureR; + private String offererSignatureS; + private Coin offererPaybackAmount; + private Coin takerPaybackAmount; + private String offererPayoutAddress; + private Transaction signedTakerDepositTx; + + private TradeMessage tradeMessage; + + // state + private State state; + + public SellerTakesOfferModel(Trade trade, + TradeMessageService tradeMessageService, + WalletService walletService, + BlockChainService blockChainService, + SignatureService signatureService, + User user) { + super(trade); + this.tradeMessageService = tradeMessageService; + this.walletService = walletService; + this.blockChainService = blockChainService; + this.signatureService = signatureService; + + offer = trade.getOffer(); + tradeId = trade.getId(); + tradeAmount = trade.getTradeAmount(); + securityDeposit = trade.getSecurityDeposit(); + //TODO use 1. for now + arbitratorPubKey = trade.getOffer().getArbitrators().get(0).getPubKeyAsHex(); + + offererMessagePublicKey = offer.getMessagePublicKey(); + + bankAccount = user.getCurrentBankAccount().get(); + accountId = user.getAccountId(); + messagePublicKey = user.getMessagePublicKey(); + + tradePubKeyAsHex = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString(); + accountKey = walletService.getRegistrationAddressEntry().getKey(); + + state = State.Init; + } + + + // Setters + public void setPeer(Peer peer) { + this.peer = peer; + } + + public void setPeersAccountId(String peersAccountId) { + this.peersAccountId = peersAccountId; + } + + public void setPeersBankAccount(BankAccount peersBankAccount) { + this.peersBankAccount = peersBankAccount; + } + + public void setPeersPubKey(String peersPubKey) { + this.peersPubKey = peersPubKey; + } + + public void setPreparedPeersDepositTxAsHex(String preparedPeersDepositTxAsHex) { + this.preparedPeersDepositTxAsHex = preparedPeersDepositTxAsHex; + } + + public void setPeersTxOutIndex(long peersTxOutIndex) { + this.peersTxOutIndex = peersTxOutIndex; + } + + public void setDepositTxAsHex(String depositTxAsHex) { + this.depositTxAsHex = depositTxAsHex; + } + + public void setOffererSignatureR(String offererSignatureR) { + this.offererSignatureR = offererSignatureR; + } + + public void setOffererSignatureS(String offererSignatureS) { + this.offererSignatureS = offererSignatureS; + } + + public void setOffererPaybackAmount(Coin offererPaybackAmount) { + this.offererPaybackAmount = offererPaybackAmount; + } + + public void setTakerPaybackAmount(Coin takerPaybackAmount) { + this.takerPaybackAmount = takerPaybackAmount; + } + + public void setOffererPayoutAddress(String offererPayoutAddress) { + this.offererPayoutAddress = offererPayoutAddress; + } + + public void setState(State state) { + this.state = state; + } + + public void setTradeMessage(TradeMessage tradeMessage) { + this.tradeMessage = tradeMessage; + } + public void setSignedTakerDepositTx(Transaction signedTakerDepositTx) { + this.signedTakerDepositTx = signedTakerDepositTx; + } + + // Getters + public Trade getTrade() { + return trade; + } + + public TradeMessageService getTradeMessageService() { + return tradeMessageService; + } + + public WalletService getWalletService() { + return walletService; + } + + public BlockChainService getBlockChainService() { + return blockChainService; + } + + public SignatureService getSignatureService() { + return signatureService; + } + + public Offer getOffer() { + return offer; + } + + public String getTradeId() { + return tradeId; + } + + public BankAccount getBankAccount() { + return bankAccount; + } + + public String getAccountId() { + return accountId; + } + + public PublicKey getMessagePublicKey() { + return messagePublicKey; + } + + public Coin getTradeAmount() { + return tradeAmount; + } + + public String getTradePubKeyAsHex() { + return tradePubKeyAsHex; + } + + public ECKey getAccountKey() { + return accountKey; + } + + public PublicKey getOffererMessagePublicKey() { + return offererMessagePublicKey; + } + + public Coin getSecurityDeposit() { + return securityDeposit; + } + + public String getArbitratorPubKey() { + return arbitratorPubKey; + } + + public Peer getPeer() { + return peer; + } + + public String getPeersAccountId() { + return peersAccountId; + } + + public BankAccount getPeersBankAccount() { + return peersBankAccount; + } + + public String getPeersPubKey() { + return peersPubKey; + } + + public String getPreparedPeersDepositTxAsHex() { + return preparedPeersDepositTxAsHex; + } + + public long getPeersTxOutIndex() { + return peersTxOutIndex; + } + + public String getDepositTxAsHex() { + return depositTxAsHex; + } + + public String getOffererSignatureR() { + return offererSignatureR; + } + + public String getOffererSignatureS() { + return offererSignatureS; + } + + public Coin getOffererPaybackAmount() { + return offererPaybackAmount; + } + + public Coin getTakerPaybackAmount() { + return takerPaybackAmount; + } + + public String getOffererPayoutAddress() { + return offererPayoutAddress; + } + + public State getState() { + return state; + } + + public TradeMessage getTradeMessage() { + return tradeMessage; + } public Transaction getSignedTakerDepositTx() { + return signedTakerDepositTx; + } +} diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferProtocol.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferProtocol.java index ef07a55d99..9fa00f1eae 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferProtocol.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerTakesOfferProtocol.java @@ -17,16 +17,11 @@ package io.bitsquare.trade.protocol.trade.taker; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.btc.BlockChainService; -import io.bitsquare.btc.WalletService; -import io.bitsquare.crypto.SignatureService; +import io.bitsquare.network.Message; import io.bitsquare.network.Peer; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.Contract; import io.bitsquare.trade.Trade; -import io.bitsquare.trade.TradeMessageService; -import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener; +import io.bitsquare.trade.TradeTaskRunner; +import io.bitsquare.trade.protocol.trade.TradeMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage; @@ -41,21 +36,17 @@ import io.bitsquare.trade.protocol.trade.taker.tasks.SendSignedTakerDepositTxAsH import io.bitsquare.trade.protocol.trade.taker.tasks.SendTakeOfferFeePayedMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.SignAndPublishPayoutTx; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCommitDepositTx; +import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateBankTransferInitedMessage; +import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateDepositTxPublishedMessage; +import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateRespondToTakeOfferRequestMessage; +import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateTakerDepositPaymentRequestMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOfferFeePayment; import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOffererAccount; -import io.bitsquare.user.User; - -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.ECKey; -import org.bitcoinj.core.Transaction; - -import java.security.PublicKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.google.common.base.Preconditions.*; -import static io.bitsquare.util.Validator.*; +import static io.bitsquare.util.Validator.nonEmptyStringOf; /** @@ -68,395 +59,160 @@ import static io.bitsquare.util.Validator.*; public class SellerTakesOfferProtocol { private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferProtocol.class); - - public enum State { - Init, - GetPeerAddress, - RequestTakeOffer, - - ValidateRespondToTakeOfferRequestMessage, - PayTakeOfferFee, - SendTakeOfferFeePayedMessage, - - ValidateTakerDepositPaymentRequestMessage, - VerifyOffererAccount, - CreateAndSignContract, - PayDeposit, - SendSignedTakerDepositTxAsHex, - - ValidateDepositTxPublishedMessage, - TakerCommitDepositTx, - handleBankTransferInitedMessage, - SignAndPublishPayoutTx, - SendPayoutTxToOfferer - } - - // provided data - private final Trade trade; - private final SellerTakesOfferProtocolListener listener; - private final TradeMessageService tradeMessageService; - private final WalletService walletService; - private final BlockChainService blockChainService; - private final SignatureService signatureService; - - // derived - private final Offer offer; - private final String tradeId; - private final BankAccount bankAccount; - private final String accountId; - private final PublicKey messagePublicKey; - private final Coin tradeAmount; - private final String tradePubKeyAsHex; - private final ECKey accountKey; - private final PublicKey offererMessagePublicKey; - private final Coin securityDeposit; - private final String arbitratorPubKey; - - // written/read by task - private Peer peer; - - // written by messages, read by tasks - private String peersAccountId; - private BankAccount peersBankAccount; - private String peersPubKey; - private String preparedPeersDepositTxAsHex; - private long peersTxOutIndex; - - private String depositTxAsHex; - private String offererSignatureR; - private String offererSignatureS; - private Coin offererPaybackAmount; - private Coin takerPaybackAmount; - private String offererPayoutAddress; - - // state - private State state; + private final SellerTakesOfferModel model; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - public SellerTakesOfferProtocol(Trade trade, - SellerTakesOfferProtocolListener listener, - TradeMessageService tradeMessageService, - WalletService walletService, - BlockChainService blockChainService, - SignatureService signatureService, - User user) { - this.trade = trade; - this.listener = listener; - this.tradeMessageService = tradeMessageService; - this.walletService = walletService; - this.blockChainService = blockChainService; - this.signatureService = signatureService; - - offer = trade.getOffer(); - tradeId = trade.getId(); - tradeAmount = trade.getTradeAmount(); - securityDeposit = trade.getSecurityDeposit(); - //TODO use 1. for now - arbitratorPubKey = trade.getOffer().getArbitrators().get(0).getPubKeyAsHex(); - - offererMessagePublicKey = offer.getMessagePublicKey(); - - bankAccount = user.getCurrentBankAccount().get(); - accountId = user.getAccountId(); - messagePublicKey = user.getMessagePublicKey(); - - tradePubKeyAsHex = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString(); - accountKey = walletService.getRegistrationAddressEntry().getKey(); - - state = State.Init; + public SellerTakesOfferProtocol(SellerTakesOfferModel model) { + this.model = model; } public void start() { - getPeerAddress(); + model.getTradeMessageService().addMessageHandler(this::handleMessage); + + TradeTaskRunner sequence1 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence1 completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence1.addTasks( + GetPeerAddress.class, + RequestTakeOffer.class + ); + sequence1.run(); } - // 1. GetPeerAddress - private void getPeerAddress() { - log.debug("getPeerAddress called: state = " + state); - state = State.GetPeerAddress; - GetPeerAddress.run(this::handleGetPeerAddressResult, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey); + public void cleanup() { + model.getTradeMessageService().removeMessageHandler(this::handleMessage); } - // 2. RequestTakeOffer - private void handleGetPeerAddressResult(Peer peer) { - log.debug("handleGetPeerAddressResult called: state = " + state); - this.peer = peer; - state = State.RequestTakeOffer; - RequestTakeOffer.run(this::handleErrorMessage, tradeMessageService, peer, tradeId); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer + // Incoming message handling /////////////////////////////////////////////////////////////////////////////////////////// - // 5. handleRespondToTakeOfferRequestMessage - public void handleRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message) { - log.debug("handleRespondToTakeOfferRequestMessage called: state = " + state); + private void handleMessage(Message message, Peer sender) { + log.trace("handleNewMessage: message = " + message.getClass().getSimpleName()); + if (message instanceof TradeMessage) { + TradeMessage tradeMessage = (TradeMessage) message; + nonEmptyStringOf(tradeMessage.getTradeId()); - try { - // validation - checkState(state == State.RequestTakeOffer); - state = State.ValidateRespondToTakeOfferRequestMessage; - checkTradeId(tradeId, message); - - // apply new state - if (message.isTakeOfferRequestAccepted()) { - trade.setState(Trade.State.OFFERER_ACCEPTED); - listener.onTakeOfferRequestAccepted(); - - // next task - payTakeOfferFee(); + if (tradeMessage instanceof RespondToTakeOfferRequestMessage) { + handleTradeMessage((RespondToTakeOfferRequestMessage) tradeMessage); + } + else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) { + handleTradeMessage((TakerDepositPaymentRequestMessage) tradeMessage); + } + else if (tradeMessage instanceof DepositTxPublishedMessage) { + handleTradeMessage((DepositTxPublishedMessage) tradeMessage); + } + else if (tradeMessage instanceof BankTransferInitedMessage) { + handleTradeMessage((BankTransferInitedMessage) tradeMessage); } else { - // exit case - trade.setState(Trade.State.OFFERER_REJECTED); - listener.onTakeOfferRequestRejected(); + log.error("Incoming message not supported. " + tradeMessage); } - } catch (Throwable t) { - handleValidationFault(t); } } - // 6. PayTakeOfferFee - private void payTakeOfferFee() { - state = State.PayTakeOfferFee; - PayTakeOfferFee.run(this::handlePayTakeOfferFeeResult, this::handleFault, walletService, tradeId); + private void handleTradeMessage(RespondToTakeOfferRequestMessage tradeMessage) { + model.setTradeMessage(tradeMessage); + + TradeTaskRunner sequence2 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence2 completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence2.addTasks( + ValidateRespondToTakeOfferRequestMessage.class, + PayTakeOfferFee.class, + SendTakeOfferFeePayedMessage.class + ); + sequence2.run(); } - // 7. SendTakeOfferFeePayedMessage - private void handlePayTakeOfferFeeResult(String takeOfferFeeTxId) { - log.debug("handlePayTakeOfferFeeResult called: state = " + state); - trade.setTakeOfferFeeTxID(takeOfferFeeTxId); - state = State.SendTakeOfferFeePayedMessage; - SendTakeOfferFeePayedMessage.run(this::handleErrorMessage, peer, tradeMessageService, tradeId, takeOfferFeeTxId, tradeAmount, tradePubKeyAsHex); + private void handleTradeMessage(TakerDepositPaymentRequestMessage tradeMessage) { + model.setTradeMessage(tradeMessage); + + TradeTaskRunner sequence3 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence3 completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence3.addTasks( + ValidateTakerDepositPaymentRequestMessage.class, + VerifyOffererAccount.class, + CreateAndSignContract.class, + PayDeposit.class, + SendSignedTakerDepositTxAsHex.class + ); + sequence3.run(); } + private void handleTradeMessage(DepositTxPublishedMessage tradeMessage) { + model.setTradeMessage(tradeMessage); + + TradeTaskRunner sequence4 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence4 completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence4.addTasks( + ValidateDepositTxPublishedMessage.class, + TakerCommitDepositTx.class + ); + sequence4.run(); + } + + private void handleTradeMessage(BankTransferInitedMessage tradeMessage) { + model.setTradeMessage(tradeMessage); + + TradeTaskRunner sequence5 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence5 completed"); + model.getTrade().setState(Trade.State.FIAT_PAYMENT_STARTED); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence5.addTasks(ValidateBankTransferInitedMessage.class); + sequence5.run(); + } /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - // 11. VerifyOffererAccount - public void handleTakerDepositPaymentRequestMessage(TakerDepositPaymentRequestMessage message) { - log.debug("handleTakerDepositPaymentRequestMessage called: state = " + state); - - try { - // validation - checkState(state == State.SendTakeOfferFeePayedMessage); - state = State.ValidateTakerDepositPaymentRequestMessage; - checkTradeId(tradeId, message); - String peersAccountId = nonEmptyStringOf(message.getAccountId()); - BankAccount peersBankAccount = checkNotNull(message.getBankAccount()); - String offererPubKey = nonEmptyStringOf(message.getOffererPubKey()); - String preparedOffererDepositTxAsHex = nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex()); - long offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex()); - - // apply new state - this.peersAccountId = peersAccountId; - this.peersBankAccount = peersBankAccount; - this.peersPubKey = offererPubKey; - this.preparedPeersDepositTxAsHex = preparedOffererDepositTxAsHex; - this.peersTxOutIndex = offererTxOutIndex; - - // next task - verifyOffererAccount(); - } catch (Throwable t) { - handleValidationFault(t); - } - } - - // 12. VerifyOffererAccount - private void verifyOffererAccount() { - state = State.VerifyOffererAccount; - VerifyOffererAccount.run(this::handleVerifyOffererAccountResult, this::handleFault, blockChainService, peersAccountId, peersBankAccount); - } - - // 13. CreateAndSignContract - private void handleVerifyOffererAccountResult() { - log.debug("handleVerifyOffererAccountResult called: state = " + state); - String takeOfferFeeTxId = trade.getTakeOfferFeeTxId(); - state = State.CreateAndSignContract; - CreateAndSignContract.run(this::handleCreateAndSignContractResult, - this::handleFault, - signatureService, - offer, - tradeAmount, - takeOfferFeeTxId, - accountId, - bankAccount, - offererMessagePublicKey, - messagePublicKey, - peersAccountId, - peersBankAccount, - accountKey); - } - - // 14. PayDeposit - private void handleCreateAndSignContractResult(Contract contract, String contractAsJson, String signature) { - log.debug("handleCreateAndSignContractResult called: state = " + state); - trade.setContract(contract); - trade.setContractAsJson(contractAsJson); - trade.setTakerContractSignature(signature); - state = State.PayDeposit; - PayDeposit.run(this::handlePayDepositResult, this::handleFault, walletService, securityDeposit, tradeAmount, tradeId, - tradePubKeyAsHex, arbitratorPubKey, peersPubKey, preparedPeersDepositTxAsHex); - } - - // 15. SendSignedTakerDepositTxAsHex - private void handlePayDepositResult(Transaction signedTakerDepositTx) { - log.debug("handlePayDepositResult called: state = " + state); - String contractAsJson = trade.getContractAsJson(); - String takerContractSignature = trade.getTakerContractSignature(); - state = State.SendSignedTakerDepositTxAsHex; - SendSignedTakerDepositTxAsHex.run(this::handleErrorMessage, - peer, - tradeMessageService, - walletService, - bankAccount, - accountId, - messagePublicKey, - tradeId, - contractAsJson, - takerContractSignature, - signedTakerDepositTx, - peersTxOutIndex); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - // 21. TakerCommitDepositTx - public void handleDepositTxPublishedMessage(DepositTxPublishedMessage message) { - log.debug("onDepositTxPublishedMessage called: state = " + state); - log.debug("state " + state); - - try { - // validation - checkState(state == State.SendSignedTakerDepositTxAsHex); - state = State.ValidateDepositTxPublishedMessage; - checkTradeId(tradeId, message); - String depositTxAsHex = message.getDepositTxAsHex(); - nonEmptyStringOf(depositTxAsHex); - - // next task - takerCommitDepositTx(depositTxAsHex); - } catch (Throwable t) { - handleValidationFault(t); - } - } - - // 22. TakerCommitDepositTx - private void takerCommitDepositTx(String depositTxAsHex) { - state = State.TakerCommitDepositTx; - TakerCommitDepositTx.run(this::handleTakerCommitDepositTxResult, this::handleFault, walletService, depositTxAsHex); - } - - private void handleTakerCommitDepositTxResult(Transaction transaction) { - log.debug("handleTakerCommitDepositTxResult called: state = " + state); - trade.setDepositTx(transaction); - trade.setState(Trade.State.DEPOSIT_PUBLISHED); - listener.onDepositTxPublished(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - // 25. handleBankTransferInitedMessage - public void handleBankTransferInitedMessage(BankTransferInitedMessage message) { - log.debug("handleBankTransferInitedMessage called: state = " + state); - - try { - // validate - checkState(state == State.TakerCommitDepositTx); - checkTradeId(tradeId, message); - String depositTxAsHex = nonEmptyStringOf(message.getDepositTxAsHex()); - String offererSignatureR = nonEmptyStringOf(message.getOffererSignatureR()); - String offererSignatureS = nonEmptyStringOf(message.getOffererSignatureS()); - Coin offererPaybackAmount = positiveCoinOf(nonZeroCoinOf(message.getOffererPaybackAmount())); - Coin takerPaybackAmount = positiveCoinOf(nonZeroCoinOf(message.getTakerPaybackAmount())); - String offererPayoutAddress = nonEmptyStringOf(message.getOffererPayoutAddress()); - - // apply state - state = State.handleBankTransferInitedMessage; - this.depositTxAsHex = depositTxAsHex; - this.offererSignatureR = offererSignatureR; - this.offererSignatureS = offererSignatureS; - this.offererPaybackAmount = offererPaybackAmount; - this.takerPaybackAmount = takerPaybackAmount; - this.offererPayoutAddress = offererPayoutAddress; - - listener.onBankTransferInited(message.getTradeId()); - } catch (Throwable t) { - handleValidationFault(t); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Triggered UI event + // UI event handling /////////////////////////////////////////////////////////////////////////////////////////// // User clicked the "bank transfer received" button, so we release the funds for pay out - // 26. SignAndPublishPayoutTx - public void handleUIEventFiatReceived() { - log.debug("handleUIEventFiatReceived called: state = " + state); - checkState(state == State.handleBankTransferInitedMessage); - - state = State.SignAndPublishPayoutTx; - SignAndPublishPayoutTx.run(this::handleSignAndPublishPayoutTxResult, - this::handleFault, - walletService, - tradeId, - depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress); - - verifyOfferFeePayment(); - } - - // 27a. SendPayoutTxToOfferer - private void handleSignAndPublishPayoutTxResult(Transaction transaction, String payoutTxAsHex) { - log.debug("handleSignAndPublishPayoutTxResult called: state = " + state); - listener.onPayoutTxPublished(trade, transaction); - state = State.SendPayoutTxToOfferer; - SendPayoutTxToOfferer.run(this::handleErrorMessage, peer, tradeMessageService, tradeId, payoutTxAsHex); - } - - // 27b VerifyTakeOfferFeePayment - private void verifyOfferFeePayment() { - VerifyOfferFeePayment.run(this::handleFault, walletService, trade.getOffer().getOfferFeePaymentTxID()); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Private - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handleFault(Throwable throwable) { - trade.setFault(throwable); - trade.setState(Trade.State.FAILED); - listener.onFault(throwable, state); - } - - private void handleErrorMessage(String errorMessage) { - handleFault(new Exception(errorMessage)); - } - - private void handleValidationFault(Throwable throwable) { - throwable.printStackTrace(); - log.error(throwable.getMessage()); - handleErrorMessage("Validation of incoming message failed. Error message = " + throwable.getMessage()); + public void handleFiatReceivedUIEvent() { + TradeTaskRunner sequence6 = new TradeTaskRunner<>(model, + () -> { + log.debug("sequence6 completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence6.addTasks( + SignAndPublishPayoutTx.class, + VerifyOfferFeePayment.class, + SendPayoutTxToOfferer.class + ); + sequence6.run(); } } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java index 69cc573a52..975fb9e8e6 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/CreateAndSignContract.java @@ -17,53 +17,43 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.crypto.SignatureService; -import io.bitsquare.offer.Offer; import io.bitsquare.trade.Contract; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.util.Utilities; -import io.bitsquare.util.handlers.ExceptionHandler; - -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.ECKey; - -import java.security.PublicKey; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class CreateAndSignContract { +public class CreateAndSignContract extends Task { private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class); - public static void run(ResultHandler resultHandler, - ExceptionHandler exceptionHandler, - SignatureService signatureService, - Offer offer, - Coin tradeAmount, - String takeOfferFeeTxId, - String accountId, - BankAccount bankAccount, - PublicKey peersMessagePublicKey, - PublicKey messagePublicKey, - String peersAccountId, - BankAccount peersBankAccount, - ECKey registrationKey) { - log.trace("Run CreateAndSignContract task"); - try { - Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId, - peersBankAccount, bankAccount, peersMessagePublicKey, messagePublicKey); - - String contractAsJson = Utilities.objectToJson(contract); - String signature = signatureService.signMessage(registrationKey, contractAsJson); - resultHandler.onResult(contract, contractAsJson, signature); - } catch (Throwable t) { - log.error("Exception at sign contract " + t); - exceptionHandler.handleException(t); - } + public CreateAndSignContract(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); } - public interface ResultHandler { - void onResult(Contract contract, String contractAsJson, String signature); - } + @Override + protected void run() { + Trade trade = model.getTrade(); + Contract contract = new Contract( + model.getOffer(), + model.getTradeAmount(), + trade.getTakeOfferFeeTxId(), + model.getPeersAccountId(), + model.getAccountId(), + model.getPeersBankAccount(), + model.getBankAccount(), + model.getOffererMessagePublicKey(), + model.getMessagePublicKey()); + String contractAsJson = Utilities.objectToJson(contract); + String signature = model.getSignatureService().signMessage(model.getAccountKey(), contractAsJson); + trade.setContract(contract); + trade.setContractAsJson(contractAsJson); + trade.setTakerContractSignature(signature); + + complete(); + } } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java index c586d59c2c..86e8ade88d 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java @@ -20,16 +20,41 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.network.Peer; import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.GetPeerAddressListener; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.util.handlers.ErrorMessageHandler; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import java.security.PublicKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class GetPeerAddress { +public class GetPeerAddress extends Task { private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class); + public GetPeerAddress(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + model.getTradeMessageService().getPeerAddress(model.getOffererMessagePublicKey(), new GetPeerAddressListener() { + @Override + public void onResult(Peer peer) { + log.trace("Found peer: " + peer.toString()); + model.setPeer(peer); + complete(); + } + + @Override + public void onFailed() { + failed("DHT lookup for peer address failed.", null); + } + }); + } + + public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, TradeMessageService tradeMessageService, PublicKey messagePublicKey) { log.trace("Run GetPeerAddress task"); diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java index 29f519f237..7c4fffa52e 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayDeposit.java @@ -17,8 +17,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.btc.WalletService; -import io.bitsquare.util.handlers.ExceptionHandler; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; @@ -27,41 +28,32 @@ import org.bitcoinj.core.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class PayDeposit { +public class PayDeposit extends Task { private static final Logger log = LoggerFactory.getLogger(PayDeposit.class); - public static void run(ResultHandler resultHandler, - ExceptionHandler exceptionHandler, - WalletService walletService, - Coin securityDeposit, - Coin tradeAmount, - String tradeId, - String pubKeyForThatTrade, - String arbitratorPubKey, - String offererPubKey, - String preparedOffererDepositTxAsHex) { - log.trace("Run PayDeposit task"); + public PayDeposit(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { try { - Coin amountToPay = tradeAmount.add(securityDeposit); - Coin msOutputAmount = amountToPay.add(securityDeposit); - - Transaction signedTakerDepositTx = walletService.takerAddPaymentAndSignTx(amountToPay, + Coin amountToPay = model.getTradeAmount().add(model.getSecurityDeposit()); + Coin msOutputAmount = amountToPay.add(model.getSecurityDeposit()); + Transaction signedTakerDepositTx = model.getWalletService().takerAddPaymentAndSignTx( + amountToPay, msOutputAmount, - offererPubKey, - pubKeyForThatTrade, - arbitratorPubKey, - preparedOffererDepositTxAsHex, - tradeId); + model.getPeersPubKey(), + model.getTradePubKeyAsHex(), + model.getArbitratorPubKey(), + model.getPreparedPeersDepositTxAsHex(), + model.getTradeId()); - log.trace("signedTakerDepositTx: " + signedTakerDepositTx); - resultHandler.onResult(signedTakerDepositTx); + model.setSignedTakerDepositTx(signedTakerDepositTx); + + complete(); } catch (InsufficientMoneyException e) { - log.error("Pay deposit failed due InsufficientMoneyException " + e); - exceptionHandler.handleException(e); + failed(e); } } - - public interface ResultHandler { - void onResult(Transaction signedTakerDepositTx); - } } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java index e5c57918f9..ad60bba65c 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/PayTakeOfferFee.java @@ -17,8 +17,9 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.btc.WalletService; -import io.bitsquare.util.handlers.ExceptionHandler; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.bitcoinj.core.InsufficientMoneyException; import org.bitcoinj.core.Transaction; @@ -30,34 +31,31 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class PayTakeOfferFee { +public class PayTakeOfferFee extends Task { private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class); - public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService, - String tradeId) { - log.trace("Run PayTakeOfferFee task"); + public PayTakeOfferFee(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { try { - walletService.payTakeOfferFee(tradeId, new FutureCallback() { + model.getWalletService().payTakeOfferFee(model.getTradeId(), new FutureCallback() { @Override public void onSuccess(Transaction transaction) { log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString()); - resultHandler.onResult(transaction.getHashAsString()); + model.getTrade().setTakeOfferFeeTxID(transaction.getHashAsString()); + complete(); } @Override public void onFailure(@NotNull Throwable t) { - log.error("Pay take offer fee caused an exception: " + t); - exceptionHandler.handleException(t); + failed("Pay take offer fee caused an exception: ", t); } }); } catch (InsufficientMoneyException e) { - log.error("Pay take offer fee caused an exception: " + e); - exceptionHandler.handleException(e); + failed("Pay take offer fee caused an exception: ", e); } } - - public interface ResultHandler { - void onResult(String takeOfferFeeTxId); - } - } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java index 46c298719e..10ee4dc9be 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestTakeOffer.java @@ -17,32 +17,35 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.SendMessageListener; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage; -import io.bitsquare.util.handlers.ErrorMessageHandler; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RequestTakeOffer { +public class RequestTakeOffer extends Task { private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class); - public static void run(ErrorMessageHandler errorMessageHandler, - TradeMessageService tradeMessageService, Peer peer, String tradeId) { - log.trace("Run RequestTakeOffer task"); - tradeMessageService.sendMessage(peer, new RequestTakeOfferMessage(tradeId), + public RequestTakeOffer(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + model.getTradeMessageService().sendMessage(model.getPeer(), new RequestTakeOfferMessage(model.getTradeId()), new SendMessageListener() { @Override public void handleResult() { log.trace("Sending RequestTakeOfferMessage succeeded."); + complete(); } @Override public void handleFault() { - log.error("Sending RequestTakeOfferMessage failed."); - errorMessageHandler.handleErrorMessage("Sending RequestTakeOfferMessage failed."); + failed("Sending RequestTakeOfferMessage failed."); } }); } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java index fe0a7d7ee8..5921eb09fe 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendPayoutTxToOfferer.java @@ -17,33 +17,36 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.SendMessageListener; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage; -import io.bitsquare.util.handlers.ErrorMessageHandler; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SendPayoutTxToOfferer { +public class SendPayoutTxToOfferer extends Task { private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class); - public static void run(ErrorMessageHandler errorMessageHandler, Peer peer, TradeMessageService tradeMessageService, String tradeId, String payoutTxAsHex) { - log.trace("Run SendPayoutTxToOfferer task"); - PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(tradeId, payoutTxAsHex); - tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() { + public SendPayoutTxToOfferer(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(model.getTradeId(), model.getPayoutTxAsHex()); + model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() { @Override public void handleResult() { log.trace("PayoutTxPublishedMessage successfully arrived at peer"); + complete(); } @Override public void handleFault() { - errorMessageHandler.handleErrorMessage("Sending PayoutTxPublishedMessage failed."); + failed("Sending PayoutTxPublishedMessage failed."); } }); - } - } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java index 06612f7f15..b3ac19a102 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendSignedTakerDepositTxAsHex.java @@ -17,66 +17,55 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.btc.WalletService; -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.SendMessageListener; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage; -import io.bitsquare.util.handlers.ErrorMessageHandler; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; -import java.security.PublicKey; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SendSignedTakerDepositTxAsHex { +public class SendSignedTakerDepositTxAsHex extends Task { private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class); - public static void run(ErrorMessageHandler errorMessageHandler, - Peer peer, - TradeMessageService tradeMessageService, - WalletService walletService, - BankAccount bankAccount, - String accountId, - PublicKey messagePublicKey, - String tradeId, - String contractAsJson, - String takerContractSignature, - Transaction signedTakerDepositTx, - long offererTxOutIndex) { - log.trace("Run SendSignedTakerDepositTxAsHex task"); - long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex(); + public SendSignedTakerDepositTxAsHex(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } - RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(tradeId, - bankAccount, - accountId, - messagePublicKey, + @Override + protected void run() { + Transaction signedTakerDepositTx = model.getSignedTakerDepositTx(); + long takerTxOutIndex = model.getSignedTakerDepositTx().getInput(1).getOutpoint().getIndex(); + + RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage( + model.getTradeId(), + model.getBankAccount(), + model.getAccountId(), + model.getMessagePublicKey(), Utils.HEX.encode(signedTakerDepositTx.bitcoinSerialize()), Utils.HEX.encode(signedTakerDepositTx.getInput(1).getScriptBytes()), - Utils.HEX.encode(signedTakerDepositTx.getInput(1) - .getConnectedOutput() - .getParentTransaction() - .bitcoinSerialize()), - contractAsJson, - takerContractSignature, - walletService.getAddressInfoByTradeID(tradeId).getAddressString(), + Utils.HEX.encode(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()), + model.getTrade().getContractAsJson(), + model.getTrade().getTakerContractSignature(), + model.getWalletService().getAddressInfoByTradeID(model.getTradeId()).getAddressString(), takerTxOutIndex, - offererTxOutIndex); - tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() { + model.getPeersTxOutIndex()); + + model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() { @Override public void handleResult() { - log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer"); + complete(); } @Override public void handleFault() { - log.error("RequestOffererDepositPublicationMessage did not arrive at peer"); - errorMessageHandler.handleErrorMessage("RequestOffererDepositPublicationMessage did not arrive at peer"); + failed("Sending RequestOffererDepositPublicationMessage failed"); } }); } + } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedMessage.java index 14e860fb6d..8804671d19 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedMessage.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SendTakeOfferFeePayedMessage.java @@ -17,42 +17,42 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.SendMessageListener; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage; -import io.bitsquare.util.handlers.ErrorMessageHandler; - -import org.bitcoinj.core.Coin; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SendTakeOfferFeePayedMessage { +public class SendTakeOfferFeePayedMessage extends Task { private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class); - public static void run(ErrorMessageHandler errorMessageHandler, - Peer peer, - TradeMessageService tradeMessageService, - String tradeId, - String takeOfferFeeTxId, - Coin tradeAmount, - String tradePubKeyAsHex) { - log.trace("Run SendTakeOfferFeePayedMessage task"); - TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, takeOfferFeeTxId, tradeAmount, - tradePubKeyAsHex); + public SendTakeOfferFeePayedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } - tradeMessageService.sendMessage(peer, msg, new SendMessageListener() { + @Override + protected void run() { + TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage( + model.getTradeId(), + model.getTrade().getTakeOfferFeeTxId(), + model.getTradeAmount(), + model.getTradePubKeyAsHex() + ); + + model.getTradeMessageService().sendMessage(model.getPeer(), msg, new SendMessageListener() { @Override public void handleResult() { - log.trace("TakeOfferFeePayedMessage succeeded."); + log.trace("Sending TakeOfferFeePayedMessage succeeded."); + complete(); } @Override public void handleFault() { - log.error("Sending TakeOfferFeePayedMessage failed."); - errorMessageHandler.handleErrorMessage("Sending TakeOfferFeePayedMessage failed."); + failed("Sending TakeOfferFeePayedMessage failed."); } }); } -} +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java index 742fc2fffd..92cd8502eb 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/SignAndPublishPayoutTx.java @@ -17,10 +17,12 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.btc.WalletService; -import io.bitsquare.util.handlers.ExceptionHandler; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; -import org.bitcoinj.core.Coin; +import org.bitcoinj.core.AddressFormatException; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Utils; @@ -31,48 +33,43 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SignAndPublishPayoutTx { +public class SignAndPublishPayoutTx extends Task { private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class); - public static void run(ResultHandler resultHandler, - ExceptionHandler exceptionHandler, - WalletService walletService, - String tradeId, - String depositTxAsHex, - String offererSignatureR, - String offererSignatureS, - Coin offererPaybackAmount, - Coin takerPaybackAmount, - String offererPayoutAddress) { - log.trace("Run SignAndPublishPayoutTx task"); + public SignAndPublishPayoutTx(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { try { - walletService.takerSignsAndSendsTx(depositTxAsHex, - offererSignatureR, - offererSignatureS, - offererPaybackAmount, - takerPaybackAmount, - offererPayoutAddress, - tradeId, + model.getWalletService().takerSignsAndSendsTx(model.getDepositTxAsHex(), + model.getOffererSignatureR(), + model.getOffererSignatureS(), + model.getOffererPaybackAmount(), + model.getTakerPaybackAmount(), + model.getOffererPayoutAddress(), + model.getTradeId(), new FutureCallback() { @Override public void onSuccess(Transaction transaction) { log.debug("takerSignsAndSendsTx " + transaction); String payoutTxAsHex = Utils.HEX.encode(transaction.bitcoinSerialize()); - resultHandler.onResult(transaction, payoutTxAsHex); + + model.setPayoutTx(transaction); + model.setPayoutTxAsHex(payoutTxAsHex); + model.getTrade().setState(Trade.State.PAYOUT_PUBLISHED); + + complete(); } @Override public void onFailure(@NotNull Throwable t) { - exceptionHandler.handleException(t); + failed(t); } }); - } catch (Exception e) { - exceptionHandler.handleException(e); + } catch (AddressFormatException e) { + failed(e); } } - - public interface ResultHandler { - void onResult(Transaction transaction, String payoutTxAsHex); - } - } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/TakerCommitDepositTx.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/TakerCommitDepositTx.java index 3796ce98f4..1037d36e6f 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/TakerCommitDepositTx.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/TakerCommitDepositTx.java @@ -17,29 +17,30 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.btc.WalletService; -import io.bitsquare.util.handlers.ExceptionHandler; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.bitcoinj.core.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TakerCommitDepositTx { +public class TakerCommitDepositTx extends Task { private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class); - public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService, String depositTxAsHex) { - log.trace("Run PayDeposit task"); - try { - Transaction transaction = walletService.takerCommitDepositTx(depositTxAsHex); - resultHandler.onResult(transaction); - } catch (Exception e) { - log.error("takerCommitDepositTx failed with exception " + e); - exceptionHandler.handleException(e); - } + public TakerCommitDepositTx(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); } - public interface ResultHandler { - void onResult(Transaction transaction); + @Override + protected void run() { + Transaction transaction = model.getWalletService().takerCommitDepositTx(model.getDepositTxAsHex()); + + model.getTrade().setDepositTx(transaction); + model.getTrade().setState(Trade.State.DEPOSIT_PUBLISHED); + + complete(); } } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateBankTransferInitedMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateBankTransferInitedMessage.java new file mode 100644 index 0000000000..e1d2db26e4 --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateBankTransferInitedMessage.java @@ -0,0 +1,58 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.trade.taker.tasks; + +import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.checkState; +import static io.bitsquare.util.Validator.*; + +public class ValidateBankTransferInitedMessage extends Task { + private static final Logger log = LoggerFactory.getLogger(ValidateBankTransferInitedMessage.class); + + public ValidateBankTransferInitedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + try { + checkState(model.getTrade().getPreviousTask() == TakerCommitDepositTx.class); + checkTradeId(model.getTradeId(), model.getTradeMessage()); + BankTransferInitedMessage message = (BankTransferInitedMessage) model.getTradeMessage(); + + model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex())); + model.setOffererSignatureR(nonEmptyStringOf(message.getOffererSignatureR())); + model.setOffererSignatureS(nonEmptyStringOf(message.getOffererSignatureS())); + model.setOffererPaybackAmount(positiveCoinOf(nonZeroCoinOf(message.getOffererPaybackAmount()))); + model.setTakerPaybackAmount(positiveCoinOf(nonZeroCoinOf(message.getTakerPaybackAmount()))); + model.setOffererPayoutAddress(nonEmptyStringOf(message.getOffererPayoutAddress())); + + // TODO listener.onBankTransferInited(message.getTradeId()); + complete(); + } catch (Throwable t) { + failed(t); + } + } +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateDepositTxPublishedMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateDepositTxPublishedMessage.java new file mode 100644 index 0000000000..5e11db6cc2 --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateDepositTxPublishedMessage.java @@ -0,0 +1,52 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.trade.taker.tasks; + +import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.checkState; +import static io.bitsquare.util.Validator.*; + +public class ValidateDepositTxPublishedMessage extends Task { + private static final Logger log = LoggerFactory.getLogger(ValidateDepositTxPublishedMessage.class); + + public ValidateDepositTxPublishedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + try { + checkState(model.getTrade().getPreviousTask() == SendSignedTakerDepositTxAsHex.class); + checkTradeId(model.getTradeId(), model.getTradeMessage()); + + DepositTxPublishedMessage message = (DepositTxPublishedMessage) model.getTradeMessage(); + model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex())); + + complete(); + } catch (Throwable t) { + failed("Validation for DepositTxPublishedMessage failed.", t); + } + } +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateRespondToTakeOfferRequestMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateRespondToTakeOfferRequestMessage.java new file mode 100644 index 0000000000..b0f9e0eeaa --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateRespondToTakeOfferRequestMessage.java @@ -0,0 +1,57 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.trade.taker.tasks; + +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.checkState; +import static io.bitsquare.util.Validator.checkTradeId; + +public class ValidateRespondToTakeOfferRequestMessage extends Task { + private static final Logger log = LoggerFactory.getLogger(ValidateRespondToTakeOfferRequestMessage.class); + + public ValidateRespondToTakeOfferRequestMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + try { + checkState(model.getTrade().getPreviousTask() == RequestTakeOffer.class); + checkTradeId(model.getTradeId(), model.getTradeMessage()); + + if (((RespondToTakeOfferRequestMessage) model.getTradeMessage()).isTakeOfferRequestAccepted()) { + model.getTrade().setState(Trade.State.OFFERER_ACCEPTED); + complete(); + } + else { + model.getTrade().setState(Trade.State.OFFERER_REJECTED); + failed("Requested offer rejected because it is not available anymore."); + } + } catch (Throwable t) { + failed("Validation for RespondToTakeOfferRequestMessage failed.", t); + } + } +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateTakerDepositPaymentRequestMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateTakerDepositPaymentRequestMessage.java new file mode 100644 index 0000000000..567dcf4c3e --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/ValidateTakerDepositPaymentRequestMessage.java @@ -0,0 +1,55 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.trade.taker.tasks; + +import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.common.base.Preconditions.*; +import static io.bitsquare.util.Validator.*; + +public class ValidateTakerDepositPaymentRequestMessage extends Task { + private static final Logger log = LoggerFactory.getLogger(ValidateTakerDepositPaymentRequestMessage.class); + + public ValidateTakerDepositPaymentRequestMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + try { + checkState(model.getTrade().getPreviousTask() == SendTakeOfferFeePayedMessage.class); + checkTradeId(model.getTradeId(), model.getTradeMessage()); + TakerDepositPaymentRequestMessage message = (TakerDepositPaymentRequestMessage) model.getTradeMessage(); + model.setPeersAccountId(nonEmptyStringOf(message.getAccountId())); + model.setPeersBankAccount(checkNotNull(message.getBankAccount())); + model.setPeersPubKey(nonEmptyStringOf(message.getOffererPubKey())); + model.setPreparedPeersDepositTxAsHex(nonEmptyStringOf(message.getPreparedOffererDepositTxAsHex())); + model.setPeersTxOutIndex(nonNegativeLongOf(message.getOffererTxOutIndex())); + + complete(); + } catch (Throwable t) { + failed("Validation for TakerDepositPaymentRequestMessage failed.", t); + } + } +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOfferFeePayment.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOfferFeePayment.java index 0c809f18e2..10b084e950 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOfferFeePayment.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOfferFeePayment.java @@ -17,23 +17,27 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.btc.WalletService; -import io.bitsquare.util.handlers.ExceptionHandler; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VerifyOfferFeePayment { +public class VerifyOfferFeePayment extends Task { private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class); - public static void run(ExceptionHandler exceptionHandler, WalletService walletService, - String takeOfferFeeTxId) { - log.trace("Run VerifyOfferFeePayment task"); - //TODO mocked yet, need a confidence listeners - int numOfPeersSeenTx = walletService.getNumOfPeersSeenTx(takeOfferFeeTxId); + public VerifyOfferFeePayment(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + //TODO impl. missing + int numOfPeersSeenTx = model.getWalletService().getNumOfPeersSeenTx(model.getTrade().getTakeOfferFeeTxId()); /* if (numOfPeersSeenTx > 2) { resultHandler.handleResult(); }*/ + complete(); } - } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java index 17e31a1b92..3e99675a2a 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/VerifyOffererAccount.java @@ -17,21 +17,32 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; -import io.bitsquare.bank.BankAccount; -import io.bitsquare.btc.BlockChainService; -import io.bitsquare.trade.protocol.trade.shared.tasks.VerifyPeerAccount; -import io.bitsquare.util.handlers.ExceptionHandler; -import io.bitsquare.util.handlers.ResultHandler; +import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VerifyOffererAccount { +public class VerifyOffererAccount extends Task { private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class); - public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, - BlockChainService blockChainService, String peersAccountId, BankAccount peersBankAccount) { - log.trace("Run VerifyOffererAccount task"); - VerifyPeerAccount.run(resultHandler, exceptionHandler, blockChainService, peersAccountId, peersBankAccount); + public VerifyOffererAccount(TaskRunner taskHandler, SellerTakesOfferModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + if (model.getBlockChainService().verifyAccountRegistration()) { + if (model.getBlockChainService().isAccountBlackListed(model.getPeersAccountId(), model.getPeersBankAccount())) { + failed("Taker is blacklisted."); + } + else { + complete(); + } + } + else { + failed("Account registration validation for peer faultHandler.onFault."); + } } } diff --git a/gui/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java b/gui/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java index 6235c93d3d..c02ffefc72 100644 --- a/gui/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java +++ b/gui/src/main/java/io/bitsquare/trade/tomp2p/TomP2PTradeMessageService.java @@ -23,7 +23,7 @@ import io.bitsquare.network.tomp2p.TomP2PNode; import io.bitsquare.network.tomp2p.TomP2PPeer; import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.GetPeerAddressListener; -import io.bitsquare.trade.listeners.ProcessNewMessageListener; +import io.bitsquare.trade.listeners.MessageHandler; import io.bitsquare.trade.listeners.SendMessageListener; import io.bitsquare.user.User; @@ -58,7 +58,7 @@ public class TomP2PTradeMessageService implements TradeMessageService { private final TomP2PNode tomP2PNode; private final User user; - private final List processNewMessageListeners = new ArrayList<>(); + private final List messageHandlers = new ArrayList<>(); private Executor executor; @@ -133,12 +133,12 @@ public class TomP2PTradeMessageService implements TradeMessageService { // Event Listeners /////////////////////////////////////////////////////////////////////////////////////////// - public void addHandleNewMessageListener(ProcessNewMessageListener listener) { - processNewMessageListeners.add(listener); + public void addMessageHandler(MessageHandler listener) { + messageHandlers.add(listener); } - public void removeHandleNewMessageListener(ProcessNewMessageListener listener) { - processNewMessageListeners.remove(listener); + public void removeMessageHandler(MessageHandler listener) { + messageHandlers.remove(listener); } @@ -149,7 +149,7 @@ public class TomP2PTradeMessageService implements TradeMessageService { @Override public void handleMessage(Object message, Peer sender) { if (message instanceof Message && sender instanceof TomP2PPeer) { - executor.execute(() -> processNewMessageListeners.stream().forEach(e -> + executor.execute(() -> messageHandlers.stream().forEach(e -> e.handleMessage((Message) message, sender))); } } diff --git a/gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java b/gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java new file mode 100644 index 0000000000..10ecc1fbdd --- /dev/null +++ b/gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java @@ -0,0 +1,25 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.util.tasks; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SharedModel { + private static final Logger log = LoggerFactory.getLogger(SharedModel.class); +} diff --git a/gui/src/main/java/io/bitsquare/util/tasks/Task.java b/gui/src/main/java/io/bitsquare/util/tasks/Task.java new file mode 100644 index 0000000000..950d5bf099 --- /dev/null +++ b/gui/src/main/java/io/bitsquare/util/tasks/Task.java @@ -0,0 +1,56 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.util.tasks; + +import org.jetbrains.annotations.NotNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Task { + private static final Logger log = LoggerFactory.getLogger(Task.class); + + private final TaskRunner taskHandler; + protected final T model; + + public Task(TaskRunner taskHandler, T model) { + this.taskHandler = taskHandler; + this.model = model; + } + + protected void run() { + } + + protected void complete() { + taskHandler.complete(); + } + + protected void failed(String message) { + taskHandler.handleFault(message); + } + + protected void failed(String message, @NotNull Throwable throwable) { + log.error(message); + log.error(throwable.getMessage()); + taskHandler.handleFault(message, throwable); + } + + protected void failed(@NotNull Throwable throwable) { + taskHandler.handleFault(throwable.getMessage(), throwable); + } +} diff --git a/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java b/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java new file mode 100644 index 0000000000..315afb69bf --- /dev/null +++ b/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java @@ -0,0 +1,106 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.util.tasks; + +import io.bitsquare.util.handlers.FaultHandler; +import io.bitsquare.util.handlers.ResultHandler; + +import java.util.Arrays; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.jetbrains.annotations.NotNull; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TaskRunner { + private static final Logger log = LoggerFactory.getLogger(TaskRunner.class); + + private final Queue tasks = new LinkedBlockingQueue<>(); + protected final T sharedModel; + private final ResultHandler resultHandler; + private final FaultHandler faultHandler; + + private boolean failed = false; + private Class currentTask; + private Class previousTask; + + public TaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { + this.sharedModel = sharedModel; + this.resultHandler = resultHandler; + this.faultHandler = faultHandler; + } + + public void run() { + next(); + } + + public Class getCurrentTask() { + return currentTask; + } + + protected void next() { + if (!failed) { + if (tasks.size() > 0) { + try { + setCurrentTask(tasks.poll()); + log.trace("Run task: " + currentTask.getSimpleName()); + currentTask.getDeclaredConstructor(TaskRunner.class, sharedModel.getClass()).newInstance(this, sharedModel).run(); + setPreviousTask(currentTask); + } catch (Throwable t) { + t.printStackTrace(); + faultHandler.handleFault(t.getMessage(), t); + } + } + else { + resultHandler.handleResult(); + } + } + } + + protected void setPreviousTask(Class task) { + previousTask = task; + } + + protected void setCurrentTask(Class task) { + currentTask = task; + } + + public void addTask(Class task) { + tasks.add(task); + } + + public void addTasks(Class... items) { + tasks.addAll(Arrays.asList(items)); + } + + public void complete() { + next(); + } + + public void handleFault(String message) { + handleFault(message, new Exception(message)); + } + + public void handleFault(String message, @NotNull Throwable throwable) { + log.debug(throwable.getMessage()); + failed = true; + faultHandler.handleFault(message, throwable); + } +} diff --git a/gui/src/test/java/io/bitsquare/trade/protocol/placeoffer/TaskRunner.java b/gui/src/test/java/io/bitsquare/trade/protocol/placeoffer/TaskRunner.java new file mode 100644 index 0000000000..4d3921c02b --- /dev/null +++ b/gui/src/test/java/io/bitsquare/trade/protocol/placeoffer/TaskRunner.java @@ -0,0 +1,136 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare 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. + * + * Bitsquare 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 Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.placeoffer; + +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.junit.Test; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TaskRunner { + private static final Logger log = LoggerFactory.getLogger(TaskRunner.class); + + private Queue tasks; + private SharedModel sharedModel = new SharedModel(); + private FaultHandler faultHandler; + private ResultHandler taskCompleted; + private final boolean[] failed = {false}; + + @Test + public void test() { + // Task1.run(); + //Task2.run(); + + tasks = new LinkedBlockingQueue<>(); + tasks.add(Task1.class); + tasks.add(Task2.class); + + faultHandler = (throwable) -> { + log.debug(throwable.getMessage()); + failed[0] = true; + }; + taskCompleted = () -> { + next(); + }; + next(); + /* ResultHandler handleResult = () -> { + Class task = tasks.poll(); + try { + if (!failed[0]) + ((Task) task.newInstance()).run(sharedModel, taskCompleted, faultHandler); + } catch (InstantiationException e1) { + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + e1.printStackTrace(); + } + + };*/ + + + + /* tasks.stream().forEach((e) -> { + try { + ((Task) e.newInstance()).run(sharedModel, faultHandler); + } catch (InstantiationException e1) { + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + e1.printStackTrace(); + } + });*/ + } + + private void next() { + Class task = tasks.poll(); + if (task != null) { + try { + if (!failed[0]) + ((Task) task.newInstance()).run(sharedModel, taskCompleted, faultHandler); + } catch (InstantiationException e1) { + e1.printStackTrace(); + } catch (IllegalAccessException e1) { + e1.printStackTrace(); + } + } + } +} + +interface ResultHandler { + void handleResult(); +} + +interface FaultHandler { + void handleFault(Throwable throwable); +} + +class SharedModel { + public int data = 42; +} + +class Task { + + protected void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { + } + +} + +class Task1 extends Task { + private static final Logger log = LoggerFactory.getLogger(Task1.class); + + @Override + public void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { + log.debug("run " + Task1.class); + log.debug("data " + sharedModel.data); + // faultHandler.handleFault(new Exception("test")); + sharedModel.data++; + resultHandler.handleResult(); + } +} + +class Task2 extends Task { + private static final Logger log = LoggerFactory.getLogger(Task2.class); + + @Override + public void run(SharedModel sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { + log.debug("run " + Task2.class); + log.debug("data " + sharedModel.data); + resultHandler.handleResult(); + } +} \ No newline at end of file