Refactor buyer side tasks with task runner

This commit is contained in:
Manfred Karrer 2015-03-12 10:18:10 +01:00
parent ef4937bba1
commit 9c9064091a
49 changed files with 1456 additions and 1330 deletions

View file

@ -183,7 +183,7 @@ class MainViewModel implements ViewModel {
Observable<Object> walletServiceObservable = walletService.initialize(Platform::runLater); Observable<Object> walletServiceObservable = walletService.initialize(Platform::runLater);
walletServiceObservable.subscribe( walletServiceObservable.subscribe(
next -> { next -> {
log.trace("wallet next"); //log.trace("wallet next");
}, },
error -> Platform.runLater(() -> { error -> Platform.runLater(() -> {
log.trace("wallet error"); log.trace("wallet error");
@ -195,7 +195,7 @@ class MainViewModel implements ViewModel {
Observable<UpdateProcess.State> updateProcessObservable = this.updateProcess.getProcess(); Observable<UpdateProcess.State> updateProcessObservable = this.updateProcess.getProcess();
updateProcessObservable.subscribe(next -> { updateProcessObservable.subscribe(next -> {
log.trace("updateProcess next"); //log.trace("updateProcess next");
}, },
error -> { error -> {
log.trace("updateProcess error"); log.trace("updateProcess error");

View file

@ -163,6 +163,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
} }
void fiatPaymentStarted() { void fiatPaymentStarted() {
getTrade().setState(Trade.State.FIAT_PAYMENT_STARTED);
tradeManager.fiatPaymentStarted(getTrade().getId()); tradeManager.fiatPaymentStarted(getTrade().getId());
} }

View file

@ -148,7 +148,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
@FXML @FXML
void onShowPayFundsScreen() { void onShowPayFundsScreen() {
if (model.displaySecurityDepositInfo()) { // TODO deactivate for testing the moment
/* if (model.displaySecurityDepositInfo()) {
overlayManager.blurContent(); overlayManager.blurContent();
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new AbstractAction(BSResources.get("shared.close")) { actions.add(new AbstractAction(BSResources.get("shared.close")) {
@ -165,7 +166,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
actions); actions);
model.securityDepositInfoDisplayed(); model.securityDepositInfoDisplayed();
} }*/
priceAmountPane.setInactive(); priceAmountPane.setInactive();

View file

@ -138,7 +138,7 @@ class TakeOfferDataModel implements Activatable, DataModel {
} }
void takeOffer() { void takeOffer() {
final Trade trade = tradeManager.takeOffer(amountAsCoin.get(), offer); final Trade trade = tradeManager.requestTakeOffer(amountAsCoin.get(), offer);
trade.stateProperty().addListener((ov, oldValue, newValue) -> { trade.stateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue); log.debug("trade state = " + newValue);
switch (newValue) { switch (newValue) {

View file

@ -182,7 +182,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
@FXML @FXML
void onShowPayFundsScreen() { void onShowPayFundsScreen() {
if (model.displaySecurityDepositInfo()) { // TODO deactivate for testing the moment
/* if (model.displaySecurityDepositInfo()) {
overlayManager.blurContent(); overlayManager.blurContent();
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new AbstractAction(BSResources.get("shared.close")) { actions.add(new AbstractAction(BSResources.get("shared.close")) {
@ -198,7 +199,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
actions); actions);
model.securityDepositInfoDisplayed(); model.securityDepositInfoDisplayed();
} }*/
priceAmountPane.setInactive(); priceAmountPane.setInactive();

View file

@ -19,6 +19,9 @@ package io.bitsquare.offer;
import java.io.Serializable; import java.io.Serializable;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,10 +30,25 @@ public class OpenOffer implements Serializable {
private static final Logger log = LoggerFactory.getLogger(OpenOffer.class); private static final Logger log = LoggerFactory.getLogger(OpenOffer.class);
///////////////////////////////////////////////////////////////////////////////////////////
// Enum
///////////////////////////////////////////////////////////////////////////////////////////
public static enum State {
OPEN,
OFFER_ACCEPTED
}
private final Offer offer; private final Offer offer;
private State state;
transient private ObjectProperty<State> _state;
public OpenOffer(Offer offer) { public OpenOffer(Offer offer) {
this.offer = offer; this.offer = offer;
state = State.OPEN;
} }
public Offer getOffer() { public Offer getOffer() {
@ -40,4 +58,20 @@ public class OpenOffer implements Serializable {
public String getId() { public String getId() {
return offer.getId(); return offer.getId();
} }
public void setState(State state) {
this.state = state;
stateProperty().set(state);
}
public State getState() {
return state;
}
public ObjectProperty<State> stateProperty() {
if (_state == null)
_state = new SimpleObjectProperty<>(state);
return _state;
}
} }

View file

@ -18,7 +18,6 @@
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;
@ -33,24 +32,6 @@ 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

View file

@ -30,31 +30,21 @@ import io.bitsquare.offer.OfferBookService;
import io.bitsquare.offer.OpenOffer; 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.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.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererProtocol;
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.IsOfferAvailableResponseMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.IsOfferAvailableResponseMessage;
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
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.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerProtocol;
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;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.handlers.ErrorMessageHandler; import io.bitsquare.util.handlers.ErrorMessageHandler;
import io.bitsquare.util.handlers.ResultHandler; import io.bitsquare.util.handlers.ResultHandler;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.utils.Fiat; import org.bitcoinj.utils.Fiat;
import java.util.HashMap; import java.util.HashMap;
@ -91,8 +81,8 @@ public class TradeManager {
private final OfferBookService offerBookService; private final OfferBookService offerBookService;
//TODO store TakerAsSellerProtocol in trade //TODO store TakerAsSellerProtocol in trade
private final Map<String, SellerTakesOfferProtocol> takerAsSellerProtocolMap = new HashMap<>(); private final Map<String, SellerAsTakerProtocol> takerAsSellerProtocolMap = new HashMap<>();
private final Map<String, BuyerAcceptsOfferProtocol> offererAsBuyerProtocolMap = new HashMap<>(); private final Map<String, BuyerAsOffererProtocol> offererAsBuyerProtocolMap = new HashMap<>();
private final Map<String, RequestIsOfferAvailableProtocol> requestIsOfferAvailableProtocolMap = new HashMap<>(); private final Map<String, RequestIsOfferAvailableProtocol> requestIsOfferAvailableProtocolMap = new HashMap<>();
private final ObservableMap<String, OpenOffer> openOffers = FXCollections.observableHashMap(); private final ObservableMap<String, OpenOffer> openOffers = FXCollections.observableHashMap();
@ -184,7 +174,7 @@ public class TradeManager {
walletService, walletService,
offerBookService, offerBookService,
(transaction) -> { (transaction) -> {
saveOpenOffer(new OpenOffer(offer)); createOpenOffer(offer);
resultHandler.handleResult(transaction); resultHandler.handleResult(transaction);
}, },
(message, throwable) -> errorMessageHandler.handleErrorMessage(message) (message, throwable) -> errorMessageHandler.handleErrorMessage(message)
@ -193,9 +183,12 @@ public class TradeManager {
placeOfferProtocol.placeOffer(); placeOfferProtocol.placeOffer();
} }
private void saveOpenOffer(OpenOffer openOffer) { private void createOpenOffer(Offer offer) {
OpenOffer openOffer = new OpenOffer(offer);
openOffers.put(openOffer.getId(), openOffer); openOffers.put(openOffer.getId(), openOffer);
persistOpenOffers(); persistOpenOffers();
createOffererAsBuyerProtocol(openOffer);
} }
public void requestRemoveOpenOffer(String offerId, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { public void requestRemoveOpenOffer(String offerId, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
@ -261,137 +254,53 @@ public class TradeManager {
// Trading protocols // Trading protocols
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private void createOffererAsBuyerProtocol(String offerId, Peer sender) { private void createOffererAsBuyerProtocol(OpenOffer openOffer) {
log.trace("createOffererAsBuyerProtocol offerId = " + offerId); BuyerAsOffererModel model = new BuyerAsOffererModel(
if (openOffers.containsKey(offerId)) { openOffer,
Offer offer = openOffers.get(offerId).getOffer();
Trade trade = createTrade(offer);
BuyerAcceptsOfferProtocol buyerAcceptsOfferProtocol = new BuyerAcceptsOfferProtocol(trade,
sender,
tradeMessageService, tradeMessageService,
walletService, walletService,
blockChainService, blockChainService,
signatureService, signatureService,
user, user);
new BuyerAcceptsOfferProtocolListener() {
@Override
public void onOfferAccepted(Offer offer) {
persistPendingTrades();
//TODO do that later
/*requestRemoveOpenOffer(offer.getId(),
() -> log.debug("remove offer was successful"),
(message) -> log.error(message));*/
}
@Override openOffer.stateProperty().addListener((ov, oldValue, newValue) -> {
public void onDepositTxPublished(Transaction depositTx) {
persistPendingTrades();
}
// TODO should be removed
@Override
public void onDepositTxConfirmedInBlockchain() {
log.trace("trading onDepositTxConfirmedInBlockchain");
trade.setState(Trade.State.DEPOSIT_CONFIRMED);
persistPendingTrades();
}
@Override
public void onPayoutTxPublished(Transaction payoutTx) {
trade.setPayoutTx(payoutTx);
trade.setState(Trade.State.PAYOUT_PUBLISHED);
// We close the trade when the user has withdrawn his trade funds (see #283)
//closeTrade(trade);
log.debug("trading onPayoutTxPublishedMessage");
}
@Override
public void onFault(Throwable throwable, BuyerAcceptsOfferProtocol.State state) {
log.error("Error while executing trade process at state: " + state + " / " + throwable);
switch (state) {
case RespondToTakeOfferRequest:
removeFailedTrade(trade);
break;
case ValidateTakeOfferFeePayedMessage:
removeFailedTrade(trade);
break;
case CreateDepositTx:
removeFailedTrade(trade);
break;
case SendTakerDepositPaymentRequest:
removeFailedTrade(trade);
break;
case ValidateRequestOffererPublishDepositTxMessage:
removeFailedTrade(trade);
break;
case VerifyTakerAccount:
removeFailedTrade(trade);
break;
case VerifyAndSignContract:
removeFailedTrade(trade);
break;
case SignAndPublishDepositTx:
removeFailedTrade(trade);
break;
case SignAndPublishDepositTxResulted:
removeFailedTrade(trade);
break;
case SendSignedPayoutTx:
removeFailedTrade(trade);
break;
default:
log.error("Unhandled state: " + state);
break;
}
}
});
if (!offererAsBuyerProtocolMap.containsKey(trade.getId())) {
offererAsBuyerProtocolMap.put(trade.getId(), buyerAcceptsOfferProtocol);
}
else {
// We don't store the protocol in case we have already an open offer. The protocol is only
// temporary used to reply with a reject message.
log.trace("offererAsBuyerProtocol not stored as offer is already pending.");
}
buyerAcceptsOfferProtocol.start();
}
else {
log.warn("Incoming offer take request does not match with any saved offer. We ignore that request.");
}
}
public Trade takeOffer(Coin amount, Offer offer) {
Trade trade = createTrade(offer);
trade.setTradeAmount(amount);
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue); log.debug("trade state = " + newValue);
switch (newValue) { switch (newValue) {
case OPEN: case OPEN:
break; break;
case OFFERER_ACCEPTED: case OFFER_ACCEPTED:
requestRemoveOpenOffer(openOffer.getId(),
() -> log.debug("remove offer was successful"),
(message) -> log.error(message));
Trade trade = model.getTrade();
pendingTrades.put(trade.getId(), trade);
persistPendingTrades();
currentPendingTrade = trade;
// TODO check, remove listener
trade.stateProperty().addListener((ov2, oldValue2, newValue2) -> {
log.debug("trade state = " + newValue);
switch (newValue2) {
case OPEN:
break;
case OFFERER_ACCEPTED: // only taker side
case DEPOSIT_PUBLISHED:
case DEPOSIT_CONFIRMED:
case FIAT_PAYMENT_STARTED:
case FIAT_PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:
persistPendingTrades(); persistPendingTrades();
break; break;
case OFFERER_REJECTED: case OFFERER_REJECTED:
removeFailedTrade(trade);
break;
case DEPOSIT_PUBLISHED:
persistPendingTrades();
break;
case DEPOSIT_CONFIRMED:
break;
case FIAT_PAYMENT_STARTED:
persistPendingTrades();
break;
case FAILED: case FAILED:
removeFailedTrade(trade); removeFailedTrade(trade);
break; break;
case PAYOUT_PUBLISHED: default:
persistPendingTrades(); log.error("Unhandled trade state: " + newValue);
break;
}
});
break; break;
default: default:
log.error("Unhandled trade state: " + newValue); log.error("Unhandled trade state: " + newValue);
@ -399,7 +308,41 @@ public class TradeManager {
} }
}); });
SellerTakesOfferModel model = new SellerTakesOfferModel( BuyerAsOffererProtocol buyerAcceptsOfferProtocol = new BuyerAsOffererProtocol(model);
offererAsBuyerProtocolMap.put(openOffer.getId(), buyerAcceptsOfferProtocol);
buyerAcceptsOfferProtocol.start();
}
public Trade requestTakeOffer(Coin amount, Offer offer) {
Trade trade = createTrade(offer);
trade.setTradeAmount(amount);
// TODO check
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue);
switch (newValue) {
case OPEN:
break;
case OFFERER_ACCEPTED:
case DEPOSIT_PUBLISHED:
case DEPOSIT_CONFIRMED:
case FIAT_PAYMENT_STARTED:
case FIAT_PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:
persistPendingTrades();
break;
case OFFERER_REJECTED:
case FAILED:
removeFailedTrade(trade);
break;
default:
log.error("Unhandled trade state: " + newValue);
break;
}
});
SellerAsTakerModel model = new SellerAsTakerModel(
trade, trade,
tradeMessageService, tradeMessageService,
walletService, walletService,
@ -407,10 +350,10 @@ public class TradeManager {
signatureService, signatureService,
user); user);
SellerTakesOfferProtocol sellerTakesOfferProtocol = new SellerTakesOfferProtocol(model); SellerAsTakerProtocol sellerTakesOfferProtocol = new SellerAsTakerProtocol(model);
takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol); takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol);
sellerTakesOfferProtocol.start(); sellerTakesOfferProtocol.handleRequestTakeOfferUIEvent();
return trade; return trade;
} }
@ -420,8 +363,7 @@ public class TradeManager {
// Also we don't support yet offline messaging (mail box) // Also we don't support yet offline messaging (mail box)
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).handleBankTransferStartedUIEvent();
pendingTrades.get(tradeId).setState(Trade.State.FIAT_PAYMENT_STARTED);
persistPendingTrades(); persistPendingTrades();
} }
else { else {
@ -464,6 +406,7 @@ public class TradeManager {
log.trace("handleNewMessage: message = " + message.getClass().getSimpleName()); log.trace("handleNewMessage: message = " + message.getClass().getSimpleName());
log.trace("handleNewMessage: sender = " + sender); log.trace("handleNewMessage: sender = " + sender);
// TODO remove
if (message instanceof OfferMessage) { if (message instanceof OfferMessage) {
OfferMessage offerMessage = (OfferMessage) message; OfferMessage offerMessage = (OfferMessage) message;
// Before starting any take offer activity we check if the offer is still available. // Before starting any take offer activity we check if the offer is still available.
@ -491,40 +434,6 @@ public class TradeManager {
log.error("Incoming offerMessage not supported. " + offerMessage); log.error("Incoming offerMessage not supported. " + offerMessage);
} }
} }
else if (message instanceof TradeMessage) {
TradeMessage tradeMessage = (TradeMessage) message;
String tradeId = tradeMessage.getTradeId();
checkNotNull(tradeId);
if (tradeMessage instanceof RequestTakeOfferMessage) {
// Step 3. in trade protocol
createOffererAsBuyerProtocol(tradeId, sender);
}
else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
}
else if (tradeMessage instanceof TakeOfferFeePayedMessage) {
offererAsBuyerProtocolMap.get(tradeId).handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
}
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
}
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) {
offererAsBuyerProtocolMap.get(tradeId).handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
}
else if (tradeMessage instanceof DepositTxPublishedMessage) {
// persistPendingTrades();
}
else if (tradeMessage instanceof BankTransferInitedMessage) {
}
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
offererAsBuyerProtocolMap.get(tradeId).handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
}
else {
log.error("Incoming tradeMessage not supported. " + tradeMessage);
}
}
else {
log.error("Incoming message not supported. " + message);
}
} }

View file

@ -1,29 +0,0 @@
/*
* 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TradeState {
private static final Logger log = LoggerFactory.getLogger(TradeState.class);
public TradeState() {
}
}

View file

@ -1,35 +0,0 @@
/*
* 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.listeners;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol;
import org.bitcoinj.core.Transaction;
public interface BuyerAcceptsOfferProtocolListener {
void onOfferAccepted(Offer offer);
void onDepositTxPublished(Transaction depositTx);
void onDepositTxConfirmedInBlockchain();
void onPayoutTxPublished(Transaction payoutTx);
void onFault(Throwable throwable, BuyerAcceptsOfferProtocol.State state);
}

View file

@ -17,22 +17,137 @@
package io.bitsquare.trade.protocol.trade; package io.bitsquare.trade.protocol.trade;
import io.bitsquare.trade.Trade; import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.BlockChainService;
import io.bitsquare.btc.WalletService;
import io.bitsquare.crypto.SignatureService;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.user.User;
import io.bitsquare.util.tasks.SharedModel; import io.bitsquare.util.tasks.SharedModel;
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 TradeSharedModel extends SharedModel { public class TradeSharedModel extends SharedModel {
private static final Logger log = LoggerFactory.getLogger(TradeSharedModel.class); protected static final Logger log = LoggerFactory.getLogger(TradeSharedModel.class);
public Trade getTrade() { // provided
return trade; protected final Offer offer;
protected final TradeMessageService tradeMessageService;
protected final WalletService walletService;
protected final BlockChainService blockChainService;
protected final SignatureService signatureService;
// derived
protected final String arbitratorPubKey;
protected final BankAccount bankAccount;
protected final String accountId;
protected final PublicKey messagePublicKey;
protected final ECKey accountKey;
// data written/read by tasks
private TradeMessage tradeMessage;
protected String tradePubKeyAsHex;
protected String peersAccountId;
protected BankAccount peersBankAccount;
public TradeSharedModel(Offer offer,
TradeMessageService tradeMessageService,
WalletService walletService,
BlockChainService blockChainService,
SignatureService signatureService,
User user) {
this.offer = offer;
this.tradeMessageService = tradeMessageService;
this.walletService = walletService;
this.blockChainService = blockChainService;
this.signatureService = signatureService;
//TODO use default arbitrator for now
arbitratorPubKey = offer.getArbitrators().get(0).getPubKeyAsHex();
bankAccount = user.getBankAccount(offer.getBankAccountId());
accountId = user.getAccountId();
messagePublicKey = user.getMessagePublicKey();
accountKey = walletService.getRegistrationAddressEntry().getKey();
} }
protected final Trade trade; // getter/setter
public TradeSharedModel(Trade trade) { public TradeMessageService getTradeMessageService() {
this.trade = trade; return tradeMessageService;
} }
public WalletService getWalletService() {
return walletService;
}
public BlockChainService getBlockChainService() {
return blockChainService;
}
public SignatureService getSignatureService() {
return signatureService;
}
public Offer getOffer() {
return offer;
}
public String getArbitratorPubKey() {
return arbitratorPubKey;
}
public BankAccount getBankAccount() {
return bankAccount;
}
public String getAccountId() {
return accountId;
}
public PublicKey getMessagePublicKey() {
return messagePublicKey;
}
public ECKey getAccountKey() {
return accountKey;
}
public String getTradePubKeyAsHex() {
return tradePubKeyAsHex;
}
public void setTradePubKeyAsHex(String tradePubKeyAsHex) {
this.tradePubKeyAsHex = tradePubKeyAsHex;
}
public String getPeersAccountId() {
return peersAccountId;
}
public void setPeersAccountId(String peersAccountId) {
this.peersAccountId = peersAccountId;
}
public BankAccount getPeersBankAccount() {
return peersBankAccount;
}
public void setPeersBankAccount(BankAccount peersBankAccount) {
this.peersBankAccount = peersBankAccount;
}
public TradeMessage getTradeMessage() {
return tradeMessage;
}
public void setTradeMessage(TradeMessage tradeMessage) {
this.tradeMessage = tradeMessage;
}
} }

View file

@ -1,465 +0,0 @@
/*
* 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.offerer;
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.Contract;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener;
import io.bitsquare.trade.protocol.trade.offerer.tasks.CreateDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.RespondToTakeOfferRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendBankTransferInitedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendDepositTxIdToTaker;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendTakerDepositPaymentRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SetupListenerForBlockChainConfirmation;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignAndPublishDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignPayoutTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyAndSignContract;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakerAccount;
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.user.User;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
import java.security.PublicKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.*;
import static io.bitsquare.util.Validator.*;
/**
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing
* from the peer.
* <p/>
* This class handles the role of the offerer as the Bitcoin buyer.
* <p/>
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
* Any data from incoming messages need to be validated before further processing.
*/
public class BuyerAcceptsOfferProtocol {
private static final Logger log = LoggerFactory.getLogger(BuyerAcceptsOfferProtocol.class);
public enum State {
Init,
RespondToTakeOfferRequest,
/* VerifyTakeOfferFeePayment,*/
ValidateTakeOfferFeePayedMessage,
CreateDepositTx,
SendTakerDepositPaymentRequest,
ValidateRequestOffererPublishDepositTxMessage,
VerifyTakerAccount,
VerifyAndSignContract,
SignAndPublishDepositTx,
SignAndPublishDepositTxResulted,
SignPayoutTx,
SendSignedPayoutTx
}
// provided
private final Trade trade;
private final Peer peer;
private final TradeMessageService tradeMessageService;
private final WalletService walletService;
private final BlockChainService blockChainService;
private final SignatureService signatureService;
private final BuyerAcceptsOfferProtocolListener listener;
// derived
private final String tradeId;
private final Offer offer;
private final String arbitratorPubKey;
private final BankAccount bankAccount;
private final String accountId;
private final PublicKey messagePublicKey;
private final ECKey accountKey;
private final String payoutAddress;
// data written/read by tasks
private String preparedOffererDepositTxAsHex;
private long offererTxOutIndex;
// data written by messages, read by tasks
private String takeOfferFeeTxId;
private String tradePubKeyAsHex;
private String peersPayoutAddress;
private String peersAccountId;
private BankAccount peersBankAccount;
private PublicKey peersMessagePublicKey;
private String peersContractAsJson;
private String signedTakerDepositTxAsHex;
private String txConnOutAsHex;
private String txScriptSigAsHex;
private long takerTxOutIndex;
// state
private State state;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
public BuyerAcceptsOfferProtocol(Trade trade,
Peer peer,
TradeMessageService tradeMessageService,
WalletService walletService,
BlockChainService blockChainService,
SignatureService signatureService,
User user,
BuyerAcceptsOfferProtocolListener listener) {
this.trade = trade;
this.peer = peer;
this.listener = listener;
this.tradeMessageService = tradeMessageService;
this.walletService = walletService;
this.blockChainService = blockChainService;
this.signatureService = signatureService;
tradeId = trade.getId();
offer = trade.getOffer();
checkNotNull(tradeId);
checkNotNull(offer);
//TODO use default arbitrator for now
arbitratorPubKey = offer.getArbitrators().get(0).getPubKeyAsHex();
bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId());
accountId = user.getAccountId();
messagePublicKey = user.getMessagePublicKey();
accountKey = walletService.getRegistrationAddressEntry().getKey();
payoutAddress = walletService.getAddressInfoByTradeID(tradeId).getAddressString();
state = State.Init;
}
public void start() {
respondToTakeOfferRequest();
}
// 4. RespondToTakeOfferRequest
private void respondToTakeOfferRequest() {
log.debug("respondToTakeOfferRequest called: state = " + state);
state = State.RespondToTakeOfferRequest;
RespondToTakeOfferRequest.run(this::handleRespondToTakeOfferRequestResult, this::handleErrorMessage, tradeMessageService, peer,
trade.getState(), tradeId);
}
private void handleRespondToTakeOfferRequestResult() {
log.debug("handleRespondToTakeOfferRequestResult called: state = " + state);
// Here we are not setting a state as that is not relevant for the trade process.
// In accept case we remove the offer from the offerbook, but that happens outside of the flow of the trade process
if (trade.getState() == Trade.State.OPEN) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
listener.onOfferAccepted(offer);
}
else {
log.info("Ignore that request as we have already the offer accepted.");
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// 8. handleTakeOfferFeePayedMessage
public void handleTakeOfferFeePayedMessage(TakeOfferFeePayedMessage message) {
log.debug("handleTakeOfferFeePayedMessage called: state = " + state);
// validation
try {
checkState(state == State.RespondToTakeOfferRequest);
state = State.ValidateTakeOfferFeePayedMessage;
checkTradeId(tradeId, message);
String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId());
Coin tradeAmount = positiveCoinOf(nonZeroCoinOf(message.getTradeAmount()));
String tradePubKeyAsHex = nonEmptyStringOf(message.getTakerPubKeyAsHex());
// apply new state
this.takeOfferFeeTxId = takeOfferFeeTxId;
this.tradePubKeyAsHex = tradePubKeyAsHex;
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
trade.setTradeAmount(tradeAmount);
// next task
createDepositTx();
} catch (Throwable t) {
handleValidationFault(t);
}
}
// 9. CreateDepositTx
private void createDepositTx() {
log.debug("handleVerifyTakeOfferFeePaymentResult called: state = " + state);
state = State.CreateDepositTx;
CreateDepositTx.run(this::handleCreateDepositTxResult, this::handleFault, walletService, trade, tradePubKeyAsHex, arbitratorPubKey);
}
// 10. RequestTakerDepositPayment
private void handleCreateDepositTxResult(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex) {
log.debug("handleCreateDepositTxResult called: state = " + state);
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
this.offererTxOutIndex = offererTxOutIndex;
state = State.SendTakerDepositPaymentRequest;
SendTakerDepositPaymentRequest.run(this::handleErrorMessage,
peer,
tradeMessageService,
tradeId,
bankAccount,
accountId,
offererPubKey,
preparedOffererDepositTxAsHex,
offererTxOutIndex);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// 16. VerifyTakerAccount
public void handleRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message) {
log.debug("handleRequestOffererPublishDepositTxMessage called: state = " + state);
try {
// validation
checkState(state == State.SendTakerDepositPaymentRequest);
state = State.ValidateRequestOffererPublishDepositTxMessage;
checkTradeId(tradeId, message);
String peersPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress());
String peersAccountId = nonEmptyStringOf(message.getTakerAccountId());
BankAccount peersBankAccount = checkNotNull(message.getTakerBankAccount());
PublicKey peersMessagePublicKey = checkNotNull(message.getTakerMessagePublicKey());
String peersContractAsJson = nonEmptyStringOf(message.getTakerContractAsJson());
String signedTakerDepositTxAsHex = nonEmptyStringOf(message.getSignedTakerDepositTxAsHex());
String txConnOutAsHex = nonEmptyStringOf(message.getTxConnOutAsHex());
String txScriptSigAsHex = nonEmptyStringOf(message.getTxScriptSigAsHex());
long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex());
// apply new state
this.peersPayoutAddress = peersPayoutAddress;
this.peersAccountId = peersAccountId;
this.peersBankAccount = peersBankAccount;
this.peersMessagePublicKey = peersMessagePublicKey;
this.peersContractAsJson = peersContractAsJson;
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
this.txConnOutAsHex = txConnOutAsHex;
this.txScriptSigAsHex = txScriptSigAsHex;
this.takerTxOutIndex = takerTxOutIndex;
// next task
verifyTakerAccount();
} catch (Throwable t) {
handleValidationFault(t);
}
}
// 17. VerifyTakerAccount
private void verifyTakerAccount() {
state = State.VerifyTakerAccount;
VerifyTakerAccount.run(this::handleVerifyTakerAccountResult, this::handleFault, blockChainService,
this.peersAccountId, this.peersBankAccount);
}
// 18. VerifyAndSignContract
private void handleVerifyTakerAccountResult() {
log.debug("handleVerifyTakerAccountResult called: state = " + state);
Coin tradeAmount = trade.getTradeAmount();
state = State.VerifyAndSignContract;
VerifyAndSignContract.run(this::handleVerifyAndSignContractResult,
this::handleFault,
signatureService,
accountId,
tradeAmount,
takeOfferFeeTxId,
messagePublicKey,
offer,
peersAccountId,
bankAccount,
peersBankAccount,
peersMessagePublicKey,
peersContractAsJson,
accountKey);
}
// 19. SignAndPublishDepositTx
private void handleVerifyAndSignContractResult(Contract contract, String contractAsJson, String signature) {
log.debug("handleVerifyAndSignContractResult called: state = " + state);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setTakerContractSignature(signature);
state = State.SignAndPublishDepositTx;
SignAndPublishDepositTx.run(this::handleSignAndPublishDepositTxResult,
this::handleFault,
walletService,
preparedOffererDepositTxAsHex,
signedTakerDepositTxAsHex,
txConnOutAsHex,
txScriptSigAsHex,
offererTxOutIndex,
takerTxOutIndex);
}
private void handleSignAndPublishDepositTxResult(Transaction depositTransaction) {
log.debug("handleSignAndPublishDepositTxResult called: state = " + state);
state = State.SignAndPublishDepositTxResulted;
trade.setDepositTx(depositTransaction);
trade.setState(Trade.State.DEPOSIT_PUBLISHED);
listener.onDepositTxPublished(depositTransaction);
sendDepositTxIdToTaker(depositTransaction);
setupListenerForBlockChainConfirmation();
}
// 20a. SendDepositTxIdToTaker
private void sendDepositTxIdToTaker(Transaction depositTransaction) {
log.debug("sendDepositTxIdToTaker called: state = " + state);
SendDepositTxIdToTaker.run(this::handleErrorMessage, peer, tradeMessageService, tradeId, depositTransaction);
}
// TODO remove
// 20b. SetupListenerForBlockChainConfirmation
private void setupListenerForBlockChainConfirmation() {
log.debug("setupListenerForBlockChainConfirmation called: state = " + state);
SetupListenerForBlockChainConfirmation.run(trade.getDepositTx(), listener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Triggered UI event
///////////////////////////////////////////////////////////////////////////////////////////
// Triggered from UI event: Button click "Bank transfer inited"
// 23. SignPayoutTx
public void handleUIEventBankTransferStarted() {
log.debug("handleUIEventBankTransferStarted called: state = " + state);
String depositTransactionId = trade.getDepositTx().getHashAsString();
Coin securityDeposit = trade.getSecurityDeposit();
Coin tradeAmount = trade.getTradeAmount();
state = State.SignPayoutTx;
SignPayoutTx.run(this::handleSignPayoutTxResult,
this::handleFault,
walletService,
tradeId,
peersPayoutAddress,
payoutAddress,
depositTransactionId,
securityDeposit,
tradeAmount);
}
// 24a. SendBankTransferInitedMessage
private void handleSignPayoutTxResult(String depositTxAsHex,
String offererSignatureR,
String offererSignatureS,
Coin offererPaybackAmount,
Coin takerPaybackAmount,
String offererPayoutAddress) {
log.debug("handleSignPayoutTxResult called: state = " + state);
state = State.SendSignedPayoutTx;
SendBankTransferInitedMessage.run(this::handleFault,
peer,
tradeMessageService,
tradeId,
depositTxAsHex,
offererSignatureR,
offererSignatureS,
offererPaybackAmount,
takerPaybackAmount,
offererPayoutAddress);
verifyTakeOfferFeePayment();
}
// 24b VerifyTakeOfferFeePayment
private void verifyTakeOfferFeePayment() {
VerifyTakeOfferFeePayment.run(this::handleFault, walletService, this.takeOfferFeeTxId);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// 28. handlePayoutTxPublishedMessage
public void handlePayoutTxPublishedMessage(PayoutTxPublishedMessage message) {
log.debug("onPayoutTxPublishedMessage called: state = " + state);
try {
// validation
checkState(state == State.SendSignedPayoutTx);
checkTradeId(tradeId, message);
String payoutTxAsHex = nonEmptyStringOf(message.getPayoutTxAsHex());
// apply new state
Transaction payoutTx = new Transaction(walletService.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
listener.onPayoutTxPublished(payoutTx);
} catch (Throwable t) {
handleValidationFault(t);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// 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());
}
}

View file

@ -0,0 +1,282 @@
/*
* 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.offerer;
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.OpenOffer;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.protocol.trade.TradeSharedModel;
import io.bitsquare.user.User;
import org.bitcoinj.core.Coin;
import java.security.PublicKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BuyerAsOffererModel extends TradeSharedModel {
private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererModel.class);
// provided
private final OpenOffer openOffer;
// derived
private final String offererPaybackAddress;
// data written/read by tasks
private Trade trade;
private Peer peer;
private String preparedOffererDepositTxAsHex;
private String depositTxAsHex;
private String peersAccountId;
private BankAccount peersBankAccount;
private PublicKey peersMessagePublicKey;
private String peersContractAsJson;
private String signedTakerDepositTxAsHex;
private String txConnOutAsHex;
private String txScriptSigAsHex;
private long takerTxOutIndex;
private Coin takerPaybackAmount;
private String takeOfferFeeTxId;
private String tradePubKeyAsHex;
private String takerPayoutAddress;
private long offererTxOutIndex;
private String offererPubKey;
private String offererSignatureR;
private String offererSignatureS;
private Coin offererPaybackAmount;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
public BuyerAsOffererModel(OpenOffer openOffer,
TradeMessageService tradeMessageService,
WalletService walletService,
BlockChainService blockChainService,
SignatureService signatureService,
User user) {
super(openOffer.getOffer(),
tradeMessageService,
walletService,
blockChainService,
signatureService,
user);
this.openOffer = openOffer;
offererPaybackAddress = walletService.getAddressInfoByTradeID(offer.getId()).getAddressString();
}
//getter/setter
public OpenOffer getOpenOffer() {
return openOffer;
}
public Peer getPeer() {
return peer;
}
public String getOffererPaybackAddress() {
return offererPaybackAddress;
}
public String getPreparedOffererDepositTxAsHex() {
return preparedOffererDepositTxAsHex;
}
public void setPreparedOffererDepositTxAsHex(String preparedOffererDepositTxAsHex) {
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
}
public long getOffererTxOutIndex() {
return offererTxOutIndex;
}
public void setOffererTxOutIndex(long offererTxOutIndex) {
this.offererTxOutIndex = offererTxOutIndex;
}
public String getTakeOfferFeeTxId() {
return takeOfferFeeTxId;
}
public void setTakeOfferFeeTxId(String takeOfferFeeTxId) {
this.takeOfferFeeTxId = takeOfferFeeTxId;
}
@Override
public String getTradePubKeyAsHex() {
return tradePubKeyAsHex;
}
@Override
public void setTradePubKeyAsHex(String tradePubKeyAsHex) {
this.tradePubKeyAsHex = tradePubKeyAsHex;
}
public String getTakerPayoutAddress() {
return takerPayoutAddress;
}
public void setTakerPayoutAddress(String takerPayoutAddress) {
this.takerPayoutAddress = takerPayoutAddress;
}
@Override
public String getPeersAccountId() {
return peersAccountId;
}
@Override
public void setPeersAccountId(String peersAccountId) {
this.peersAccountId = peersAccountId;
}
@Override
public BankAccount getPeersBankAccount() {
return peersBankAccount;
}
@Override
public void setPeersBankAccount(BankAccount peersBankAccount) {
this.peersBankAccount = peersBankAccount;
}
public PublicKey getPeersMessagePublicKey() {
return peersMessagePublicKey;
}
public void setPeersMessagePublicKey(PublicKey peersMessagePublicKey) {
this.peersMessagePublicKey = peersMessagePublicKey;
}
public String getPeersContractAsJson() {
return peersContractAsJson;
}
public void setPeersContractAsJson(String peersContractAsJson) {
this.peersContractAsJson = peersContractAsJson;
}
public String getSignedTakerDepositTxAsHex() {
return signedTakerDepositTxAsHex;
}
public void setSignedTakerDepositTxAsHex(String signedTakerDepositTxAsHex) {
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
}
public String getTxConnOutAsHex() {
return txConnOutAsHex;
}
public void setTxConnOutAsHex(String txConnOutAsHex) {
this.txConnOutAsHex = txConnOutAsHex;
}
public String getTxScriptSigAsHex() {
return txScriptSigAsHex;
}
public void setTxScriptSigAsHex(String txScriptSigAsHex) {
this.txScriptSigAsHex = txScriptSigAsHex;
}
public long getTakerTxOutIndex() {
return takerTxOutIndex;
}
public void setTakerTxOutIndex(long takerTxOutIndex) {
this.takerTxOutIndex = takerTxOutIndex;
}
public String getOffererPubKey() {
return offererPubKey;
}
public void setOffererPubKey(String offererPubKey) {
this.offererPubKey = offererPubKey;
}
public String getDepositTxAsHex() {
return depositTxAsHex;
}
public void setDepositTxAsHex(String depositTxAsHex) {
this.depositTxAsHex = depositTxAsHex;
}
public String getOffererSignatureR() {
return offererSignatureR;
}
public void setOffererSignatureR(String offererSignatureR) {
this.offererSignatureR = offererSignatureR;
}
public String getOffererSignatureS() {
return offererSignatureS;
}
public void setOffererSignatureS(String offererSignatureS) {
this.offererSignatureS = offererSignatureS;
}
public Coin getOffererPaybackAmount() {
return offererPaybackAmount;
}
public void setOffererPaybackAmount(Coin offererPaybackAmount) {
this.offererPaybackAmount = offererPaybackAmount;
}
public Coin getTakerPaybackAmount() {
return takerPaybackAmount;
}
public void setTakerPaybackAmount(Coin takerPaybackAmount) {
this.takerPaybackAmount = takerPaybackAmount;
}
public void setTrade(Trade trade) {
this.trade = trade;
}
public Trade getTrade() {
return trade;
}
public void setPeer(Peer peer) {
this.peer = peer;
}
}

View file

@ -0,0 +1,218 @@
/*
* 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.offerer;
import io.bitsquare.network.Message;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.TradeMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.CreateDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessPayoutTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessRequestOffererPublishDepositTxMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessRequestTakeOfferMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessTakeOfferFeePayedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.RespondToTakeOfferRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendBankTransferInitedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendDepositTxIdToTaker;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendTakerDepositPaymentRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SetupListenerForBlockChainConfirmation;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignAndPublishDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignPayoutTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyAndSignContract;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakerAccount;
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.nonEmptyStringOf;
/**
* Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing
* from the peer.
* <p/>
* This class handles the role of the offerer as the Bitcoin buyer.
* <p/>
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
* Any data from incoming messages need to be validated before further processing.
*/
public class BuyerAsOffererProtocol {
private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererProtocol.class);
private BuyerAsOffererModel model;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
public BuyerAsOffererProtocol(BuyerAsOffererModel model) {
this.model = model;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
///////////////////////////////////////////////////////////////////////////////////////////
public void start() {
model.getTradeMessageService().addMessageHandler(this::handleMessage);
}
public void cleanup() {
model.getTradeMessageService().removeMessageHandler(this::handleMessage);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message handling
///////////////////////////////////////////////////////////////////////////////////////////
private void handleMessage(Message message, Peer peer) {
log.trace("handleNewMessage: message = " + message.getClass().getSimpleName());
if (message instanceof TradeMessage) {
TradeMessage tradeMessage = (TradeMessage) message;
nonEmptyStringOf(tradeMessage.getTradeId());
if (tradeMessage instanceof RequestTakeOfferMessage) {
handleRequestTakeOfferMessage((RequestTakeOfferMessage) tradeMessage, peer);
}
else if (tradeMessage instanceof TakeOfferFeePayedMessage) {
handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
}
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) {
handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
}
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
}
else {
log.error("Incoming tradeMessage not supported. " + tradeMessage);
}
}
}
private void handleRequestTakeOfferMessage(RequestTakeOfferMessage tradeMessage, Peer peer) {
model.setTradeMessage(tradeMessage);
model.setPeer(peer);
BuyerAsOffererTaskRunner<BuyerAsOffererModel> sequence = new BuyerAsOffererTaskRunner<>(model,
() -> {
log.debug("sequence0 completed");
},
(message, throwable) -> {
log.error(message);
}
);
sequence.addTasks(
ProcessRequestTakeOfferMessage.class,
RespondToTakeOfferRequest.class
);
sequence.run();
}
private void handleTakeOfferFeePayedMessage(TakeOfferFeePayedMessage tradeMessage) {
model.setTradeMessage(tradeMessage);
BuyerAsOffererTaskRunner<BuyerAsOffererModel> sequence = new BuyerAsOffererTaskRunner<>(model,
() -> {
log.debug("sequence1 completed");
},
(message, throwable) -> {
log.error(message);
}
);
sequence.addTasks(
ProcessTakeOfferFeePayedMessage.class,
CreateDepositTx.class,
SendTakerDepositPaymentRequest.class
);
sequence.run();
}
private void handleRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage tradeMessage) {
model.setTradeMessage(tradeMessage);
BuyerAsOffererTaskRunner<BuyerAsOffererModel> sequence = new BuyerAsOffererTaskRunner<>(model,
() -> {
log.debug("sequence2 completed");
},
(message, throwable) -> {
log.error(message);
}
);
sequence.addTasks(
ProcessRequestOffererPublishDepositTxMessage.class,
VerifyTakerAccount.class,
VerifyAndSignContract.class,
SignAndPublishDepositTx.class,
SetupListenerForBlockChainConfirmation.class,
SendDepositTxIdToTaker.class
);
sequence.run();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI event handling
///////////////////////////////////////////////////////////////////////////////////////////
// User clicked the "bank transfer started" button
public void handleBankTransferStartedUIEvent() {
BuyerAsOffererTaskRunner<BuyerAsOffererModel> sequence = new BuyerAsOffererTaskRunner<>(model,
() -> {
log.debug("sequence3 completed");
},
(message, throwable) -> {
log.error(message);
}
);
sequence.addTasks(
SignPayoutTx.class,
VerifyTakeOfferFeePayment.class,
SendBankTransferInitedMessage.class
);
sequence.run();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message handling
///////////////////////////////////////////////////////////////////////////////////////////
private void handlePayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage) {
model.setTradeMessage(tradeMessage);
BuyerAsOffererTaskRunner<BuyerAsOffererModel> sequence = new BuyerAsOffererTaskRunner<>(model,
() -> {
log.debug("sequence4 completed");
},
(message, throwable) -> {
log.error(message);
}
);
sequence.addTasks(ProcessPayoutTxPublishedMessage.class);
sequence.run();
}
}

View file

@ -15,12 +15,11 @@
* 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; package io.bitsquare.trade.protocol.trade.offerer;
import io.bitsquare.trade.protocol.trade.TradeSharedModel; import io.bitsquare.trade.Trade;
import io.bitsquare.util.handlers.FaultHandler; import io.bitsquare.util.handlers.FaultHandler;
import io.bitsquare.util.handlers.ResultHandler; import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -28,26 +27,13 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class TradeTaskRunner<T extends TradeSharedModel> extends TaskRunner<TradeSharedModel> { public class BuyerAsOffererTaskRunner<T extends BuyerAsOffererModel> extends TaskRunner<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(TradeTaskRunner.class); private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererTaskRunner.class);
public TradeTaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { public BuyerAsOffererTaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
super(sharedModel, resultHandler, 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 @Override
public void handleFault(String message, @NotNull Throwable throwable) { public void handleFault(String message, @NotNull Throwable throwable) {
sharedModel.getTrade().setState(Trade.State.FAILED); sharedModel.getTrade().setState(Trade.State.FAILED);

View file

@ -18,9 +18,9 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.WalletService; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.Trade; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.handlers.ExceptionHandler; 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;
@ -30,34 +30,35 @@ import org.bitcoinj.core.Utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class CreateDepositTx { public class CreateDepositTx extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(CreateDepositTx.class); private static final Logger log = LoggerFactory.getLogger(CreateDepositTx.class);
public static void run(ResultHandler resultHandler, public CreateDepositTx(TaskRunner taskHandler, BuyerAsOffererModel model) {
ExceptionHandler exceptionHandler, super(taskHandler, model);
WalletService walletService, }
Trade trade,
String takerMultiSigPubKey, @Override
String arbitratorPubKeyAsHex) { protected void run() {
log.trace("Run CreateDepositTx task");
try { try {
String offererPubKey = walletService.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(); String offererPubKey = model.getWalletService().getAddressInfoByTradeID(model.getTrade().getId()).getPubKeyAsHexString();
Coin offererInputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE); Coin offererInputAmount = model.getTrade().getSecurityDeposit().add(FeePolicy.TX_FEE);
Transaction transaction = walletService.offererCreatesMSTxAndAddPayment(offererInputAmount, offererPubKey, takerMultiSigPubKey, Transaction transaction = model.getWalletService().offererCreatesMSTxAndAddPayment(
arbitratorPubKeyAsHex, trade.getId()); offererInputAmount,
offererPubKey,
model.getTradePubKeyAsHex(),
model.getArbitratorPubKey(),
model.getTrade().getId());
String preparedOffererDepositTxAsHex = Utils.HEX.encode(transaction.bitcoinSerialize()); String preparedOffererDepositTxAsHex = Utils.HEX.encode(transaction.bitcoinSerialize());
long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex(); long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex();
resultHandler.onResult(offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex); model.setOffererPubKey(offererPubKey);
model.setPreparedOffererDepositTxAsHex(preparedOffererDepositTxAsHex);
model.setOffererTxOutIndex(offererTxOutIndex);
complete();
} catch (InsufficientMoneyException e) { } catch (InsufficientMoneyException e) {
log.error("Create deposit tx failed due InsufficientMoneyException " + e); failed(e);
exceptionHandler.handleException(e);
} }
} }
public interface ResultHandler {
void onResult(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex);
}
} }

View 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.protocol.trade.offerer.tasks;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.*;
public class ProcessPayoutTxPublishedMessage extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(ProcessPayoutTxPublishedMessage.class);
public ProcessPayoutTxPublishedMessage(TaskRunner taskHandler, BuyerAsOffererModel model) {
super(taskHandler, model);
}
@Override
protected void run() {
try {
checkTradeId(model.getTrade().getId(), model.getTradeMessage());
String payoutTxAsHex = nonEmptyStringOf(((PayoutTxPublishedMessage) model.getTradeMessage()).getPayoutTxAsHex());
Transaction payoutTx = new Transaction(model.getWalletService().getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
model.getTrade().setPayoutTx(payoutTx);
model.getTrade().setState(Trade.State.PAYOUT_PUBLISHED);
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -0,0 +1,59 @@
/*
* 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.offerer.tasks;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
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 ProcessRequestOffererPublishDepositTxMessage extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(ProcessRequestOffererPublishDepositTxMessage.class);
public ProcessRequestOffererPublishDepositTxMessage(TaskRunner taskHandler, BuyerAsOffererModel model) {
super(taskHandler, model);
}
@Override
protected void run() {
try {
checkTradeId(model.getTrade().getId(), model.getTradeMessage());
RequestOffererPublishDepositTxMessage message = (RequestOffererPublishDepositTxMessage) model.getTradeMessage();
model.setTakerPayoutAddress(nonEmptyStringOf(message.getTakerPayoutAddress()));
model.setPeersAccountId(nonEmptyStringOf(message.getTakerAccountId()));
model.setPeersBankAccount(checkNotNull(message.getTakerBankAccount()));
model.setPeersMessagePublicKey(checkNotNull(message.getTakerMessagePublicKey()));
model.setPeersContractAsJson(nonEmptyStringOf(message.getTakerContractAsJson()));
model.setSignedTakerDepositTxAsHex(nonEmptyStringOf(message.getSignedTakerDepositTxAsHex()));
model.setTxConnOutAsHex(nonEmptyStringOf(message.getTxConnOutAsHex()));
model.setTxScriptSigAsHex(nonEmptyStringOf(message.getTxScriptSigAsHex()));
model.setTakerTxOutIndex(nonNegativeLongOf(message.getTakerTxOutIndex()));
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -0,0 +1,46 @@
/*
* 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.offerer.tasks;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.checkTradeId;
public class ProcessRequestTakeOfferMessage extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(ProcessRequestTakeOfferMessage.class);
public ProcessRequestTakeOfferMessage(TaskRunner taskHandler, BuyerAsOffererModel model) {
super(taskHandler, model);
}
@Override
protected void run() {
try {
checkTradeId(model.getOffer().getId(), model.getTradeMessage());
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -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.offerer.tasks;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.*;
public class ProcessTakeOfferFeePayedMessage extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(ProcessTakeOfferFeePayedMessage.class);
public ProcessTakeOfferFeePayedMessage(TaskRunner taskHandler, BuyerAsOffererModel model) {
super(taskHandler, model);
}
@Override
protected void run() {
try {
checkTradeId(model.getTrade().getId(), model.getTradeMessage());
Trade trade = model.getTrade();
TakeOfferFeePayedMessage takeOfferFeePayedMessage = (TakeOfferFeePayedMessage) model.getTradeMessage();
trade.setTakeOfferFeeTxID(nonEmptyStringOf(takeOfferFeePayedMessage.getTakeOfferFeeTxId()));
trade.setTradeAmount(positiveCoinOf(nonZeroCoinOf(takeOfferFeePayedMessage.getTradeAmount())));
model.setTakeOfferFeeTxId(nonEmptyStringOf(takeOfferFeePayedMessage.getTakeOfferFeeTxId()));
model.setTradePubKeyAsHex(nonEmptyStringOf(takeOfferFeePayedMessage.getTakerPubKeyAsHex()));
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -17,43 +17,47 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.network.Peer; import io.bitsquare.offer.OpenOffer;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener; import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
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 RespondToTakeOfferRequest { public class RespondToTakeOfferRequest extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(RespondToTakeOfferRequest.class); private static final Logger log = LoggerFactory.getLogger(RespondToTakeOfferRequest.class);
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, public RespondToTakeOfferRequest(TaskRunner taskHandler, BuyerAsOffererModel model) {
TradeMessageService tradeMessageService, Peer peer, Trade.State tradeState, String tradeId) { super(taskHandler, model);
log.trace("Run HandleTakeOfferRequest task");
boolean takeOfferRequestAccepted = tradeState == Trade.State.OPEN;
if (!takeOfferRequestAccepted) {
log.warn("Received take offer request but the offer not marked as open anymore.");
} }
RespondToTakeOfferRequestMessage tradeMessage = new RespondToTakeOfferRequestMessage(tradeId, takeOfferRequestAccepted);
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() { @Override
protected void run() {
boolean takeOfferRequestAccepted = model.getOpenOffer().getState() == OpenOffer.State.OPEN;
if (!takeOfferRequestAccepted)
log.info("Received take offer request but the offer not marked as open anymore.");
Trade trade = new Trade(model.getOpenOffer().getOffer());
model.setTrade(trade);
model.getOpenOffer().setState(OpenOffer.State.OFFER_ACCEPTED);
RespondToTakeOfferRequestMessage tradeMessage = new RespondToTakeOfferRequestMessage(trade.getId(), takeOfferRequestAccepted);
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {
log.trace("RespondToTakeOfferRequestMessage successfully arrived at peer"); log.trace("RespondToTakeOfferRequestMessage successfully arrived at peer");
resultHandler.handleResult(); complete();
} }
@Override @Override
public void handleFault() { public void handleFault() {
log.error("AcceptTakeOfferRequestMessage did not arrive at peer"); failed("AcceptTakeOfferRequestMessage did not arrive at peer");
errorMessageHandler.handleErrorMessage("AcceptTakeOfferRequestMessage did not arrive at peer");
} }
}); });
}
public interface ResultHandler {
void handleResult();
} }
} }

View file

@ -17,53 +17,43 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.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.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage;
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.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SendBankTransferInitedMessage { public class SendBankTransferInitedMessage extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SendBankTransferInitedMessage.class); private static final Logger log = LoggerFactory.getLogger(SendBankTransferInitedMessage.class);
public static void run(ExceptionHandler exceptionHandler, public SendBankTransferInitedMessage(TaskRunner taskHandler, BuyerAsOffererModel model) {
Peer peer, super(taskHandler, model);
TradeMessageService tradeMessageService, }
String tradeId,
String depositTxAsHex, @Override
String offererSignatureR, protected void run() {
String offererSignatureS, BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(
Coin offererPaybackAmount, model.getTrade().getId(),
Coin takerPaybackAmount, model.getDepositTxAsHex(),
String offererPayoutAddress) { model.getOffererSignatureR(),
log.trace("Run SendSignedPayoutTx task"); model.getOffererSignatureS(),
try { model.getOffererPaybackAmount(),
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(tradeId, model.getTakerPaybackAmount(),
depositTxAsHex, model.getOffererPaybackAddress());
offererSignatureR, model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
offererSignatureS,
offererPaybackAmount,
takerPaybackAmount,
offererPayoutAddress);
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {
log.trace("Sending BankTransferInitedMessage succeeded."); log.trace("Sending BankTransferInitedMessage succeeded.");
complete();
} }
@Override @Override
public void handleFault() { public void handleFault() {
exceptionHandler.handleException(new Exception("Sending BankTransferInitedMessage failed.")); failed("Sending BankTransferInitedMessage failed.");
} }
}); });
} catch (Exception e) {
exceptionHandler.handleException(e);
}
} }
} }

View file

@ -17,39 +17,40 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.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.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage;
import io.bitsquare.util.handlers.ErrorMessageHandler; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils; import org.bitcoinj.core.Utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SendDepositTxIdToTaker { public class SendDepositTxIdToTaker extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class); private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
public static void run( ErrorMessageHandler errorMessageHandler, Peer peer, public SendDepositTxIdToTaker(TaskRunner taskHandler, BuyerAsOffererModel model) {
TradeMessageService tradeMessageService, String tradeId, Transaction depositTransaction) { super(taskHandler, model);
log.trace("Run task"); }
DepositTxPublishedMessage tradeMessage =
new DepositTxPublishedMessage(tradeId, Utils.HEX.encode(depositTransaction.bitcoinSerialize()));
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() { @Override
protected void run() {
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(model.getTrade().getId(),
Utils.HEX.encode(model.getTrade().getDepositTx().bitcoinSerialize()));
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {
log.trace("DepositTxPublishedMessage successfully arrived at peer"); log.trace("DepositTxPublishedMessage successfully arrived at peer");
complete();
} }
@Override @Override
public void handleFault() { public void handleFault() {
log.error("DepositTxPublishedMessage did not arrive at peer"); failed("Sending DepositTxPublishedMessage failed.");
errorMessageHandler.handleErrorMessage("DepositTxPublishedMessage did not arrive at peer");
} }
}); });
} }
} }

View file

@ -17,43 +17,43 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.bank.BankAccount;
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.offerer.BuyerAsOffererModel;
import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage;
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 SendTakerDepositPaymentRequest { public class SendTakerDepositPaymentRequest extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SendTakerDepositPaymentRequest.class); private static final Logger log = LoggerFactory.getLogger(SendTakerDepositPaymentRequest.class);
public static void run(ErrorMessageHandler errorMessageHandler, public SendTakerDepositPaymentRequest(TaskRunner taskHandler, BuyerAsOffererModel model) {
Peer peer, super(taskHandler, model);
TradeMessageService tradeMessageService, }
String tradeId,
BankAccount bankAccount, @Override
String accountId, protected void run() {
String offererPubKey,
String preparedOffererDepositTxAsHex,
long offererTxOutIndex) {
log.trace("Run SendTakerDepositPaymentRequest task");
TakerDepositPaymentRequestMessage tradeMessage = new TakerDepositPaymentRequestMessage( TakerDepositPaymentRequestMessage tradeMessage = new TakerDepositPaymentRequestMessage(
tradeId, bankAccount, accountId, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex); model.getTrade().getId(),
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() { model.getBankAccount(),
model.getAccountId(),
model.getOffererPubKey(),
model.getPreparedOffererDepositTxAsHex(),
model.getOffererTxOutIndex());
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer"); log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
complete();
} }
@Override @Override
public void handleFault() { public void handleFault() {
log.error("RequestTakerDepositPaymentMessage did not arrive at peer"); failed("RequestTakerDepositPaymentMessage did not arrive at peer");
errorMessageHandler.handleErrorMessage("RequestTakerDepositPaymentMessage did not arrive at peer");
} }
}); });
} }
} }

View file

@ -17,7 +17,10 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
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.TransactionConfidence; import org.bitcoinj.core.TransactionConfidence;
@ -26,25 +29,30 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
// TODO should be removed // TODO should be removed
public class SetupListenerForBlockChainConfirmation { public class SetupListenerForBlockChainConfirmation extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class); private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
public static void run(Transaction depositTransaction, BuyerAcceptsOfferProtocolListener listener) { public SetupListenerForBlockChainConfirmation(TaskRunner taskHandler, BuyerAsOffererModel model) {
log.trace("Run SetupListenerForBlockChainConfirmation task"); super(taskHandler, model);
//TODO }
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener() { @Override
protected void run() {
TransactionConfidence confidence = model.getTrade().getDepositTx().getConfidence();
confidence.addEventListener(new TransactionConfidence.Listener() {
@Override @Override
public void onConfidenceChanged(Transaction tx, ChangeReason reason) { public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
log.trace("onConfidenceChanged " + tx.getConfidence()); log.trace("onConfidenceChanged " + tx.getConfidence());
if (reason == ChangeReason.TYPE && if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
listener.onDepositTxConfirmedInBlockchain(); model.getTrade().setState(Trade.State.DEPOSIT_CONFIRMED);
depositTransaction.getConfidence().removeEventListener(this);
log.trace("Tx is in blockchain"); //TODO not sure if that works
confidence.removeEventListener(this);
} }
} }
}); });
complete();
} }
} }

View file

@ -17,8 +17,10 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.WalletService; import io.bitsquare.trade.Trade;
import io.bitsquare.util.handlers.ExceptionHandler; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
@ -29,47 +31,40 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SignAndPublishDepositTx { public class SignAndPublishDepositTx extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class); private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
public static void run(ResultHandler resultHandler, public SignAndPublishDepositTx(TaskRunner taskHandler, BuyerAsOffererModel model) {
ExceptionHandler exceptionHandler, super(taskHandler, model);
WalletService walletService, }
String preparedOffererDepositTxAsHex,
String signedTakerDepositTxAsHex, @Override
String txConnOutAsHex, protected void run() {
String txScriptSigAsHex,
long offererTxOutIndex,
long takerTxOutIndex) {
log.trace("Run task");
try { try {
walletService.offererSignAndPublishTx(preparedOffererDepositTxAsHex, model.getWalletService().offererSignAndPublishTx(model.getPreparedOffererDepositTxAsHex(),
signedTakerDepositTxAsHex, model.getSignedTakerDepositTxAsHex(),
txConnOutAsHex, model.getTxConnOutAsHex(),
txScriptSigAsHex, model.getTxScriptSigAsHex(),
offererTxOutIndex, model.getOffererTxOutIndex(),
takerTxOutIndex, model.getTakerTxOutIndex(),
new FutureCallback<Transaction>() { new FutureCallback<Transaction>() {
@Override @Override
public void onSuccess(Transaction transaction) { public void onSuccess(Transaction transaction) {
log.trace("offererSignAndPublishTx succeeded " + transaction); log.trace("offererSignAndPublishTx succeeded " + transaction);
resultHandler.onResult(transaction);
model.getTrade().setDepositTx(transaction);
model.getTrade().setState(Trade.State.DEPOSIT_PUBLISHED);
complete();
} }
@Override @Override
public void onFailure(@NotNull Throwable t) { public void onFailure(@NotNull Throwable t) {
log.error("offererSignAndPublishTx faultHandler.onFault:" + t); failed(t);
exceptionHandler.handleException(t);
} }
}); });
} catch (Exception e) { } catch (Exception e) {
log.error("offererSignAndPublishTx faultHandler.onFault:" + e); failed(e);
exceptionHandler.handleException(e);
} }
} }
public interface ResultHandler {
void onResult(Transaction depositTransaction);
}
} }

View file

@ -17,8 +17,10 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.WalletService; import io.bitsquare.trade.Trade;
import io.bitsquare.util.handlers.ExceptionHandler; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
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.ECKey; import org.bitcoinj.core.ECKey;
@ -28,45 +30,37 @@ import javafx.util.Pair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SignPayoutTx { public class SignPayoutTx extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(SignPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(SignPayoutTx.class);
public static void run(ResultHandler resultHandler, public SignPayoutTx(TaskRunner taskHandler, BuyerAsOffererModel model) {
ExceptionHandler exceptionHandler, super(taskHandler, model);
WalletService walletService, }
String tradeId,
String takerPayoutAddress, @Override
String offererPayoutAddress, protected void run() {
String depositTransactionId,
Coin securityDeposit,
Coin tradeAmount) {
log.trace("Run SignPayoutTx task");
try { try {
Coin offererPaybackAmount = tradeAmount.add(securityDeposit); Trade trade = model.getTrade();
Coin securityDeposit = trade.getSecurityDeposit();
Coin offererPaybackAmount = trade.getTradeAmount().add(securityDeposit);
@SuppressWarnings("UnnecessaryLocalVariable") Coin takerPaybackAmount = securityDeposit; @SuppressWarnings("UnnecessaryLocalVariable") Coin takerPaybackAmount = securityDeposit;
Pair<ECKey.ECDSASignature, String> result = walletService.offererCreatesAndSignsPayoutTx( Pair<ECKey.ECDSASignature, String> result = model.getWalletService().offererCreatesAndSignsPayoutTx(
depositTransactionId, offererPaybackAmount, takerPaybackAmount, takerPayoutAddress, tradeId); trade.getDepositTx().getHashAsString(), offererPaybackAmount, takerPaybackAmount, model.getTakerPayoutAddress(), model.getTrade().getId());
ECKey.ECDSASignature offererSignature = result.getKey(); ECKey.ECDSASignature offererSignature = result.getKey();
String offererSignatureR = offererSignature.r.toString();
String offererSignatureS = offererSignature.s.toString();
String depositTxAsHex = result.getValue(); String depositTxAsHex = result.getValue();
resultHandler.handleResult(depositTxAsHex, offererSignatureR, offererSignatureS, offererPaybackAmount, takerPaybackAmount, offererPayoutAddress); model.setDepositTxAsHex(depositTxAsHex);
model.setOffererSignatureR(offererSignature.r.toString());
model.setOffererSignatureS(offererSignature.s.toString());
model.setOffererPaybackAmount(offererPaybackAmount);
model.setTakerPaybackAmount(takerPaybackAmount);
complete();
} catch (Exception e) { } catch (Exception e) {
exceptionHandler.handleException(e); failed(e);
}
} }
} }
public interface ResultHandler {
void handleResult(String depositTxAsHex,
String offererSignatureR,
String offererSignatureS,
Coin offererPaybackAmount,
Coin takerPaybackAmount,
String offererPayoutAddress);
}
}

View file

@ -17,51 +17,44 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.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.offerer.BuyerAsOffererModel;
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 VerifyAndSignContract { public class VerifyAndSignContract extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class); private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class);
public static void run(ResultHandler resultHandler, public VerifyAndSignContract(TaskRunner taskHandler, BuyerAsOffererModel model) {
ExceptionHandler exceptionHandler, super(taskHandler, model);
SignatureService signatureService, }
String accountId,
Coin tradeAmount,
String takeOfferFeeTxId,
PublicKey messagePublicKey,
Offer offer,
String peersAccountId,
BankAccount bankAccount,
BankAccount peersBankAccount,
PublicKey takerMessagePublicKey,
String peersContractAsJson,
ECKey registrationKey) {
log.trace("Run task");
Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, accountId, peersAccountId,
bankAccount, peersBankAccount, messagePublicKey, takerMessagePublicKey);
@Override
protected void run() {
Trade trade = model.getTrade();
Contract contract = new Contract(
model.getOffer(),
trade.getTradeAmount(),
model.getTakeOfferFeeTxId(),
model.getAccountId(),
model.getPeersAccountId(),
model.getBankAccount(),
model.getPeersBankAccount(),
model.getMessagePublicKey(),
model.getPeersMessagePublicKey());
String contractAsJson = Utilities.objectToJson(contract); String contractAsJson = Utilities.objectToJson(contract);
String signature = model.getSignatureService().signMessage(model.getAccountKey(), contractAsJson);
log.trace("The 2 contracts as json does match"); trade.setContract(contract);
String signature = signatureService.signMessage(registrationKey, contractAsJson); trade.setContractAsJson(contractAsJson);
//log.trace("signature: " + signature); trade.setTakerContractSignature(signature);
resultHandler.onResult(contract, contractAsJson, signature);
}
public interface ResultHandler { complete();
void onResult(Contract contract, String contractAsJson, String signature);
} }
} }

View file

@ -17,23 +17,29 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.WalletService; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
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 VerifyTakeOfferFeePayment { public class VerifyTakeOfferFeePayment extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class); private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class);
public static void run(ExceptionHandler exceptionHandler, WalletService walletService, public VerifyTakeOfferFeePayment(TaskRunner taskHandler, BuyerAsOffererModel model) {
String takeOfferFeeTxId) { super(taskHandler, model);
log.trace("Run VerifyTakeOfferFeePayment task"); }
@Override
protected void run() {
//TODO mocked yet, need a confidence listeners //TODO mocked yet, need a confidence listeners
int numOfPeersSeenTx = walletService.getNumOfPeersSeenTx(takeOfferFeeTxId); int numOfPeersSeenTx = model.getWalletService().getNumOfPeersSeenTx(model.getTakeOfferFeeTxId());
/* if (numOfPeersSeenTx > 2) { /* if (numOfPeersSeenTx > 2) {
resultHandler.handleResult(); resultHandler.handleResult();
}*/ }*/
complete();
} }
} }

View file

@ -17,22 +17,34 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.bank.BankAccount; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel;
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 VerifyTakerAccount { public class VerifyTakerAccount extends Task<BuyerAsOffererModel> {
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class); private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, public VerifyTakerAccount(TaskRunner taskHandler, BuyerAsOffererModel model) {
BlockChainService blockChainService, String peersAccountId, BankAccount peersBankAccount) { super(taskHandler, model);
log.trace("Run task");
VerifyPeerAccount.run(resultHandler, exceptionHandler, blockChainService, peersAccountId, peersBankAccount);
} }
@Override
protected void run() {
//TODO mocked yet
if (model.getBlockChainService().verifyAccountRegistration()) {
if (model.getBlockChainService().isAccountBlackListed(model.getPeersAccountId(), model.getPeersBankAccount())) {
log.error("Taker is blacklisted");
failed("Taker is blacklisted");
}
else {
complete();
}
}
else {
failed("Account registration validation for peer failed.");
}
}
} }

View file

@ -17,20 +17,16 @@
package io.bitsquare.trade.protocol.trade.taker; package io.bitsquare.trade.protocol.trade.taker;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.BlockChainService; import io.bitsquare.btc.BlockChainService;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.crypto.SignatureService; import io.bitsquare.crypto.SignatureService;
import io.bitsquare.network.Peer; import io.bitsquare.network.Peer;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.protocol.trade.TradeMessage;
import io.bitsquare.trade.protocol.trade.TradeSharedModel; import io.bitsquare.trade.protocol.trade.TradeSharedModel;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
import java.security.PublicKey; import java.security.PublicKey;
@ -38,304 +34,175 @@ import java.security.PublicKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SellerTakesOfferModel extends TradeSharedModel { public class SellerAsTakerModel extends TradeSharedModel {
private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferModel.class); private static final Logger log = LoggerFactory.getLogger(SellerAsTakerModel.class);
private Transaction payoutTx;
private String payoutTxAsHex;
public void setPayoutTx(Transaction payoutTx) { // provided
this.payoutTx = payoutTx; private final Trade trade;
}
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 // 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 Coin tradeAmount;
private final String tradePubKeyAsHex;
private final ECKey accountKey;
private final PublicKey offererMessagePublicKey;
private final Coin securityDeposit; private final Coin securityDeposit;
private final String arbitratorPubKey; private final PublicKey offererMessagePublicKey;
// written/read by task // written/read by task
private Peer peer; private Peer peer;
// written by messages, read by tasks
private String peersAccountId;
private BankAccount peersBankAccount;
private String peersPubKey;
private String preparedPeersDepositTxAsHex; private String preparedPeersDepositTxAsHex;
private long peersTxOutIndex;
private String depositTxAsHex; private String depositTxAsHex;
private Transaction signedTakerDepositTx;
private Transaction payoutTx;
private String payoutTxAsHex;
private Coin takerPaybackAmount;
private String peersPubKey;
private long peersTxOutIndex;
private String offererSignatureR; private String offererSignatureR;
private String offererSignatureS; private String offererSignatureS;
private Coin offererPaybackAmount; private Coin offererPaybackAmount;
private Coin takerPaybackAmount;
private String offererPayoutAddress; private String offererPayoutAddress;
private Transaction signedTakerDepositTx;
private TradeMessage tradeMessage; public SellerAsTakerModel(Trade trade,
// state
private State state;
public SellerTakesOfferModel(Trade trade,
TradeMessageService tradeMessageService, TradeMessageService tradeMessageService,
WalletService walletService, WalletService walletService,
BlockChainService blockChainService, BlockChainService blockChainService,
SignatureService signatureService, SignatureService signatureService,
User user) { User user) {
super(trade); super(trade.getOffer(),
this.tradeMessageService = tradeMessageService; tradeMessageService,
this.walletService = walletService; walletService,
this.blockChainService = blockChainService; blockChainService,
this.signatureService = signatureService; signatureService,
user);
offer = trade.getOffer(); this.trade = trade;
tradeId = trade.getId();
tradeAmount = trade.getTradeAmount(); tradeAmount = trade.getTradeAmount();
securityDeposit = trade.getSecurityDeposit(); securityDeposit = trade.getSecurityDeposit();
//TODO use 1. for now
arbitratorPubKey = trade.getOffer().getArbitrators().get(0).getPubKeyAsHex();
offererMessagePublicKey = offer.getMessagePublicKey(); offererMessagePublicKey = offer.getMessagePublicKey();
tradePubKeyAsHex = walletService.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
bankAccount = user.getCurrentBankAccount().get();
accountId = user.getAccountId();
messagePublicKey = user.getMessagePublicKey();
tradePubKeyAsHex = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
accountKey = walletService.getRegistrationAddressEntry().getKey();
state = State.Init;
} }
// getter/setter
// 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() { public Trade getTrade() {
return trade; 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() { public Coin getTradeAmount() {
return tradeAmount; return tradeAmount;
} }
public String getTradePubKeyAsHex() { public Coin getSecurityDeposit() {
return tradePubKeyAsHex; return securityDeposit;
}
public ECKey getAccountKey() {
return accountKey;
} }
public PublicKey getOffererMessagePublicKey() { public PublicKey getOffererMessagePublicKey() {
return offererMessagePublicKey; return offererMessagePublicKey;
} }
public Coin getSecurityDeposit() {
return securityDeposit;
}
public String getArbitratorPubKey() {
return arbitratorPubKey;
}
public Peer getPeer() { public Peer getPeer() {
return peer; return peer;
} }
public String getPeersAccountId() { public void setPeer(Peer peer) {
return peersAccountId; this.peer = peer;
} }
public BankAccount getPeersBankAccount() { public Transaction getPayoutTx() {
return peersBankAccount; return payoutTx;
}
public void setPayoutTx(Transaction payoutTx) {
this.payoutTx = payoutTx;
}
public String getPayoutTxAsHex() {
return payoutTxAsHex;
}
public void setPayoutTxAsHex(String payoutTxAsHex) {
this.payoutTxAsHex = payoutTxAsHex;
} }
public String getPeersPubKey() { public String getPeersPubKey() {
return peersPubKey; return peersPubKey;
} }
public void setPeersPubKey(String peersPubKey) {
this.peersPubKey = peersPubKey;
}
public String getPreparedPeersDepositTxAsHex() { public String getPreparedPeersDepositTxAsHex() {
return preparedPeersDepositTxAsHex; return preparedPeersDepositTxAsHex;
} }
public void setPreparedPeersDepositTxAsHex(String preparedPeersDepositTxAsHex) {
this.preparedPeersDepositTxAsHex = preparedPeersDepositTxAsHex;
}
public long getPeersTxOutIndex() { public long getPeersTxOutIndex() {
return peersTxOutIndex; return peersTxOutIndex;
} }
public void setPeersTxOutIndex(long peersTxOutIndex) {
this.peersTxOutIndex = peersTxOutIndex;
}
public String getDepositTxAsHex() { public String getDepositTxAsHex() {
return depositTxAsHex; return depositTxAsHex;
} }
public void setDepositTxAsHex(String depositTxAsHex) {
this.depositTxAsHex = depositTxAsHex;
}
public String getOffererSignatureR() { public String getOffererSignatureR() {
return offererSignatureR; return offererSignatureR;
} }
public void setOffererSignatureR(String offererSignatureR) {
this.offererSignatureR = offererSignatureR;
}
public String getOffererSignatureS() { public String getOffererSignatureS() {
return offererSignatureS; return offererSignatureS;
} }
public void setOffererSignatureS(String offererSignatureS) {
this.offererSignatureS = offererSignatureS;
}
public Coin getOffererPaybackAmount() { public Coin getOffererPaybackAmount() {
return offererPaybackAmount; return offererPaybackAmount;
} }
public void setOffererPaybackAmount(Coin offererPaybackAmount) {
this.offererPaybackAmount = offererPaybackAmount;
}
public Coin getTakerPaybackAmount() { public Coin getTakerPaybackAmount() {
return takerPaybackAmount; return takerPaybackAmount;
} }
public void setTakerPaybackAmount(Coin takerPaybackAmount) {
this.takerPaybackAmount = takerPaybackAmount;
}
public String getOffererPayoutAddress() { public String getOffererPayoutAddress() {
return offererPayoutAddress; return offererPayoutAddress;
} }
public State getState() { public void setOffererPayoutAddress(String offererPayoutAddress) {
return state; this.offererPayoutAddress = offererPayoutAddress;
} }
public TradeMessage getTradeMessage() { public Transaction getSignedTakerDepositTx() {
return tradeMessage;
} public Transaction getSignedTakerDepositTx() {
return signedTakerDepositTx; return signedTakerDepositTx;
} }
public void setSignedTakerDepositTx(Transaction signedTakerDepositTx) {
this.signedTakerDepositTx = signedTakerDepositTx;
}
} }

View file

@ -20,7 +20,6 @@ package io.bitsquare.trade.protocol.trade.taker;
import io.bitsquare.network.Message; import io.bitsquare.network.Message;
import io.bitsquare.network.Peer; import io.bitsquare.network.Peer;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeTaskRunner;
import io.bitsquare.trade.protocol.trade.TradeMessage; 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;
@ -36,10 +35,10 @@ 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.ProcessBankTransferInitedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateDepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.ProcessDepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateRespondToTakeOfferRequestMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.ProcessRespondToTakeOfferRequestMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.ValidateTakerDepositPaymentRequestMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.ProcessTakerDepositPaymentRequestMessage;
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;
@ -56,24 +55,29 @@ import static io.bitsquare.util.Validator.nonEmptyStringOf;
* It uses sub tasks to not pollute the main class too much with all the async result/fault handling. * It uses sub tasks to not pollute the main class too much with all the async result/fault handling.
* Any data from incoming messages as well data used to send to the peer need to be validated before further processing. * Any data from incoming messages as well data used to send to the peer need to be validated before further processing.
*/ */
public class SellerTakesOfferProtocol { public class SellerAsTakerProtocol {
private static final Logger log = LoggerFactory.getLogger(SellerTakesOfferProtocol.class); private static final Logger log = LoggerFactory.getLogger(SellerAsTakerProtocol.class);
private final SellerTakesOfferModel model; private final SellerAsTakerModel model;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public SellerTakesOfferProtocol(SellerTakesOfferModel model) { public SellerAsTakerProtocol(SellerAsTakerModel model) {
this.model = model; this.model = model;
} }
public void start() {
///////////////////////////////////////////////////////////////////////////////////////////
// UI event handling
///////////////////////////////////////////////////////////////////////////////////////////
public void handleRequestTakeOfferUIEvent() {
model.getTradeMessageService().addMessageHandler(this::handleMessage); model.getTradeMessageService().addMessageHandler(this::handleMessage);
TradeTaskRunner<SellerTakesOfferModel> sequence1 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence1 completed"); log.debug("sequence1 completed");
}, },
@ -81,17 +85,18 @@ public class SellerTakesOfferProtocol {
log.error(message); log.error(message);
} }
); );
sequence1.addTasks( sequence.addTasks(
GetPeerAddress.class, GetPeerAddress.class,
RequestTakeOffer.class RequestTakeOffer.class
); );
sequence1.run(); sequence.run();
} }
public void cleanup() { public void cleanup() {
model.getTradeMessageService().removeMessageHandler(this::handleMessage); model.getTradeMessageService().removeMessageHandler(this::handleMessage);
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message handling // Incoming message handling
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -103,16 +108,16 @@ public class SellerTakesOfferProtocol {
nonEmptyStringOf(tradeMessage.getTradeId()); nonEmptyStringOf(tradeMessage.getTradeId());
if (tradeMessage instanceof RespondToTakeOfferRequestMessage) { if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
handleTradeMessage((RespondToTakeOfferRequestMessage) tradeMessage); handleRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage);
} }
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) { else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
handleTradeMessage((TakerDepositPaymentRequestMessage) tradeMessage); handleTakerDepositPaymentRequestMessage((TakerDepositPaymentRequestMessage) tradeMessage);
} }
else if (tradeMessage instanceof DepositTxPublishedMessage) { else if (tradeMessage instanceof DepositTxPublishedMessage) {
handleTradeMessage((DepositTxPublishedMessage) tradeMessage); handleDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
} }
else if (tradeMessage instanceof BankTransferInitedMessage) { else if (tradeMessage instanceof BankTransferInitedMessage) {
handleTradeMessage((BankTransferInitedMessage) tradeMessage); handleBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
} }
else { else {
log.error("Incoming message not supported. " + tradeMessage); log.error("Incoming message not supported. " + tradeMessage);
@ -120,10 +125,10 @@ public class SellerTakesOfferProtocol {
} }
} }
private void handleTradeMessage(RespondToTakeOfferRequestMessage tradeMessage) { private void handleRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage tradeMessage) {
model.setTradeMessage(tradeMessage); model.setTradeMessage(tradeMessage);
TradeTaskRunner<SellerTakesOfferModel> sequence2 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence2 = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence2 completed"); log.debug("sequence2 completed");
}, },
@ -132,17 +137,17 @@ public class SellerTakesOfferProtocol {
} }
); );
sequence2.addTasks( sequence2.addTasks(
ValidateRespondToTakeOfferRequestMessage.class, ProcessRespondToTakeOfferRequestMessage.class,
PayTakeOfferFee.class, PayTakeOfferFee.class,
SendTakeOfferFeePayedMessage.class SendTakeOfferFeePayedMessage.class
); );
sequence2.run(); sequence2.run();
} }
private void handleTradeMessage(TakerDepositPaymentRequestMessage tradeMessage) { private void handleTakerDepositPaymentRequestMessage(TakerDepositPaymentRequestMessage tradeMessage) {
model.setTradeMessage(tradeMessage); model.setTradeMessage(tradeMessage);
TradeTaskRunner<SellerTakesOfferModel> sequence3 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence3 = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence3 completed"); log.debug("sequence3 completed");
}, },
@ -151,7 +156,7 @@ public class SellerTakesOfferProtocol {
} }
); );
sequence3.addTasks( sequence3.addTasks(
ValidateTakerDepositPaymentRequestMessage.class, ProcessTakerDepositPaymentRequestMessage.class,
VerifyOffererAccount.class, VerifyOffererAccount.class,
CreateAndSignContract.class, CreateAndSignContract.class,
PayDeposit.class, PayDeposit.class,
@ -160,10 +165,10 @@ public class SellerTakesOfferProtocol {
sequence3.run(); sequence3.run();
} }
private void handleTradeMessage(DepositTxPublishedMessage tradeMessage) { private void handleDepositTxPublishedMessage(DepositTxPublishedMessage tradeMessage) {
model.setTradeMessage(tradeMessage); model.setTradeMessage(tradeMessage);
TradeTaskRunner<SellerTakesOfferModel> sequence4 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence4 = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence4 completed"); log.debug("sequence4 completed");
}, },
@ -172,16 +177,16 @@ public class SellerTakesOfferProtocol {
} }
); );
sequence4.addTasks( sequence4.addTasks(
ValidateDepositTxPublishedMessage.class, ProcessDepositTxPublishedMessage.class,
TakerCommitDepositTx.class TakerCommitDepositTx.class
); );
sequence4.run(); sequence4.run();
} }
private void handleTradeMessage(BankTransferInitedMessage tradeMessage) { private void handleBankTransferInitedMessage(BankTransferInitedMessage tradeMessage) {
model.setTradeMessage(tradeMessage); model.setTradeMessage(tradeMessage);
TradeTaskRunner<SellerTakesOfferModel> sequence5 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence5 = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence5 completed"); log.debug("sequence5 completed");
model.getTrade().setState(Trade.State.FIAT_PAYMENT_STARTED); model.getTrade().setState(Trade.State.FIAT_PAYMENT_STARTED);
@ -190,7 +195,7 @@ public class SellerTakesOfferProtocol {
log.error(message); log.error(message);
} }
); );
sequence5.addTasks(ValidateBankTransferInitedMessage.class); sequence5.addTasks(ProcessBankTransferInitedMessage.class);
sequence5.run(); sequence5.run();
} }
@ -200,7 +205,7 @@ public class SellerTakesOfferProtocol {
// 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
public void handleFiatReceivedUIEvent() { public void handleFiatReceivedUIEvent() {
TradeTaskRunner<SellerTakesOfferModel> sequence6 = new TradeTaskRunner<>(model, SellerAsTakerTaskRunner<SellerAsTakerModel> sequence6 = new SellerAsTakerTaskRunner<>(model,
() -> { () -> {
log.debug("sequence6 completed"); log.debug("sequence6 completed");
}, },

View file

@ -0,0 +1,42 @@
/*
* 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.trade.Trade;
import io.bitsquare.util.handlers.FaultHandler;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.util.tasks.TaskRunner;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SellerAsTakerTaskRunner<T extends SellerAsTakerModel> extends TaskRunner<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(SellerAsTakerTaskRunner.class);
public SellerAsTakerTaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) {
super(sharedModel, resultHandler, faultHandler);
}
@Override
public void handleFault(String message, @NotNull Throwable throwable) {
sharedModel.getTrade().setState(Trade.State.FAILED);
super.handleFault(message, throwable);
}
}

View file

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.Contract; import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -27,10 +27,10 @@ import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class CreateAndSignContract extends Task<SellerTakesOfferModel> { public class CreateAndSignContract extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class); private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
public CreateAndSignContract(TaskRunner taskHandler, SellerTakesOfferModel model) { public CreateAndSignContract(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }

View file

@ -20,7 +20,7 @@ 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.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.handlers.ErrorMessageHandler; import io.bitsquare.util.handlers.ErrorMessageHandler;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -30,10 +30,10 @@ import java.security.PublicKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class GetPeerAddress extends Task<SellerTakesOfferModel> { public class GetPeerAddress extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class); private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
public GetPeerAddress(TaskRunner taskHandler, SellerTakesOfferModel model) { public GetPeerAddress(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }

View file

@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -28,10 +28,10 @@ import org.bitcoinj.core.Transaction;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class PayDeposit extends Task<SellerTakesOfferModel> { public class PayDeposit extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class); private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
public PayDeposit(TaskRunner taskHandler, SellerTakesOfferModel model) { public PayDeposit(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@ -47,7 +47,7 @@ public class PayDeposit extends Task<SellerTakesOfferModel> {
model.getTradePubKeyAsHex(), model.getTradePubKeyAsHex(),
model.getArbitratorPubKey(), model.getArbitratorPubKey(),
model.getPreparedPeersDepositTxAsHex(), model.getPreparedPeersDepositTxAsHex(),
model.getTradeId()); model.getTrade().getId());
model.setSignedTakerDepositTx(signedTakerDepositTx); model.setSignedTakerDepositTx(signedTakerDepositTx);

View file

@ -17,7 +17,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -31,17 +31,17 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class PayTakeOfferFee extends Task<SellerTakesOfferModel> { public class PayTakeOfferFee extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class); private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
public PayTakeOfferFee(TaskRunner taskHandler, SellerTakesOfferModel model) { public PayTakeOfferFee(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
try { try {
model.getWalletService().payTakeOfferFee(model.getTradeId(), new FutureCallback<Transaction>() { model.getWalletService().payTakeOfferFee(model.getTrade().getId(), 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());

View file

@ -18,28 +18,26 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
import static io.bitsquare.util.Validator.*; import static io.bitsquare.util.Validator.*;
public class ValidateBankTransferInitedMessage extends Task<SellerTakesOfferModel> { public class ProcessBankTransferInitedMessage extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(ValidateBankTransferInitedMessage.class); private static final Logger log = LoggerFactory.getLogger(ProcessBankTransferInitedMessage.class);
public ValidateBankTransferInitedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { public ProcessBankTransferInitedMessage(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
try { try {
checkState(model.getTrade().getPreviousTask() == TakerCommitDepositTx.class); checkTradeId(model.getTrade().getId(), model.getTradeMessage());
checkTradeId(model.getTradeId(), model.getTradeMessage());
BankTransferInitedMessage message = (BankTransferInitedMessage) model.getTradeMessage(); BankTransferInitedMessage message = (BankTransferInitedMessage) model.getTradeMessage();
model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex())); model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex()));
@ -49,7 +47,7 @@ public class ValidateBankTransferInitedMessage extends Task<SellerTakesOfferMode
model.setTakerPaybackAmount(positiveCoinOf(nonZeroCoinOf(message.getTakerPaybackAmount()))); model.setTakerPaybackAmount(positiveCoinOf(nonZeroCoinOf(message.getTakerPaybackAmount())));
model.setOffererPayoutAddress(nonEmptyStringOf(message.getOffererPayoutAddress())); model.setOffererPayoutAddress(nonEmptyStringOf(message.getOffererPayoutAddress()));
// TODO listener.onBankTransferInited(message.getTradeId()); // TODO listener.onBankTransferInited(message.getTrade().getId());
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {
failed(t); failed(t);

View file

@ -18,28 +18,26 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
import static io.bitsquare.util.Validator.*; import static io.bitsquare.util.Validator.*;
public class ValidateDepositTxPublishedMessage extends Task<SellerTakesOfferModel> { public class ProcessDepositTxPublishedMessage extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(ValidateDepositTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(ProcessDepositTxPublishedMessage.class);
public ValidateDepositTxPublishedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { public ProcessDepositTxPublishedMessage(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
try { try {
checkState(model.getTrade().getPreviousTask() == SendSignedTakerDepositTxAsHex.class); checkTradeId(model.getTrade().getId(), model.getTradeMessage());
checkTradeId(model.getTradeId(), model.getTradeMessage());
DepositTxPublishedMessage message = (DepositTxPublishedMessage) model.getTradeMessage(); DepositTxPublishedMessage message = (DepositTxPublishedMessage) model.getTradeMessage();
model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex())); model.setDepositTxAsHex(nonEmptyStringOf(message.getDepositTxAsHex()));

View file

@ -19,28 +19,26 @@ package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkState;
import static io.bitsquare.util.Validator.checkTradeId; import static io.bitsquare.util.Validator.checkTradeId;
public class ValidateRespondToTakeOfferRequestMessage extends Task<SellerTakesOfferModel> { public class ProcessRespondToTakeOfferRequestMessage extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(ValidateRespondToTakeOfferRequestMessage.class); private static final Logger log = LoggerFactory.getLogger(ProcessRespondToTakeOfferRequestMessage.class);
public ValidateRespondToTakeOfferRequestMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { public ProcessRespondToTakeOfferRequestMessage(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
try { try {
checkState(model.getTrade().getPreviousTask() == RequestTakeOffer.class); checkTradeId(model.getTrade().getId(), model.getTradeMessage());
checkTradeId(model.getTradeId(), model.getTradeMessage());
if (((RespondToTakeOfferRequestMessage) model.getTradeMessage()).isTakeOfferRequestAccepted()) { if (((RespondToTakeOfferRequestMessage) model.getTradeMessage()).isTakeOfferRequestAccepted()) {
model.getTrade().setState(Trade.State.OFFERER_ACCEPTED); model.getTrade().setState(Trade.State.OFFERER_ACCEPTED);

View file

@ -18,28 +18,27 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage; import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
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 com.google.common.base.Preconditions.checkNotNull;
import static io.bitsquare.util.Validator.*; import static io.bitsquare.util.Validator.*;
public class ValidateTakerDepositPaymentRequestMessage extends Task<SellerTakesOfferModel> { public class ProcessTakerDepositPaymentRequestMessage extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(ValidateTakerDepositPaymentRequestMessage.class); private static final Logger log = LoggerFactory.getLogger(ProcessTakerDepositPaymentRequestMessage.class);
public ValidateTakerDepositPaymentRequestMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { public ProcessTakerDepositPaymentRequestMessage(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
try { try {
checkState(model.getTrade().getPreviousTask() == SendTakeOfferFeePayedMessage.class); checkTradeId(model.getTrade().getId(), model.getTradeMessage());
checkTradeId(model.getTradeId(), model.getTradeMessage());
TakerDepositPaymentRequestMessage message = (TakerDepositPaymentRequestMessage) model.getTradeMessage(); TakerDepositPaymentRequestMessage message = (TakerDepositPaymentRequestMessage) model.getTradeMessage();
model.setPeersAccountId(nonEmptyStringOf(message.getAccountId())); model.setPeersAccountId(nonEmptyStringOf(message.getAccountId()));
model.setPeersBankAccount(checkNotNull(message.getBankAccount())); model.setPeersBankAccount(checkNotNull(message.getBankAccount()));

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
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.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage; import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -26,16 +26,16 @@ 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 extends Task<SellerTakesOfferModel> { public class RequestTakeOffer extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class); private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
public RequestTakeOffer(TaskRunner taskHandler, SellerTakesOfferModel model) { public RequestTakeOffer(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
model.getTradeMessageService().sendMessage(model.getPeer(), new RequestTakeOfferMessage(model.getTradeId()), model.getTradeMessageService().sendMessage(model.getPeer(), new RequestTakeOfferMessage(model.getTrade().getId()),
new SendMessageListener() { new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
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.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage; import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -26,16 +26,16 @@ 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 extends Task<SellerTakesOfferModel> { public class SendPayoutTxToOfferer extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class); private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
public SendPayoutTxToOfferer(TaskRunner taskHandler, SellerTakesOfferModel model) { public SendPayoutTxToOfferer(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(model.getTradeId(), model.getPayoutTxAsHex()); PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(model.getTrade().getId(), model.getPayoutTxAsHex());
model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() { model.getTradeMessageService().sendMessage(model.getPeer(), tradeMessage, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
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.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage; import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -29,10 +29,10 @@ import org.bitcoinj.core.Utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SendSignedTakerDepositTxAsHex extends Task<SellerTakesOfferModel> { public class SendSignedTakerDepositTxAsHex extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class); private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
public SendSignedTakerDepositTxAsHex(TaskRunner taskHandler, SellerTakesOfferModel model) { public SendSignedTakerDepositTxAsHex(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@ -42,7 +42,7 @@ public class SendSignedTakerDepositTxAsHex extends Task<SellerTakesOfferModel> {
long takerTxOutIndex = model.getSignedTakerDepositTx().getInput(1).getOutpoint().getIndex(); long takerTxOutIndex = model.getSignedTakerDepositTx().getInput(1).getOutpoint().getIndex();
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage( RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(
model.getTradeId(), model.getTrade().getId(),
model.getBankAccount(), model.getBankAccount(),
model.getAccountId(), model.getAccountId(),
model.getMessagePublicKey(), model.getMessagePublicKey(),
@ -51,7 +51,7 @@ public class SendSignedTakerDepositTxAsHex extends Task<SellerTakesOfferModel> {
Utils.HEX.encode(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()), Utils.HEX.encode(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
model.getTrade().getContractAsJson(), model.getTrade().getContractAsJson(),
model.getTrade().getTakerContractSignature(), model.getTrade().getTakerContractSignature(),
model.getWalletService().getAddressInfoByTradeID(model.getTradeId()).getAddressString(), model.getWalletService().getAddressInfoByTradeID(model.getTrade().getId()).getAddressString(),
takerTxOutIndex, takerTxOutIndex,
model.getPeersTxOutIndex()); model.getPeersTxOutIndex());

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
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.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage; import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -26,17 +26,17 @@ import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SendTakeOfferFeePayedMessage extends Task<SellerTakesOfferModel> { public class SendTakeOfferFeePayedMessage extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class); private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class);
public SendTakeOfferFeePayedMessage(TaskRunner taskHandler, SellerTakesOfferModel model) { public SendTakeOfferFeePayedMessage(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@Override @Override
protected void run() { protected void run() {
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage( TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(
model.getTradeId(), model.getTrade().getId(),
model.getTrade().getTakeOfferFeeTxId(), model.getTrade().getTakeOfferFeeTxId(),
model.getTradeAmount(), model.getTradeAmount(),
model.getTradePubKeyAsHex() model.getTradePubKeyAsHex()

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -33,10 +33,10 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class SignAndPublishPayoutTx extends Task<SellerTakesOfferModel> { public class SignAndPublishPayoutTx extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
public SignAndPublishPayoutTx(TaskRunner taskHandler, SellerTakesOfferModel model) { public SignAndPublishPayoutTx(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }
@ -49,7 +49,7 @@ public class SignAndPublishPayoutTx extends Task<SellerTakesOfferModel> {
model.getOffererPaybackAmount(), model.getOffererPaybackAmount(),
model.getTakerPaybackAmount(), model.getTakerPaybackAmount(),
model.getOffererPayoutAddress(), model.getOffererPayoutAddress(),
model.getTradeId(), model.getTrade().getId(),
new FutureCallback<Transaction>() { new FutureCallback<Transaction>() {
@Override @Override
public void onSuccess(Transaction transaction) { public void onSuccess(Transaction transaction) {

View file

@ -18,7 +18,7 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
@ -27,10 +27,10 @@ import org.bitcoinj.core.Transaction;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class TakerCommitDepositTx extends Task<SellerTakesOfferModel> { public class TakerCommitDepositTx extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class); private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class);
public TakerCommitDepositTx(TaskRunner taskHandler, SellerTakesOfferModel model) { public TakerCommitDepositTx(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }

View file

@ -17,17 +17,17 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; 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 extends Task<SellerTakesOfferModel> { public class VerifyOfferFeePayment extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class); private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class);
public VerifyOfferFeePayment(TaskRunner taskHandler, SellerTakesOfferModel model) { public VerifyOfferFeePayment(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }

View file

@ -17,17 +17,17 @@
package io.bitsquare.trade.protocol.trade.taker.tasks; package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.Task;
import io.bitsquare.util.tasks.TaskRunner; import io.bitsquare.util.tasks.TaskRunner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class VerifyOffererAccount extends Task<SellerTakesOfferModel> { public class VerifyOffererAccount extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class); private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
public VerifyOffererAccount(TaskRunner taskHandler, SellerTakesOfferModel model) { public VerifyOffererAccount(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model); super(taskHandler, model);
} }