mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-06 21:13:59 -04:00
Refactor tasks with taskrunner
This commit is contained in:
parent
033709f288
commit
ef4937bba1
@ -167,6 +167,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||
}
|
||||
|
||||
void fiatPaymentReceived() {
|
||||
getTrade().setState(Trade.State.FIAT_PAYMENT_RECEIVED);
|
||||
tradeManager.fiatPaymentReceived(getTrade().getId());
|
||||
}
|
||||
|
||||
|
@ -230,11 +230,11 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT :
|
||||
State.TAKER_SELLER_WAIT_PAYMENT_STARTED);
|
||||
break;
|
||||
case PAYMENT_STARTED:
|
||||
case FIAT_PAYMENT_STARTED:
|
||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
|
||||
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
|
||||
break;
|
||||
case COMPLETED:
|
||||
case PAYOUT_PUBLISHED:
|
||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
|
||||
break;
|
||||
case FAILED:
|
||||
|
@ -162,12 +162,12 @@ class TakeOfferDataModel implements Activatable, DataModel {
|
||||
" That should not happen and needs more investigation why it can happen.");
|
||||
}
|
||||
break;
|
||||
case PAYMENT_STARTED:
|
||||
case FIAT_PAYMENT_STARTED:
|
||||
break;
|
||||
case FAILED:
|
||||
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
|
||||
break;
|
||||
case COMPLETED:
|
||||
case PAYOUT_PUBLISHED:
|
||||
break;
|
||||
default:
|
||||
log.error("Unhandled trade state: " + newValue);
|
||||
|
@ -76,7 +76,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
@FXML InputTextField amountTextField;
|
||||
@FXML AddressTextField addressTextField;
|
||||
@FXML BalanceTextField balanceTextField;
|
||||
@FXML ProgressIndicator takeOfferSpinner;
|
||||
@FXML ProgressIndicator takeOfferSpinner, isOfferAvailableProgressIndicator;
|
||||
@FXML InfoDisplay advancedInfoDisplay, fundsBoxInfoDisplay;
|
||||
@FXML TitledGroupBg priceAmountPane, payFundsPane, showDetailsPane;
|
||||
@FXML Button showPaymentInfoScreenButton, showAdvancedSettingsButton, takeOfferButton;
|
||||
@ -88,7 +88,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
bankAccountTypeLabel, bankAccountCurrencyLabel, bankAccountCountyLabel, acceptedCountriesLabel,
|
||||
acceptedLanguagesLabel, acceptedArbitratorsLabel, amountBtcLabel, priceDescriptionLabel,
|
||||
volumeDescriptionLabel, takeOfferSpinnerInfoLabel;
|
||||
@FXML ProgressIndicator isOfferAvailableProgressIndicator;
|
||||
|
||||
private ImageView expand;
|
||||
private ImageView collapse;
|
||||
|
@ -18,6 +18,7 @@
|
||||
package io.bitsquare.trade;
|
||||
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.util.tasks.Task;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
@ -32,6 +33,24 @@ import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
public class Trade implements Serializable {
|
||||
private static final long serialVersionUID = -8275323072940974077L;
|
||||
private Class<? extends Task> previousTask;
|
||||
private Class<? extends Task> currentTask;
|
||||
|
||||
public void setCurrentTask(Class<? extends Task> currentTask) {
|
||||
this.currentTask = currentTask;
|
||||
}
|
||||
|
||||
public Class<? extends Task> getCurrentTask() {
|
||||
return currentTask;
|
||||
}
|
||||
|
||||
public void setPreviousTask(Class<? extends Task> previousTask) {
|
||||
this.previousTask = previousTask;
|
||||
}
|
||||
|
||||
public Class<? extends Task> 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;
|
||||
|
@ -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<String, Trade>) 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
56
gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java
Normal file
56
gui/src/main/java/io/bitsquare/trade/TradeTaskRunner.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<T extends TradeSharedModel> extends TaskRunner<TradeSharedModel> {
|
||||
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<? extends Task> task) {
|
||||
super.setCurrentTask(task);
|
||||
sharedModel.getTrade().setCurrentTask(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setPreviousTask(Class<? extends Task> 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -15,24 +15,24 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
@ -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<SellerTakesOfferModel> 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<SellerTakesOfferModel> 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<SellerTakesOfferModel> 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<SellerTakesOfferModel> 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<SellerTakesOfferModel> 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<SellerTakesOfferModel> sequence6 = new TradeTaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("sequence6 completed");
|
||||
},
|
||||
(message, throwable) -> {
|
||||
log.error(message);
|
||||
}
|
||||
);
|
||||
sequence6.addTasks(
|
||||
SignAndPublishPayoutTx.class,
|
||||
VerifyOfferFeePayment.class,
|
||||
SendPayoutTxToOfferer.class
|
||||
);
|
||||
sequence6.run();
|
||||
}
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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");
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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<Transaction>() {
|
||||
model.getWalletService().payTakeOfferFee(model.getTradeId(), new FutureCallback<Transaction>() {
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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.");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -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<SellerTakesOfferModel> {
|
||||
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<Transaction>() {
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<SellerTakesOfferModel> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<SellerTakesOfferModel> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<SellerTakesOfferModel> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<SellerTakesOfferModel> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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<SellerTakesOfferModel> {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<SellerTakesOfferModel> {
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<ProcessNewMessageListener> processNewMessageListeners = new ArrayList<>();
|
||||
private final List<MessageHandler> 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)));
|
||||
}
|
||||
}
|
||||
|
25
gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java
Normal file
25
gui/src/main/java/io/bitsquare/util/tasks/SharedModel.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
56
gui/src/main/java/io/bitsquare/util/tasks/Task.java
Normal file
56
gui/src/main/java/io/bitsquare/util/tasks/Task.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.util.tasks;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Task<T extends SharedModel> {
|
||||
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);
|
||||
}
|
||||
}
|
106
gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java
Normal file
106
gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<T extends SharedModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(TaskRunner.class);
|
||||
|
||||
private final Queue<Class> tasks = new LinkedBlockingQueue<>();
|
||||
protected final T sharedModel;
|
||||
private final ResultHandler resultHandler;
|
||||
private final FaultHandler faultHandler;
|
||||
|
||||
private boolean failed = false;
|
||||
private Class<? extends Task> currentTask;
|
||||
private Class<? extends Task> previousTask;
|
||||
|
||||
public TaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||
this.sharedModel = sharedModel;
|
||||
this.resultHandler = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
next();
|
||||
}
|
||||
|
||||
public Class<? extends Task> 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<? extends Task> task) {
|
||||
previousTask = task;
|
||||
}
|
||||
|
||||
protected void setCurrentTask(Class<? extends Task> task) {
|
||||
currentTask = task;
|
||||
}
|
||||
|
||||
public void addTask(Class<? extends Task> task) {
|
||||
tasks.add(task);
|
||||
}
|
||||
|
||||
public void addTasks(Class<? extends Task>... 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);
|
||||
}
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Class> 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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user