mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-26 08:25:23 -04:00
Refactor tasks with taskrunner
This commit is contained in:
parent
033709f288
commit
ef4937bba1
33 changed files with 1417 additions and 719 deletions
|
@ -167,6 +167,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fiatPaymentReceived() {
|
void fiatPaymentReceived() {
|
||||||
|
getTrade().setState(Trade.State.FIAT_PAYMENT_RECEIVED);
|
||||||
tradeManager.fiatPaymentReceived(getTrade().getId());
|
tradeManager.fiatPaymentReceived(getTrade().getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -230,11 +230,11 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
||||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT :
|
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT :
|
||||||
State.TAKER_SELLER_WAIT_PAYMENT_STARTED);
|
State.TAKER_SELLER_WAIT_PAYMENT_STARTED);
|
||||||
break;
|
break;
|
||||||
case PAYMENT_STARTED:
|
case FIAT_PAYMENT_STARTED:
|
||||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
|
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
|
||||||
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
|
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
|
||||||
break;
|
break;
|
||||||
case COMPLETED:
|
case PAYOUT_PUBLISHED:
|
||||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
|
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
|
||||||
break;
|
break;
|
||||||
case FAILED:
|
case FAILED:
|
||||||
|
|
|
@ -162,12 +162,12 @@ class TakeOfferDataModel implements Activatable, DataModel {
|
||||||
" That should not happen and needs more investigation why it can happen.");
|
" That should not happen and needs more investigation why it can happen.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PAYMENT_STARTED:
|
case FIAT_PAYMENT_STARTED:
|
||||||
break;
|
break;
|
||||||
case FAILED:
|
case FAILED:
|
||||||
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
|
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
|
||||||
break;
|
break;
|
||||||
case COMPLETED:
|
case PAYOUT_PUBLISHED:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log.error("Unhandled trade state: " + newValue);
|
log.error("Unhandled trade state: " + newValue);
|
||||||
|
|
|
@ -76,7 +76,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
@FXML InputTextField amountTextField;
|
@FXML InputTextField amountTextField;
|
||||||
@FXML AddressTextField addressTextField;
|
@FXML AddressTextField addressTextField;
|
||||||
@FXML BalanceTextField balanceTextField;
|
@FXML BalanceTextField balanceTextField;
|
||||||
@FXML ProgressIndicator takeOfferSpinner;
|
@FXML ProgressIndicator takeOfferSpinner, isOfferAvailableProgressIndicator;
|
||||||
@FXML InfoDisplay advancedInfoDisplay, fundsBoxInfoDisplay;
|
@FXML InfoDisplay advancedInfoDisplay, fundsBoxInfoDisplay;
|
||||||
@FXML TitledGroupBg priceAmountPane, payFundsPane, showDetailsPane;
|
@FXML TitledGroupBg priceAmountPane, payFundsPane, showDetailsPane;
|
||||||
@FXML Button showPaymentInfoScreenButton, showAdvancedSettingsButton, takeOfferButton;
|
@FXML Button showPaymentInfoScreenButton, showAdvancedSettingsButton, takeOfferButton;
|
||||||
|
@ -88,7 +88,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||||
bankAccountTypeLabel, bankAccountCurrencyLabel, bankAccountCountyLabel, acceptedCountriesLabel,
|
bankAccountTypeLabel, bankAccountCurrencyLabel, bankAccountCountyLabel, acceptedCountriesLabel,
|
||||||
acceptedLanguagesLabel, acceptedArbitratorsLabel, amountBtcLabel, priceDescriptionLabel,
|
acceptedLanguagesLabel, acceptedArbitratorsLabel, amountBtcLabel, priceDescriptionLabel,
|
||||||
volumeDescriptionLabel, takeOfferSpinnerInfoLabel;
|
volumeDescriptionLabel, takeOfferSpinnerInfoLabel;
|
||||||
@FXML ProgressIndicator isOfferAvailableProgressIndicator;
|
|
||||||
|
|
||||||
private ImageView expand;
|
private ImageView expand;
|
||||||
private ImageView collapse;
|
private ImageView collapse;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.trade;
|
package io.bitsquare.trade;
|
||||||
|
|
||||||
import io.bitsquare.offer.Offer;
|
import io.bitsquare.offer.Offer;
|
||||||
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
|
@ -32,6 +33,24 @@ import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
|
||||||
public class Trade implements Serializable {
|
public class Trade implements Serializable {
|
||||||
private static final long serialVersionUID = -8275323072940974077L;
|
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
|
// Enum
|
||||||
|
@ -43,9 +62,10 @@ public class Trade implements Serializable {
|
||||||
OFFERER_REJECTED, /* For taker only*/
|
OFFERER_REJECTED, /* For taker only*/
|
||||||
DEPOSIT_PUBLISHED,
|
DEPOSIT_PUBLISHED,
|
||||||
DEPOSIT_CONFIRMED,
|
DEPOSIT_CONFIRMED,
|
||||||
PAYMENT_STARTED,
|
FIAT_PAYMENT_STARTED,
|
||||||
FAILED,
|
FIAT_PAYMENT_RECEIVED,
|
||||||
COMPLETED
|
PAYOUT_PUBLISHED,
|
||||||
|
FAILED
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Offer offer;
|
private final Offer offer;
|
||||||
|
|
|
@ -31,7 +31,6 @@ import io.bitsquare.offer.OpenOffer;
|
||||||
import io.bitsquare.persistence.Persistence;
|
import io.bitsquare.persistence.Persistence;
|
||||||
import io.bitsquare.trade.handlers.TransactionResultHandler;
|
import io.bitsquare.trade.handlers.TransactionResultHandler;
|
||||||
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener;
|
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener;
|
||||||
import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener;
|
|
||||||
import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol;
|
import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol;
|
||||||
import io.bitsquare.trade.protocol.trade.OfferMessage;
|
import io.bitsquare.trade.protocol.trade.OfferMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.TradeMessage;
|
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.messages.TakerDepositPaymentRequestMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.IsOfferAvailableResponse;
|
import io.bitsquare.trade.protocol.trade.offerer.tasks.IsOfferAvailableResponse;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.RequestIsOfferAvailableProtocol;
|
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.SellerTakesOfferProtocol;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
|
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.RequestIsOfferAvailableMessage;
|
import io.bitsquare.trade.protocol.trade.taker.messages.RequestIsOfferAvailableMessage;
|
||||||
|
@ -137,7 +137,7 @@ public class TradeManager {
|
||||||
closedTrades.putAll((Map<String, Trade>) closedTradesObject);
|
closedTrades.putAll((Map<String, Trade>) closedTradesObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
tradeMessageService.addHandleNewMessageListener(this::handleNewMessage);
|
tradeMessageService.addMessageHandler(this::handleNewMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ public class TradeManager {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
tradeMessageService.removeHandleNewMessageListener(this::handleNewMessage);
|
tradeMessageService.removeMessageHandler(this::handleNewMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -239,6 +239,11 @@ public class TradeManager {
|
||||||
pendingTrades.remove(trade.getId());
|
pendingTrades.remove(trade.getId());
|
||||||
persistPendingTrades();
|
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);
|
closedTrades.put(trade.getId(), trade);
|
||||||
persistClosedTrades();
|
persistClosedTrades();
|
||||||
}
|
}
|
||||||
|
@ -274,9 +279,9 @@ public class TradeManager {
|
||||||
public void onOfferAccepted(Offer offer) {
|
public void onOfferAccepted(Offer offer) {
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
//TODO do that later
|
//TODO do that later
|
||||||
requestRemoveOpenOffer(offer.getId(),
|
/*requestRemoveOpenOffer(offer.getId(),
|
||||||
() -> log.debug("remove offer was successful"),
|
() -> log.debug("remove offer was successful"),
|
||||||
(message) -> log.error(message));
|
(message) -> log.error(message));*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -295,7 +300,7 @@ public class TradeManager {
|
||||||
@Override
|
@Override
|
||||||
public void onPayoutTxPublished(Transaction payoutTx) {
|
public void onPayoutTxPublished(Transaction payoutTx) {
|
||||||
trade.setPayoutTx(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)
|
// We close the trade when the user has withdrawn his trade funds (see #283)
|
||||||
//closeTrade(trade);
|
//closeTrade(trade);
|
||||||
|
|
||||||
|
@ -363,76 +368,48 @@ public class TradeManager {
|
||||||
Trade trade = createTrade(offer);
|
Trade trade = createTrade(offer);
|
||||||
trade.setTradeAmount(amount);
|
trade.setTradeAmount(amount);
|
||||||
|
|
||||||
SellerTakesOfferProtocolListener listener = new SellerTakesOfferProtocolListener() {
|
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
@Override
|
log.debug("trade state = " + newValue);
|
||||||
public void onTakeOfferRequestAccepted() {
|
switch (newValue) {
|
||||||
|
case OPEN:
|
||||||
|
break;
|
||||||
|
case OFFERER_ACCEPTED:
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
}
|
break;
|
||||||
|
case OFFERER_REJECTED:
|
||||||
@Override
|
|
||||||
public void onTakeOfferRequestRejected() {
|
|
||||||
removeFailedTrade(trade);
|
removeFailedTrade(trade);
|
||||||
}
|
break;
|
||||||
|
case DEPOSIT_PUBLISHED:
|
||||||
@Override
|
|
||||||
public void onDepositTxPublished() {
|
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
}
|
break;
|
||||||
|
case DEPOSIT_CONFIRMED:
|
||||||
@Override
|
break;
|
||||||
public void onBankTransferInited(String tradeId) {
|
case FIAT_PAYMENT_STARTED:
|
||||||
trade.setState(Trade.State.PAYMENT_STARTED);
|
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
}
|
break;
|
||||||
|
case FAILED:
|
||||||
@Override
|
removeFailedTrade(trade);
|
||||||
public void onPayoutTxPublished(Trade trade, Transaction payoutTx) {
|
break;
|
||||||
trade.setPayoutTx(payoutTx);
|
case PAYOUT_PUBLISHED:
|
||||||
trade.setState(Trade.State.COMPLETED);
|
|
||||||
// We close the trade when the user has withdrawn his trade funds (see #283)
|
|
||||||
//closeTrade(trade);
|
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.error("Unhandled trade state: " + newValue);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@Override
|
SellerTakesOfferModel model = new SellerTakesOfferModel(
|
||||||
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(
|
|
||||||
trade,
|
trade,
|
||||||
listener,
|
|
||||||
tradeMessageService,
|
tradeMessageService,
|
||||||
walletService,
|
walletService,
|
||||||
blockChainService,
|
blockChainService,
|
||||||
signatureService,
|
signatureService,
|
||||||
user);
|
user);
|
||||||
|
|
||||||
|
SellerTakesOfferProtocol sellerTakesOfferProtocol = new SellerTakesOfferProtocol(model);
|
||||||
takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol);
|
takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol);
|
||||||
|
|
||||||
sellerTakesOfferProtocol.start();
|
sellerTakesOfferProtocol.start();
|
||||||
|
|
||||||
return trade;
|
return trade;
|
||||||
|
@ -444,7 +421,7 @@ public class TradeManager {
|
||||||
public void fiatPaymentStarted(String tradeId) {
|
public void fiatPaymentStarted(String tradeId) {
|
||||||
if (offererAsBuyerProtocolMap.get(tradeId) != null) {
|
if (offererAsBuyerProtocolMap.get(tradeId) != null) {
|
||||||
offererAsBuyerProtocolMap.get(tradeId).handleUIEventBankTransferStarted();
|
offererAsBuyerProtocolMap.get(tradeId).handleUIEventBankTransferStarted();
|
||||||
pendingTrades.get(tradeId).setState(Trade.State.PAYMENT_STARTED);
|
pendingTrades.get(tradeId).setState(Trade.State.FIAT_PAYMENT_STARTED);
|
||||||
persistPendingTrades();
|
persistPendingTrades();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -455,7 +432,7 @@ public class TradeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fiatPaymentReceived(String tradeId) {
|
public void fiatPaymentReceived(String tradeId) {
|
||||||
takerAsSellerProtocolMap.get(tradeId).handleUIEventFiatReceived();
|
takerAsSellerProtocolMap.get(tradeId).handleFiatReceivedUIEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestIsOfferAvailable(Offer offer) {
|
public void requestIsOfferAvailable(Offer offer) {
|
||||||
|
@ -524,29 +501,19 @@ public class TradeManager {
|
||||||
createOffererAsBuyerProtocol(tradeId, sender);
|
createOffererAsBuyerProtocol(tradeId, sender);
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
|
else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
|
||||||
takerAsSellerProtocolMap.get(tradeId).handleRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage);
|
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof TakeOfferFeePayedMessage) {
|
else if (tradeMessage instanceof TakeOfferFeePayedMessage) {
|
||||||
offererAsBuyerProtocolMap.get(tradeId).handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
|
offererAsBuyerProtocolMap.get(tradeId).handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
|
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
|
||||||
takerAsSellerProtocolMap.get(tradeId).handleTakerDepositPaymentRequestMessage((TakerDepositPaymentRequestMessage) tradeMessage);
|
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) {
|
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) {
|
||||||
offererAsBuyerProtocolMap.get(tradeId).handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
|
offererAsBuyerProtocolMap.get(tradeId).handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof DepositTxPublishedMessage) {
|
else if (tradeMessage instanceof DepositTxPublishedMessage) {
|
||||||
persistPendingTrades();
|
// persistPendingTrades();
|
||||||
takerAsSellerProtocolMap.get(tradeId).handleDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
|
|
||||||
}
|
}
|
||||||
else if (tradeMessage instanceof BankTransferInitedMessage) {
|
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) {
|
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
|
||||||
offererAsBuyerProtocolMap.get(tradeId).handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
|
offererAsBuyerProtocolMap.get(tradeId).handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
|
||||||
|
|
|
@ -21,7 +21,7 @@ import io.bitsquare.network.Message;
|
||||||
import io.bitsquare.network.MessageBroker;
|
import io.bitsquare.network.MessageBroker;
|
||||||
import io.bitsquare.network.Peer;
|
import io.bitsquare.network.Peer;
|
||||||
import io.bitsquare.trade.listeners.GetPeerAddressListener;
|
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.trade.listeners.SendMessageListener;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
@ -34,9 +34,9 @@ public interface TradeMessageService extends MessageBroker {
|
||||||
|
|
||||||
void sendMessage(Peer peer, Message message, SendMessageListener listener);
|
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);
|
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.Message;
|
||||||
import io.bitsquare.network.Peer;
|
import io.bitsquare.network.Peer;
|
||||||
|
|
||||||
public interface ProcessNewMessageListener {
|
public interface MessageHandler {
|
||||||
void handleMessage(Message message, Peer sender);
|
void handleMessage(Message message, Peer sender);
|
||||||
}
|
}
|
|
@ -15,24 +15,24 @@
|
||||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
* 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.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 {
|
public class TradeSharedModel extends SharedModel {
|
||||||
void onDepositTxPublished();
|
private static final Logger log = LoggerFactory.getLogger(TradeSharedModel.class);
|
||||||
|
|
||||||
void onBankTransferInited(String tradeId);
|
public Trade getTrade() {
|
||||||
|
return trade;
|
||||||
|
}
|
||||||
|
|
||||||
void onPayoutTxPublished(Trade trade, Transaction payoutTx);
|
protected final Trade trade;
|
||||||
|
|
||||||
void onFault(Throwable throwable, SellerTakesOfferProtocol.State state);
|
|
||||||
|
|
||||||
void onTakeOfferRequestAccepted();
|
|
||||||
|
|
||||||
void onTakeOfferRequestRejected();
|
|
||||||
|
|
||||||
|
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;
|
package io.bitsquare.trade.protocol.trade.taker;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.network.Message;
|
||||||
import io.bitsquare.btc.BlockChainService;
|
|
||||||
import io.bitsquare.btc.WalletService;
|
|
||||||
import io.bitsquare.crypto.SignatureService;
|
|
||||||
import io.bitsquare.network.Peer;
|
import io.bitsquare.network.Peer;
|
||||||
import io.bitsquare.offer.Offer;
|
|
||||||
import io.bitsquare.trade.Contract;
|
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.TradeMessageService;
|
import io.bitsquare.trade.TradeTaskRunner;
|
||||||
import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener;
|
import io.bitsquare.trade.protocol.trade.TradeMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage;
|
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.DepositTxPublishedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
|
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.SendTakeOfferFeePayedMessage;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.tasks.SignAndPublishPayoutTx;
|
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.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.VerifyOfferFeePayment;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOffererAccount;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.*;
|
import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
||||||
import static io.bitsquare.util.Validator.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,395 +59,160 @@ import static io.bitsquare.util.Validator.*;
|
||||||
public class SellerTakesOfferProtocol {
|
public class SellerTakesOfferProtocol {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferProtocol.class);
|
private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferProtocol.class);
|
||||||
|
|
||||||
|
private final SellerTakesOfferModel model;
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public SellerTakesOfferProtocol(Trade trade,
|
public SellerTakesOfferProtocol(SellerTakesOfferModel model) {
|
||||||
SellerTakesOfferProtocolListener listener,
|
this.model = model;
|
||||||
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 void start() {
|
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
|
public void cleanup() {
|
||||||
private void getPeerAddress() {
|
model.getTradeMessageService().removeMessageHandler(this::handleMessage);
|
||||||
log.debug("getPeerAddress called: state = " + state);
|
|
||||||
state = State.GetPeerAddress;
|
|
||||||
GetPeerAddress.run(this::handleGetPeerAddressResult, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
private void handleMessage(Message message, Peer sender) {
|
||||||
public void handleRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message) {
|
log.trace("handleNewMessage: message = " + message.getClass().getSimpleName());
|
||||||
log.debug("handleRespondToTakeOfferRequestMessage called: state = " + state);
|
if (message instanceof TradeMessage) {
|
||||||
|
TradeMessage tradeMessage = (TradeMessage) message;
|
||||||
|
nonEmptyStringOf(tradeMessage.getTradeId());
|
||||||
|
|
||||||
try {
|
if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
|
||||||
// validation
|
handleTradeMessage((RespondToTakeOfferRequestMessage) tradeMessage);
|
||||||
checkState(state == State.RequestTakeOffer);
|
}
|
||||||
state = State.ValidateRespondToTakeOfferRequestMessage;
|
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
|
||||||
checkTradeId(tradeId, message);
|
handleTradeMessage((TakerDepositPaymentRequestMessage) tradeMessage);
|
||||||
|
}
|
||||||
// apply new state
|
else if (tradeMessage instanceof DepositTxPublishedMessage) {
|
||||||
if (message.isTakeOfferRequestAccepted()) {
|
handleTradeMessage((DepositTxPublishedMessage) tradeMessage);
|
||||||
trade.setState(Trade.State.OFFERER_ACCEPTED);
|
}
|
||||||
listener.onTakeOfferRequestAccepted();
|
else if (tradeMessage instanceof BankTransferInitedMessage) {
|
||||||
|
handleTradeMessage((BankTransferInitedMessage) tradeMessage);
|
||||||
// next task
|
|
||||||
payTakeOfferFee();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// exit case
|
log.error("Incoming message not supported. " + tradeMessage);
|
||||||
trade.setState(Trade.State.OFFERER_REJECTED);
|
|
||||||
listener.onTakeOfferRequestRejected();
|
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
|
||||||
handleValidationFault(t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. PayTakeOfferFee
|
private void handleTradeMessage(RespondToTakeOfferRequestMessage tradeMessage) {
|
||||||
private void payTakeOfferFee() {
|
model.setTradeMessage(tradeMessage);
|
||||||
state = State.PayTakeOfferFee;
|
|
||||||
PayTakeOfferFee.run(this::handlePayTakeOfferFeeResult, this::handleFault, walletService, tradeId);
|
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 handleTradeMessage(TakerDepositPaymentRequestMessage tradeMessage) {
|
||||||
private void handlePayTakeOfferFeeResult(String takeOfferFeeTxId) {
|
model.setTradeMessage(tradeMessage);
|
||||||
log.debug("handlePayTakeOfferFeeResult called: state = " + state);
|
|
||||||
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
|
TradeTaskRunner<SellerTakesOfferModel> sequence3 = new TradeTaskRunner<>(model,
|
||||||
state = State.SendTakeOfferFeePayedMessage;
|
() -> {
|
||||||
SendTakeOfferFeePayedMessage.run(this::handleErrorMessage, peer, tradeMessageService, tradeId, takeOfferFeeTxId, tradeAmount, tradePubKeyAsHex);
|
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
|
// UI event handling
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// 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
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||||
// 26. SignAndPublishPayoutTx
|
public void handleFiatReceivedUIEvent() {
|
||||||
public void handleUIEventFiatReceived() {
|
TradeTaskRunner<SellerTakesOfferModel> sequence6 = new TradeTaskRunner<>(model,
|
||||||
log.debug("handleUIEventFiatReceived called: state = " + state);
|
() -> {
|
||||||
checkState(state == State.handleBankTransferInitedMessage);
|
log.debug("sequence6 completed");
|
||||||
|
},
|
||||||
state = State.SignAndPublishPayoutTx;
|
(message, throwable) -> {
|
||||||
SignAndPublishPayoutTx.run(this::handleSignAndPublishPayoutTxResult,
|
log.error(message);
|
||||||
this::handleFault,
|
|
||||||
walletService,
|
|
||||||
tradeId,
|
|
||||||
depositTxAsHex,
|
|
||||||
offererSignatureR,
|
|
||||||
offererSignatureS,
|
|
||||||
offererPaybackAmount,
|
|
||||||
takerPaybackAmount,
|
|
||||||
offererPayoutAddress);
|
|
||||||
|
|
||||||
verifyOfferFeePayment();
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
// 27a. SendPayoutTxToOfferer
|
sequence6.addTasks(
|
||||||
private void handleSignAndPublishPayoutTxResult(Transaction transaction, String payoutTxAsHex) {
|
SignAndPublishPayoutTx.class,
|
||||||
log.debug("handleSignAndPublishPayoutTxResult called: state = " + state);
|
VerifyOfferFeePayment.class,
|
||||||
listener.onPayoutTxPublished(trade, transaction);
|
SendPayoutTxToOfferer.class
|
||||||
state = State.SendPayoutTxToOfferer;
|
);
|
||||||
SendPayoutTxToOfferer.run(this::handleErrorMessage, peer, tradeMessageService, tradeId, payoutTxAsHex);
|
sequence6.run();
|
||||||
}
|
|
||||||
|
|
||||||
// 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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,53 +17,43 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
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.Contract;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.util.Utilities;
|
import io.bitsquare.util.Utilities;
|
||||||
import io.bitsquare.util.handlers.ExceptionHandler;
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
import org.bitcoinj.core.Coin;
|
|
||||||
import org.bitcoinj.core.ECKey;
|
|
||||||
|
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class CreateAndSignContract {
|
public class CreateAndSignContract extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
public CreateAndSignContract(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
ExceptionHandler exceptionHandler,
|
super(taskHandler, model);
|
||||||
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);
|
|
||||||
|
|
||||||
|
@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 contractAsJson = Utilities.objectToJson(contract);
|
||||||
String signature = signatureService.signMessage(registrationKey, contractAsJson);
|
String signature = model.getSignatureService().signMessage(model.getAccountKey(), contractAsJson);
|
||||||
resultHandler.onResult(contract, contractAsJson, signature);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
log.error("Exception at sign contract " + t);
|
|
||||||
exceptionHandler.handleException(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ResultHandler {
|
trade.setContract(contract);
|
||||||
void onResult(Contract contract, String contractAsJson, String signature);
|
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.network.Peer;
|
||||||
import io.bitsquare.trade.TradeMessageService;
|
import io.bitsquare.trade.TradeMessageService;
|
||||||
import io.bitsquare.trade.listeners.GetPeerAddressListener;
|
import io.bitsquare.trade.listeners.GetPeerAddressListener;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.util.handlers.ErrorMessageHandler;
|
import io.bitsquare.util.handlers.ErrorMessageHandler;
|
||||||
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class GetPeerAddress {
|
public class GetPeerAddress extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
|
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,
|
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler,
|
||||||
TradeMessageService tradeMessageService, PublicKey messagePublicKey) {
|
TradeMessageService tradeMessageService, PublicKey messagePublicKey) {
|
||||||
log.trace("Run GetPeerAddress task");
|
log.trace("Run GetPeerAddress task");
|
||||||
|
|
|
@ -17,8 +17,9 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.util.handlers.ExceptionHandler;
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
|
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
import org.bitcoinj.core.InsufficientMoneyException;
|
import org.bitcoinj.core.InsufficientMoneyException;
|
||||||
|
@ -27,41 +28,32 @@ import org.bitcoinj.core.Transaction;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class PayDeposit {
|
public class PayDeposit extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
public PayDeposit(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
ExceptionHandler exceptionHandler,
|
super(taskHandler, model);
|
||||||
WalletService walletService,
|
}
|
||||||
Coin securityDeposit,
|
|
||||||
Coin tradeAmount,
|
@Override
|
||||||
String tradeId,
|
protected void run() {
|
||||||
String pubKeyForThatTrade,
|
|
||||||
String arbitratorPubKey,
|
|
||||||
String offererPubKey,
|
|
||||||
String preparedOffererDepositTxAsHex) {
|
|
||||||
log.trace("Run PayDeposit task");
|
|
||||||
try {
|
try {
|
||||||
Coin amountToPay = tradeAmount.add(securityDeposit);
|
Coin amountToPay = model.getTradeAmount().add(model.getSecurityDeposit());
|
||||||
Coin msOutputAmount = amountToPay.add(securityDeposit);
|
Coin msOutputAmount = amountToPay.add(model.getSecurityDeposit());
|
||||||
|
Transaction signedTakerDepositTx = model.getWalletService().takerAddPaymentAndSignTx(
|
||||||
Transaction signedTakerDepositTx = walletService.takerAddPaymentAndSignTx(amountToPay,
|
amountToPay,
|
||||||
msOutputAmount,
|
msOutputAmount,
|
||||||
offererPubKey,
|
model.getPeersPubKey(),
|
||||||
pubKeyForThatTrade,
|
model.getTradePubKeyAsHex(),
|
||||||
arbitratorPubKey,
|
model.getArbitratorPubKey(),
|
||||||
preparedOffererDepositTxAsHex,
|
model.getPreparedPeersDepositTxAsHex(),
|
||||||
tradeId);
|
model.getTradeId());
|
||||||
|
|
||||||
log.trace("signedTakerDepositTx: " + signedTakerDepositTx);
|
model.setSignedTakerDepositTx(signedTakerDepositTx);
|
||||||
resultHandler.onResult(signedTakerDepositTx);
|
|
||||||
|
complete();
|
||||||
} catch (InsufficientMoneyException e) {
|
} catch (InsufficientMoneyException e) {
|
||||||
log.error("Pay deposit failed due InsufficientMoneyException " + e);
|
failed(e);
|
||||||
exceptionHandler.handleException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ResultHandler {
|
|
||||||
void onResult(Transaction signedTakerDepositTx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.util.handlers.ExceptionHandler;
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
|
|
||||||
import org.bitcoinj.core.InsufficientMoneyException;
|
import org.bitcoinj.core.InsufficientMoneyException;
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
|
@ -30,34 +31,31 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class PayTakeOfferFee {
|
public class PayTakeOfferFee extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
|
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService,
|
public PayTakeOfferFee(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
String tradeId) {
|
super(taskHandler, model);
|
||||||
log.trace("Run PayTakeOfferFee task");
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
try {
|
try {
|
||||||
walletService.payTakeOfferFee(tradeId, new FutureCallback<Transaction>() {
|
model.getWalletService().payTakeOfferFee(model.getTradeId(), new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
||||||
resultHandler.onResult(transaction.getHashAsString());
|
model.getTrade().setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NotNull Throwable t) {
|
public void onFailure(@NotNull Throwable t) {
|
||||||
log.error("Pay take offer fee caused an exception: " + t);
|
failed("Pay take offer fee caused an exception: ", t);
|
||||||
exceptionHandler.handleException(t);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (InsufficientMoneyException e) {
|
} catch (InsufficientMoneyException e) {
|
||||||
log.error("Pay take offer fee caused an exception: " + e);
|
failed("Pay take offer fee caused an exception: ", e);
|
||||||
exceptionHandler.handleException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ResultHandler {
|
|
||||||
void onResult(String takeOfferFeeTxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,32 +17,35 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
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.listeners.SendMessageListener;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class RequestTakeOffer {
|
public class RequestTakeOffer extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
|
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
|
||||||
|
|
||||||
public static void run(ErrorMessageHandler errorMessageHandler,
|
public RequestTakeOffer(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
TradeMessageService tradeMessageService, Peer peer, String tradeId) {
|
super(taskHandler, model);
|
||||||
log.trace("Run RequestTakeOffer task");
|
}
|
||||||
tradeMessageService.sendMessage(peer, new RequestTakeOfferMessage(tradeId),
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
model.getTradeMessageService().sendMessage(model.getPeer(), new RequestTakeOfferMessage(model.getTradeId()),
|
||||||
new SendMessageListener() {
|
new SendMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void handleResult() {
|
public void handleResult() {
|
||||||
log.trace("Sending RequestTakeOfferMessage succeeded.");
|
log.trace("Sending RequestTakeOfferMessage succeeded.");
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleFault() {
|
public void handleFault() {
|
||||||
log.error("Sending RequestTakeOfferMessage failed.");
|
failed("Sending RequestTakeOfferMessage failed.");
|
||||||
errorMessageHandler.handleErrorMessage("Sending RequestTakeOfferMessage failed.");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,33 +17,36 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
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.listeners.SendMessageListener;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SendPayoutTxToOfferer {
|
public class SendPayoutTxToOfferer extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
||||||
|
|
||||||
public static void run(ErrorMessageHandler errorMessageHandler, Peer peer, TradeMessageService tradeMessageService, String tradeId, String payoutTxAsHex) {
|
public SendPayoutTxToOfferer(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
log.trace("Run SendPayoutTxToOfferer task");
|
super(taskHandler, model);
|
||||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(tradeId, payoutTxAsHex);
|
}
|
||||||
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() {
|
|
||||||
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(model.getTradeId(), model.getPayoutTxAsHex());
|
||||||
|
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void handleResult() {
|
public void handleResult() {
|
||||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleFault() {
|
public void handleFault() {
|
||||||
errorMessageHandler.handleErrorMessage("Sending PayoutTxPublishedMessage failed.");
|
failed("Sending PayoutTxPublishedMessage failed.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,66 +17,55 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
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.listeners.SendMessageListener;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
|
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.Transaction;
|
||||||
import org.bitcoinj.core.Utils;
|
import org.bitcoinj.core.Utils;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SendSignedTakerDepositTxAsHex {
|
public class SendSignedTakerDepositTxAsHex extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
||||||
|
|
||||||
public static void run(ErrorMessageHandler errorMessageHandler,
|
public SendSignedTakerDepositTxAsHex(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
Peer peer,
|
super(taskHandler, model);
|
||||||
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();
|
|
||||||
|
|
||||||
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(tradeId,
|
@Override
|
||||||
bankAccount,
|
protected void run() {
|
||||||
accountId,
|
Transaction signedTakerDepositTx = model.getSignedTakerDepositTx();
|
||||||
messagePublicKey,
|
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.bitcoinSerialize()),
|
||||||
Utils.HEX.encode(signedTakerDepositTx.getInput(1).getScriptBytes()),
|
Utils.HEX.encode(signedTakerDepositTx.getInput(1).getScriptBytes()),
|
||||||
Utils.HEX.encode(signedTakerDepositTx.getInput(1)
|
Utils.HEX.encode(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
|
||||||
.getConnectedOutput()
|
model.getTrade().getContractAsJson(),
|
||||||
.getParentTransaction()
|
model.getTrade().getTakerContractSignature(),
|
||||||
.bitcoinSerialize()),
|
model.getWalletService().getAddressInfoByTradeID(model.getTradeId()).getAddressString(),
|
||||||
contractAsJson,
|
|
||||||
takerContractSignature,
|
|
||||||
walletService.getAddressInfoByTradeID(tradeId).getAddressString(),
|
|
||||||
takerTxOutIndex,
|
takerTxOutIndex,
|
||||||
offererTxOutIndex);
|
model.getPeersTxOutIndex());
|
||||||
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() {
|
|
||||||
|
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
public void handleResult() {
|
public void handleResult() {
|
||||||
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleFault() {
|
public void handleFault() {
|
||||||
log.error("RequestOffererDepositPublicationMessage did not arrive at peer");
|
failed("Sending RequestOffererDepositPublicationMessage failed");
|
||||||
errorMessageHandler.handleErrorMessage("RequestOffererDepositPublicationMessage did not arrive at peer");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,41 +17,41 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
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.listeners.SendMessageListener;
|
||||||
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
|
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
|
||||||
import io.bitsquare.util.handlers.ErrorMessageHandler;
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
import org.bitcoinj.core.Coin;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SendTakeOfferFeePayedMessage {
|
public class SendTakeOfferFeePayedMessage extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class);
|
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class);
|
||||||
|
|
||||||
public static void run(ErrorMessageHandler errorMessageHandler,
|
public SendTakeOfferFeePayedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
Peer peer,
|
super(taskHandler, model);
|
||||||
TradeMessageService tradeMessageService,
|
}
|
||||||
String tradeId,
|
|
||||||
String takeOfferFeeTxId,
|
|
||||||
Coin tradeAmount,
|
|
||||||
String tradePubKeyAsHex) {
|
|
||||||
log.trace("Run SendTakeOfferFeePayedMessage task");
|
|
||||||
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, takeOfferFeeTxId, tradeAmount,
|
|
||||||
tradePubKeyAsHex);
|
|
||||||
|
|
||||||
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
|
@Override
|
||||||
public void handleResult() {
|
public void handleResult() {
|
||||||
log.trace("TakeOfferFeePayedMessage succeeded.");
|
log.trace("Sending TakeOfferFeePayedMessage succeeded.");
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleFault() {
|
public void handleFault() {
|
||||||
log.error("Sending TakeOfferFeePayedMessage failed.");
|
failed("Sending TakeOfferFeePayedMessage failed.");
|
||||||
errorMessageHandler.handleErrorMessage("Sending TakeOfferFeePayedMessage failed.");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.trade.Trade;
|
||||||
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.AddressFormatException;
|
||||||
import org.bitcoinj.core.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
import org.bitcoinj.core.Utils;
|
import org.bitcoinj.core.Utils;
|
||||||
|
|
||||||
|
@ -31,48 +33,43 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class SignAndPublishPayoutTx {
|
public class SignAndPublishPayoutTx extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler,
|
public SignAndPublishPayoutTx(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
ExceptionHandler exceptionHandler,
|
super(taskHandler, model);
|
||||||
WalletService walletService,
|
}
|
||||||
String tradeId,
|
|
||||||
String depositTxAsHex,
|
@Override
|
||||||
String offererSignatureR,
|
protected void run() {
|
||||||
String offererSignatureS,
|
|
||||||
Coin offererPaybackAmount,
|
|
||||||
Coin takerPaybackAmount,
|
|
||||||
String offererPayoutAddress) {
|
|
||||||
log.trace("Run SignAndPublishPayoutTx task");
|
|
||||||
try {
|
try {
|
||||||
walletService.takerSignsAndSendsTx(depositTxAsHex,
|
model.getWalletService().takerSignsAndSendsTx(model.getDepositTxAsHex(),
|
||||||
offererSignatureR,
|
model.getOffererSignatureR(),
|
||||||
offererSignatureS,
|
model.getOffererSignatureS(),
|
||||||
offererPaybackAmount,
|
model.getOffererPaybackAmount(),
|
||||||
takerPaybackAmount,
|
model.getTakerPaybackAmount(),
|
||||||
offererPayoutAddress,
|
model.getOffererPayoutAddress(),
|
||||||
tradeId,
|
model.getTradeId(),
|
||||||
new FutureCallback<Transaction>() {
|
new FutureCallback<Transaction>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Transaction transaction) {
|
public void onSuccess(Transaction transaction) {
|
||||||
log.debug("takerSignsAndSendsTx " + transaction);
|
log.debug("takerSignsAndSendsTx " + transaction);
|
||||||
String payoutTxAsHex = Utils.HEX.encode(transaction.bitcoinSerialize());
|
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
|
@Override
|
||||||
public void onFailure(@NotNull Throwable t) {
|
public void onFailure(@NotNull Throwable t) {
|
||||||
exceptionHandler.handleException(t);
|
failed(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (AddressFormatException e) {
|
||||||
exceptionHandler.handleException(e);
|
failed(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ResultHandler {
|
|
||||||
void onResult(Transaction transaction, String payoutTxAsHex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,29 +17,30 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.trade.Trade;
|
||||||
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.Transaction;
|
import org.bitcoinj.core.Transaction;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class TakerCommitDepositTx {
|
public class TakerCommitDepositTx extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class);
|
private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService, String depositTxAsHex) {
|
public TakerCommitDepositTx(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
log.trace("Run PayDeposit task");
|
super(taskHandler, model);
|
||||||
try {
|
|
||||||
Transaction transaction = walletService.takerCommitDepositTx(depositTxAsHex);
|
|
||||||
resultHandler.onResult(transaction);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("takerCommitDepositTx failed with exception " + e);
|
|
||||||
exceptionHandler.handleException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ResultHandler {
|
@Override
|
||||||
void onResult(Transaction transaction);
|
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;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.util.handlers.ExceptionHandler;
|
import io.bitsquare.util.tasks.Task;
|
||||||
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class VerifyOfferFeePayment {
|
public class VerifyOfferFeePayment extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class);
|
private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class);
|
||||||
|
|
||||||
public static void run(ExceptionHandler exceptionHandler, WalletService walletService,
|
public VerifyOfferFeePayment(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
String takeOfferFeeTxId) {
|
super(taskHandler, model);
|
||||||
log.trace("Run VerifyOfferFeePayment task");
|
}
|
||||||
//TODO mocked yet, need a confidence listeners
|
|
||||||
int numOfPeersSeenTx = walletService.getNumOfPeersSeenTx(takeOfferFeeTxId);
|
@Override
|
||||||
|
protected void run() {
|
||||||
|
//TODO impl. missing
|
||||||
|
int numOfPeersSeenTx = model.getWalletService().getNumOfPeersSeenTx(model.getTrade().getTakeOfferFeeTxId());
|
||||||
/* if (numOfPeersSeenTx > 2) {
|
/* if (numOfPeersSeenTx > 2) {
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
}*/
|
}*/
|
||||||
|
complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,32 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
package io.bitsquare.trade.protocol.trade.taker.tasks;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel;
|
||||||
import io.bitsquare.btc.BlockChainService;
|
import io.bitsquare.util.tasks.Task;
|
||||||
import io.bitsquare.trade.protocol.trade.shared.tasks.VerifyPeerAccount;
|
import io.bitsquare.util.tasks.TaskRunner;
|
||||||
import io.bitsquare.util.handlers.ExceptionHandler;
|
|
||||||
import io.bitsquare.util.handlers.ResultHandler;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class VerifyOffererAccount {
|
public class VerifyOffererAccount extends Task<SellerTakesOfferModel> {
|
||||||
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
||||||
|
|
||||||
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler,
|
public VerifyOffererAccount(TaskRunner taskHandler, SellerTakesOfferModel model) {
|
||||||
BlockChainService blockChainService, String peersAccountId, BankAccount peersBankAccount) {
|
super(taskHandler, model);
|
||||||
log.trace("Run VerifyOffererAccount task");
|
}
|
||||||
VerifyPeerAccount.run(resultHandler, exceptionHandler, blockChainService, peersAccountId, peersBankAccount);
|
|
||||||
|
@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.network.tomp2p.TomP2PPeer;
|
||||||
import io.bitsquare.trade.TradeMessageService;
|
import io.bitsquare.trade.TradeMessageService;
|
||||||
import io.bitsquare.trade.listeners.GetPeerAddressListener;
|
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.trade.listeners.SendMessageListener;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ public class TomP2PTradeMessageService implements TradeMessageService {
|
||||||
|
|
||||||
private final TomP2PNode tomP2PNode;
|
private final TomP2PNode tomP2PNode;
|
||||||
private final User user;
|
private final User user;
|
||||||
private final List<ProcessNewMessageListener> processNewMessageListeners = new ArrayList<>();
|
private final List<MessageHandler> messageHandlers = new ArrayList<>();
|
||||||
private Executor executor;
|
private Executor executor;
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,12 +133,12 @@ public class TomP2PTradeMessageService implements TradeMessageService {
|
||||||
// Event Listeners
|
// Event Listeners
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void addHandleNewMessageListener(ProcessNewMessageListener listener) {
|
public void addMessageHandler(MessageHandler listener) {
|
||||||
processNewMessageListeners.add(listener);
|
messageHandlers.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeHandleNewMessageListener(ProcessNewMessageListener listener) {
|
public void removeMessageHandler(MessageHandler listener) {
|
||||||
processNewMessageListeners.remove(listener);
|
messageHandlers.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ public class TomP2PTradeMessageService implements TradeMessageService {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Object message, Peer sender) {
|
public void handleMessage(Object message, Peer sender) {
|
||||||
if (message instanceof Message && sender instanceof TomP2PPeer) {
|
if (message instanceof Message && sender instanceof TomP2PPeer) {
|
||||||
executor.execute(() -> processNewMessageListeners.stream().forEach(e ->
|
executor.execute(() -> messageHandlers.stream().forEach(e ->
|
||||||
e.handleMessage((Message) message, sender)));
|
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…
Add table
Add a link
Reference in a new issue