Refactor payment process

This commit is contained in:
Manfred Karrer 2015-03-10 16:53:25 +01:00
parent 397aedc099
commit aee5addacf
32 changed files with 472 additions and 462 deletions

View File

@ -39,7 +39,6 @@ import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
import org.bitcoinj.core.TransactionOutput;
import org.bitcoinj.core.Utils;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.core.Wallet;
import org.bitcoinj.core.WalletEventListener;
import org.bitcoinj.crypto.DeterministicKey;
@ -624,11 +623,11 @@ public class WalletService {
log.trace("offererPubKey=" + offererPubKey);
log.trace("takerPubKey=" + takerPubKey);
log.trace("arbitratorPubKey=" + arbitratorPubKey);
log.trace("offererInputAmount=" + offererInputAmount.toFriendlyString());
log.trace("tradeId=" + tradeId);
// we need to subtract the fee as it will go to the miners
Coin amountToPay = offererInputAmount.subtract(FeePolicy.TX_FEE);
log.trace("amountToPay=" + amountToPay.toFriendlyString());
// We need to subtract the fee as it will go to the miners
Coin offererInput = offererInputAmount.subtract(FeePolicy.TX_FEE);
log.trace("amountToPay=" + offererInput.toFriendlyString());
// We pay the offererInputAmount to a temporary MS output which will be changed later to the correct value.
// With the usage of completeTx() we get all the work done with fee calculation, validation and coin selection.
@ -638,7 +637,7 @@ public class WalletService {
// The btc tx fee will be included by the completeTx() call, so we don't need to add it manually.
Transaction tx = new Transaction(params);
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
tx.addOutput(amountToPay, multiSigOutputScript);
tx.addOutput(offererInput, multiSigOutputScript); // that output is just a dummy for input calculation
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
sendRequest.shuffleOutputs = false;
@ -660,8 +659,7 @@ public class WalletService {
/*
IN[0] any input > offererInputAmount + fee (unsigned)
OUT[0] MS offererInputAmount
OUT[1] Change = input - offererInputAmount - fee
btc tx fee
OUT[1] Optional Change = input - offererInputAmount - fee btc tx fee
*/
log.trace("Check if wallet is consistent: result=" + wallet.isConsistent());
@ -688,6 +686,7 @@ public class WalletService {
log.trace("takerPubKey=" + takerPubKey);
log.trace("arbitratorPubKey=" + arbitratorPubKey);
log.trace("offerersPartialDepositTxAsHex=" + offerersPartialDepositTxAsHex);
log.trace("tradeId=" + tradeId);
// We pay the btc tx fee 2 times to the deposit tx:
// 1. will be spent to miners when publishing the deposit tx
@ -718,8 +717,7 @@ public class WalletService {
/*
IN[0] any input taker > takerInputAmount + fee (signed)
OUT[0] MS takerInputAmount
OUT[1] Change = input taker - takerInputAmount - fee
btc tx fee
OUT[1] Optional change = input taker - takerInputAmount - fee btc tx fee
*/
@ -736,7 +734,9 @@ public class WalletService {
*/
// Now we add the inputs and outputs from our temp tx and change the multiSig amount to the correct value
// TODO multiple inputs not supported yet
tx.addInput(tempTx.getInput(0));
// handle optional change output
if (tempTx.getOutputs().size() == 2) {
tx.addOutput(tempTx.getOutput(1));
}
@ -745,11 +745,10 @@ public class WalletService {
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE);
tx.getOutput(0).setValue(msOutputAmount);
// Now we sign our input
// Now we sign our input (index 1)
TransactionInput input = tx.getInput(1);
if (input == null || input.getConnectedOutput() == null) {
log.error("input or input.getConnectedOutput() is null: " + input);
}
if (input == null || input.getConnectedOutput() == null)
log.error("Must not happen - input or input.getConnectedOutput() is null: " + input);
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
@ -778,8 +777,7 @@ public class WalletService {
IN[1] any input taker > takerInputAmount + fee (signed) e.g.: 1.1001
OUT[0] MS offererInputAmount e.g.: 1.2001
OUT[1] Change = input offerer - offererInputAmount - fee e.g.: 0 if input is matching correct value
OUT[2] Change = input taker - takerInputAmount - fee e.g.: 0 if input is matching correct value
btc tx fee e.g.: 0.1001
OUT[2] Change = input taker - takerInputAmount - fee e.g.: 0 if input is matching correct value btc tx fee e.g.: 0.1001
*/
// We must not commit that tx to the wallet as we will get it over the network when the offerer
@ -926,13 +924,9 @@ public class WalletService {
// boolean isAlreadyInWallet = wallet.maybeCommitTx(depositTx);
//log.trace("isAlreadyInWallet=" + isAlreadyInWallet);
try {
// Manually add the multisigContract to the wallet, overriding the isRelevant checks so we can track
// it and check for double-spends later
wallet.receivePending(depositTx, null, true);
} catch (VerificationException e) {
throw new RuntimeException(e); // Cannot happen, we already called multisigContract.verify()
}
// Manually add the multisigContract to the wallet, overriding the isRelevant checks so we can track
// it and check for double-spends later
wallet.receivePending(depositTx, null, true);
return depositTx;

View File

@ -548,7 +548,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
setGraphic(iconView);
}
else {
if (stateProperty != null) {
if (stateProperty != null && stateChangeListener != null) {
stateProperty.removeListener(stateChangeListener);
stateChangeListener = null;
}

View File

@ -142,9 +142,16 @@ class TakeOfferDataModel implements Activatable, DataModel {
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue);
switch (newValue) {
// TODO Check why DEPOSIT_CONFIRMED can happen, refactor state handling
case OPEN:
break;
case OFFERER_ACCEPTED:
break;
case OFFERER_REJECTED:
requestTakeOfferErrorMessage.set("Take offer request got rejected. Maybe another trader has taken the offer in the meantime.");
break;
case DEPOSIT_PUBLISHED:
case DEPOSIT_CONFIRMED:
// TODO Check why DEPOSIT_CONFIRMED can happen, refactor state handling
// TODO null pointer happened here!
if (trade.getDepositTx() != null) {
transactionId.set(trade.getDepositTx().getHashAsString());
@ -155,14 +162,15 @@ class TakeOfferDataModel implements Activatable, DataModel {
" That should not happen and needs more investigation why it can happen.");
}
break;
case PAYMENT_STARTED:
break;
case FAILED:
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
break;
case OFFERER_REJECTED:
requestTakeOfferErrorMessage.set("Take offer request got rejected.");
case COMPLETED:
break;
default:
log.warn("Unhandled trade state: " + newValue);
log.error("Unhandled trade state: " + newValue);
break;
}
});

View File

@ -163,13 +163,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
showPaymentInfoScreenButton.setVisible(true);
}
else if ((state == Offer.State.OFFER_NOT_AVAILABLE)) {
Popups.openWarningPopup("You cannot take that offer",
"The offerer is either offline or the offer was already taken by another trader.");
Popups.openWarningPopup("You cannot take that offer", "The offerer is either offline or the offer was already taken by another trader.");
close();
}
else if ((state == Offer.State.OFFER_REMOVED)) {
Popups.openWarningPopup("You cannot take that offer",
"The offerer has been removed in the meantime.");
Popups.openWarningPopup("You cannot take that offer", "The offerer has been removed in the meantime.");
close();
}
}
@ -196,8 +194,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
}
});
Popups.openInfoPopup("To ensure that both traders behave fair they need to pay a security deposit.",
"The deposit will stay in your local trading wallet until the offer gets accepted by " +
"another trader. " +
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader. " +
"\nIt will be refunded to you after the trade has successfully completed.",
actions);

View File

@ -53,7 +53,7 @@ public class Trade implements Serializable {
private String takeOfferFeeTxID;
private Contract contract;
private String contractAsJson;
private String takerSignature;
private String takerContractSignature;
private Transaction depositTx;
private Transaction payoutTx;
@ -86,8 +86,8 @@ public class Trade implements Serializable {
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setContractTakerSignature(String takerSignature) {
this.takerSignature = takerSignature;
public void setTakerContractSignature(String takerSignature) {
this.takerContractSignature = takerSignature;
}
public void setTakeOfferFeeTxID(String takeOfferFeeTxID) {
@ -143,8 +143,8 @@ public class Trade implements Serializable {
return offer.getVolumeByAmount(tradeAmount);
}
public String getTakerSignature() {
return takerSignature;
public String getTakerContractSignature() {
return takerContractSignature;
}
public Transaction getDepositTx() {

View File

@ -30,20 +30,20 @@ import io.bitsquare.offer.OfferBookService;
import io.bitsquare.offer.OpenOffer;
import io.bitsquare.persistence.Persistence;
import io.bitsquare.trade.handlers.TransactionResultHandler;
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener;
import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener;
import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol;
import io.bitsquare.trade.protocol.trade.OfferMessage;
import io.bitsquare.trade.protocol.trade.TradeMessage;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocolListener;
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.RequestTakerDepositPaymentMessage;
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.taker.RequestIsOfferAvailableProtocol;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocolListener;
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.RequestOffererPublishDepositTxMessage;
@ -227,6 +227,8 @@ public class TradeManager {
pendingTrades.put(offer.getId(), trade);
persistPendingTrades();
currentPendingTrade = trade;
return trade;
}
@ -241,6 +243,14 @@ public class TradeManager {
persistClosedTrades();
}
private void removeFailedTrade(Trade trade) {
if (!pendingTrades.containsKey(trade.getId()))
log.error("trades does not contain the trade with the ID " + trade.getId());
pendingTrades.remove(trade.getId());
persistPendingTrades();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Trading protocols
@ -251,7 +261,6 @@ public class TradeManager {
if (openOffers.containsKey(offerId)) {
Offer offer = openOffers.get(offerId).getOffer();
Trade trade = createTrade(offer);
currentPendingTrade = trade;
BuyerAcceptsOfferProtocol buyerAcceptsOfferProtocol = new BuyerAcceptsOfferProtocol(trade,
sender,
@ -263,10 +272,10 @@ public class TradeManager {
new BuyerAcceptsOfferProtocolListener() {
@Override
public void onOfferAccepted(Offer offer) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
persistPendingTrades();
//TODO do that later
requestRemoveOpenOffer(offer.getId(),
() -> log.debug("remove was successful"),
() -> log.debug("remove offer was successful"),
(message) -> log.error(message));
}
@ -298,21 +307,11 @@ public class TradeManager {
@Override
public void onFault(Throwable throwable, BuyerAcceptsOfferProtocol.State state) {
log.error("Error while executing trade process at state: " + state + " / " + throwable);
trade.setFault(throwable);
trade.setState(Trade.State.FAILED);
persistPendingTrades();
}
// probably not needed
@Override
public void onWaitingForPeerResponse(BuyerAcceptsOfferProtocol.State state) {
log.debug("Waiting for peers response at state " + state);
}
// probably not needed
@Override
public void onWaitingForUserInteraction(BuyerAcceptsOfferProtocol.State state) {
log.debug("Waiting for UI activity at state " + state);
switch (state) {
case RespondToTakeOfferRequest:
removeFailedTrade(trade);
break;
}
}
});
@ -336,18 +335,15 @@ public class TradeManager {
Trade trade = createTrade(offer);
trade.setTradeAmount(amount);
currentPendingTrade = trade;
SellerTakesOfferProtocolListener listener = new SellerTakesOfferProtocolListener() {
@Override
public void onTakeOfferRequestAccepted(Trade trade) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
public void onTakeOfferRequestAccepted() {
persistPendingTrades();
}
@Override
public void onTakeOfferRequestRejected(Trade trade) {
trade.setState(Trade.State.OFFERER_REJECTED);
persistPendingTrades();
public void onTakeOfferRequestRejected() {
removeFailedTrade(trade);
}
@Override
@ -369,25 +365,28 @@ public class TradeManager {
trade.setState(Trade.State.COMPLETED);
// We close the trade when the user has withdrawn his trade funds (see #283)
//closeTrade(trade);
persistPendingTrades();
}
@Override
public void onFault(Throwable throwable, SellerTakesOfferProtocol.State state) {
log.error("onFault: " + throwable.getMessage() + " / " + state);
log.error("Error while executing trade process at state: " + state + " / " + throwable);
switch (state) {
case GetPeerAddress:
// TODO add unreachable node to a local ignore list in case of repeated failures
removeFailedTrade(trade);
break;
case RequestTakeOffer:
// TODO add unreachable node to a local ignore list in case of repeated failures
removeFailedTrade(trade);
break;
case PayTakeOfferFee:
removeFailedTrade(trade);
break;
case SendTakeOfferFeePayedMessage:
removeFailedTrade(trade);
break;
}
}
// probably not needed
@Override
public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) {
log.debug("onWaitingForPeerResponse");
}
}
};
@ -411,7 +410,7 @@ public class TradeManager {
// Also we don't support yet offline messaging (mail box)
public void fiatPaymentStarted(String tradeId) {
if (offererAsBuyerProtocolMap.get(tradeId) != null) {
offererAsBuyerProtocolMap.get(tradeId).onUIEventBankTransferInited();
offererAsBuyerProtocolMap.get(tradeId).handleUIEventBankTransferInited();
pendingTrades.get(tradeId).setState(Trade.State.PAYMENT_STARTED);
persistPendingTrades();
}
@ -423,7 +422,7 @@ public class TradeManager {
}
public void fiatPaymentReceived(String tradeId) {
takerAsSellerProtocolMap.get(tradeId).onUIEventFiatReceived();
takerAsSellerProtocolMap.get(tradeId).handleUIEventFiatReceived();
}
public void requestIsOfferAvailable(Offer offer) {
@ -436,12 +435,12 @@ public class TradeManager {
log.warn("requestIsOfferAvailable already called for offer with ID:" + offer.getId());
}
}
// When closing take offer view, we are not interested in the requestIsOfferAvailable result anymore, so remove from the map
public void stopRequestIsOfferAvailableRequest(Offer offer) {
requestIsOfferAvailableProtocolMap.remove(offer.getId());
}
public void onOfferRemovedFromRemoteOfferBook(Offer offer) {
requestIsOfferAvailableProtocolMap.remove(offer.getId());
}
@ -488,23 +487,24 @@ public class TradeManager {
checkNotNull(tradeId);
if (tradeMessage instanceof RequestTakeOfferMessage) {
// Step 3. in trade protocol
createOffererAsBuyerProtocol(tradeId, sender);
}
else if (tradeMessage instanceof RespondToTakeOfferRequestMessage) {
takerAsSellerProtocolMap.get(tradeId).onRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage);
takerAsSellerProtocolMap.get(tradeId).handleRespondToTakeOfferRequestMessage((RespondToTakeOfferRequestMessage) tradeMessage);
}
else if (tradeMessage instanceof TakeOfferFeePayedMessage) {
offererAsBuyerProtocolMap.get(tradeId).onTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
offererAsBuyerProtocolMap.get(tradeId).handleTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
}
else if (tradeMessage instanceof RequestTakerDepositPaymentMessage) {
takerAsSellerProtocolMap.get(tradeId).onRequestTakerDepositPaymentMessage((RequestTakerDepositPaymentMessage) tradeMessage);
else if (tradeMessage instanceof TakerDepositPaymentRequestMessage) {
takerAsSellerProtocolMap.get(tradeId).handleTakerDepositPaymentRequestMessage((TakerDepositPaymentRequestMessage) tradeMessage);
}
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage) {
offererAsBuyerProtocolMap.get(tradeId).onRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
offererAsBuyerProtocolMap.get(tradeId).handleRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
}
else if (tradeMessage instanceof DepositTxPublishedMessage) {
persistPendingTrades();
takerAsSellerProtocolMap.get(tradeId).onDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
takerAsSellerProtocolMap.get(tradeId).handleDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
}
else if (tradeMessage instanceof BankTransferInitedMessage) {
// Here happened a null pointer. I assume the only possible reason was that we got a null for the
@ -513,10 +513,10 @@ public class TradeManager {
// For getting better info we add a check. tradeId is checked above.
if (takerAsSellerProtocolMap.get(tradeId) == null)
log.error("takerAsSellerProtocolMap.get(tradeId) = null. That must not happen.");
takerAsSellerProtocolMap.get(tradeId).onBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
takerAsSellerProtocolMap.get(tradeId).handleBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
}
else if (tradeMessage instanceof PayoutTxPublishedMessage) {
offererAsBuyerProtocolMap.get(tradeId).onPayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
offererAsBuyerProtocolMap.get(tradeId).handlePayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
}
else {
log.error("Incoming tradeMessage not supported. " + tradeMessage);

View File

@ -15,9 +15,10 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.offerer;
package io.bitsquare.trade.listeners;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol;
import org.bitcoinj.core.Transaction;
@ -31,8 +32,4 @@ public interface BuyerAcceptsOfferProtocolListener {
void onPayoutTxPublished(Transaction payoutTx);
void onFault(Throwable throwable, BuyerAcceptsOfferProtocol.State state);
void onWaitingForPeerResponse(BuyerAcceptsOfferProtocol.State state);
void onWaitingForUserInteraction(BuyerAcceptsOfferProtocol.State state);
}

View File

@ -15,9 +15,10 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.taker;
package io.bitsquare.trade.listeners;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.taker.SellerTakesOfferProtocol;
import org.bitcoinj.core.Transaction;
@ -30,10 +31,8 @@ public interface SellerTakesOfferProtocolListener {
void onFault(Throwable throwable, SellerTakesOfferProtocol.State state);
void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state);
void onTakeOfferRequestAccepted();
void onTakeOfferRequestAccepted(Trade trade);
void onTakeOfferRequestRejected(Trade trade);
void onTakeOfferRequestRejected();
}

View File

@ -27,15 +27,15 @@ 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.HandleTakeOfferRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.RequestTakerDepositPayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.RespondToTakeOfferRequest;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendDepositTxIdToTaker;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendSignedPayoutTx;
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.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;
@ -72,25 +72,24 @@ public class BuyerAcceptsOfferProtocol {
public enum State {
Init,
HandleTakeOfferRequest,
RespondToTakeOfferRequest,
onTakeOfferFeePayedMessage,
VerifyTakeOfferFeePayment,
handleTakeOfferFeePayedMessage,
/* VerifyTakeOfferFeePayment,*/
CreateDepositTx,
RequestTakerDepositPayment,
onRequestOffererPublishDepositTxMessage,
handleRequestOffererPublishDepositTxMessage,
VerifyTakerAccount,
VerifyAndSignContract,
SignAndPublishDepositTx,
SendDepositTxIdToTaker,
SetupListenerForBlockChainConfirmation,
onResultSetupListenerForBlockChainConfirmation,
onUIEventBankTransferInited,
handleUIEventBankTransferInited,
SendSignedPayoutTx,
onPayoutTxPublishedMessage
handlePayoutTxPublishedMessage
}
// provided
@ -118,7 +117,7 @@ public class BuyerAcceptsOfferProtocol {
// data written by messages, read by tasks
private String takeOfferFeeTxId;
private String takerPubKey;
private String tradePubKeyAsHex;
private String peersPayoutAddress;
private String peersAccountId;
private BankAccount peersBankAccount;
@ -131,7 +130,7 @@ public class BuyerAcceptsOfferProtocol {
// state
private State state;
private int step = 0;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
@ -173,33 +172,28 @@ public class BuyerAcceptsOfferProtocol {
}
public void start() {
handleTakeOfferRequest();
respondToTakeOfferRequest();
}
// 1. HandleTakeOfferRequest
// Async
// In case of an error: Repeat once, then give up. No rollback activity needed
private void handleTakeOfferRequest() {
log.debug("handleTakeOfferRequest called " + step++);
state = State.HandleTakeOfferRequest;
HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onHandleTakeOfferRequestFault, peer, tradeMessageService, trade.getState(),
tradeId);
// 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 onHandleTakeOfferRequestFault(Throwable throwable) {
HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFault, peer, tradeMessageService, trade.getState(), tradeId);
}
private void handleRespondToTakeOfferRequestResult() {
log.debug("handleRespondToTakeOfferRequestResult called: state = " + state);
public void onResultHandleTakeOfferRequest(boolean takeOfferRequestAccepted) {
log.debug("onResultHandleTakeOfferRequest called " + step++);
if (takeOfferRequestAccepted) {
// 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);
listener.onWaitingForPeerResponse(state);
}
else {
// Don't use OFFERER_REJECTED as that trade might has been accepted to another taker.
log.info("Finish here as we have already the offer accepted.");
log.info("Ignore that request as we have already the offer accepted.");
}
}
@ -208,48 +202,48 @@ public class BuyerAcceptsOfferProtocol {
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
public void onTakeOfferFeePayedMessage(@NotNull TakeOfferFeePayedMessage message) {
log.debug("onTakeOfferFeePayedMessage called " + step++);
log.debug("state " + state);
// 8. handleTakeOfferFeePayedMessage
public void handleTakeOfferFeePayedMessage(@NotNull TakeOfferFeePayedMessage message) {
log.debug("handleTakeOfferFeePayedMessage called: state = " + state);
// validation
checkState(state == State.HandleTakeOfferRequest);
checkArgument(tradeId.equals(message.getTradeId()));
checkState(state == State.RespondToTakeOfferRequest);
checkTradeId(tradeId, message);
String takeOfferFeeTxId = nonEmptyStringOf(message.getTakeOfferFeeTxId());
Coin tradeAmount = positiveCoinOf(nonZeroCoinOf(message.getTradeAmount()));
String takerPubKey = nonEmptyStringOf(message.getTakerPubKey());
String tradePubKeyAsHex = nonEmptyStringOf(message.getTakerPubKeyAsHex());
// apply new state
state = State.onTakeOfferFeePayedMessage;
state = State.handleTakeOfferFeePayedMessage;
this.takeOfferFeeTxId = takeOfferFeeTxId;
this.takerPubKey = takerPubKey;
this.tradePubKeyAsHex = tradePubKeyAsHex;
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
trade.setTradeAmount(tradeAmount);
// next task
state = State.VerifyTakeOfferFeePayment;
VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFault, walletService,
this.takeOfferFeeTxId);
createDepositTx();
}
public void onResultVerifyTakeOfferFeePayment() {
log.debug("onResultVerifyTakeOfferFeePayment called " + step++);
// 9. CreateDepositTx
private void createDepositTx() {
log.debug("handleVerifyTakeOfferFeePaymentResult called: state = " + state);
checkState(state == State.handleTakeOfferFeePayedMessage);
Coin offererInputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE);
state = State.CreateDepositTx;
CreateDepositTx.run(this::onResultCreateDepositTx, this::onFault, walletService, tradeId, offererInputAmount,
takerPubKey, arbitratorPubKey);
CreateDepositTx.run(this::handleCreateDepositTxResult, this::handleFault, walletService, tradeId, offererInputAmount,
tradePubKeyAsHex, arbitratorPubKey);
}
public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex,
long offererTxOutIndex) {
log.debug("onResultCreateDepositTx called " + step++);
// 4. RequestTakerDepositPayment
private void handleCreateDepositTxResult(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex) {
log.debug("handleCreateDepositTxResult called: state = " + state);
checkState(state == State.CreateDepositTx);
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
this.offererTxOutIndex = offererTxOutIndex;
state = State.RequestTakerDepositPayment;
RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment,
this::onFault,
SendTakerDepositPaymentRequest.run(this::handleErrorMessage,
peer,
tradeMessageService,
tradeId,
@ -260,23 +254,19 @@ public class BuyerAcceptsOfferProtocol {
offererTxOutIndex);
}
public void onResultRequestTakerDepositPayment() {
log.debug("onResultRequestTakerDepositPayment called " + step++);
listener.onWaitingForPeerResponse(state);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message) {
log.debug("onRequestOffererPublishDepositTxMessage called " + step++);
// 5. VerifyTakerAccount
public void handleRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message) {
log.debug("handleRequestOffererPublishDepositTxMessage called: state = " + state);
log.debug("state " + state);
// validation
checkState(state == State.RequestTakerDepositPayment);
checkArgument(tradeId.equals(message.getTradeId()));
checkTradeId(tradeId, message);
String peersPayoutAddress = nonEmptyStringOf(message.getTakerPayoutAddress());
String peersAccountId = nonEmptyStringOf(message.getTakerAccountId());
BankAccount peersBankAccount = checkNotNull(message.getTakerBankAccount());
@ -288,7 +278,7 @@ public class BuyerAcceptsOfferProtocol {
long takerTxOutIndex = nonNegativeLongOf(message.getTakerTxOutIndex());
// apply new state
state = State.onRequestOffererPublishDepositTxMessage;
state = State.handleRequestOffererPublishDepositTxMessage;
this.peersPayoutAddress = peersPayoutAddress;
this.peersAccountId = peersAccountId;
this.peersBankAccount = peersBankAccount;
@ -301,17 +291,18 @@ public class BuyerAcceptsOfferProtocol {
// next task
state = State.VerifyTakerAccount;
VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFault, blockChainService,
VerifyTakerAccount.run(this::handleVerifyTakerAccountResult, this::handleFault, blockChainService,
this.peersAccountId, this.peersBankAccount);
}
public void onResultVerifyTakerAccount() {
log.debug("onResultVerifyTakerAccount called " + step++);
// 6. VerifyAndSignContract
private void handleVerifyTakerAccountResult() {
log.debug("handleVerifyTakerAccountResult called: state = " + state);
Coin tradeAmount = trade.getTradeAmount();
state = State.VerifyAndSignContract;
VerifyAndSignContract.run(this::onResultVerifyAndSignContract,
this::onFault,
VerifyAndSignContract.run(this::handleVerifyAndSignContractResult,
this::handleFault,
signatureService,
accountId,
tradeAmount,
@ -326,15 +317,16 @@ public class BuyerAcceptsOfferProtocol {
accountKey);
}
public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature) {
log.debug("onResultVerifyAndSignContract called " + step++);
// 7. SignAndPublishDepositTx
private void handleVerifyAndSignContractResult(Contract contract, String contractAsJson, String signature) {
log.debug("handleVerifyAndSignContractResult called: state = " + state);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setContractTakerSignature(signature);
trade.setTakerContractSignature(signature);
state = State.SignAndPublishDepositTx;
SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx,
this::onFault,
SignAndPublishDepositTx.run(this::handleSignAndPublishDepositTxResult,
this::handleFault,
walletService,
preparedOffererDepositTxAsHex,
signedTakerDepositTxAsHex,
@ -344,54 +336,64 @@ public class BuyerAcceptsOfferProtocol {
takerTxOutIndex);
}
public void onResultSignAndPublishDepositTx(Transaction depositTransaction) {
log.debug("onResultSignAndPublishDepositTx called " + step++);
// 8. SendDepositTxIdToTaker
private void handleSignAndPublishDepositTxResult(Transaction depositTransaction) {
log.debug("handleSignAndPublishDepositTxResult called: state = " + state);
listener.onDepositTxPublished(depositTransaction);
state = State.SendDepositTxIdToTaker;
SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFault, peer, tradeMessageService,
SendDepositTxIdToTaker.run(this::handleSendDepositTxIdToTakerResult, this::handleErrorMessage, peer, tradeMessageService,
tradeId, depositTransaction);
}
public void onResultSendDepositTxIdToTaker() {
log.debug("onResultSendDepositTxIdToTaker called " + step++);
private void handleSendDepositTxIdToTakerResult() {
log.debug("handleSendDepositTxIdToTakerResult called: state = " + state);
state = State.SetupListenerForBlockChainConfirmation;
SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation,
trade.getDepositTx(), listener);
SetupListenerForBlockChainConfirmation.run(trade.getDepositTx(), listener);
}
public void onResultSetupListenerForBlockChainConfirmation() {
log.debug("onResultSetupListenerForBlockChainConfirmation called " + step++);
state = State.onResultSetupListenerForBlockChainConfirmation;
listener.onWaitingForUserInteraction(state);
/*
// 9. VerifyTakeOfferFeePayment
private void verifyTakeOfferFeePayment() {
state = State.VerifyTakeOfferFeePayment;
VerifyTakeOfferFeePayment.run(this::handleVerifyTakeOfferFeePaymentResult, this::handleFault, walletService, this.takeOfferFeeTxId);
}
// 10. CreateDepositTx
private void handleVerifyTakeOfferFeePaymentResult() {
log.debug("handleVerifyTakeOfferFeePaymentResult called: state = " + state);
checkState(state == State.VerifyTakeOfferFeePayment);
Coin offererInputAmount = trade.getSecurityDeposit().add(FeePolicy.TX_FEE);
state = State.CreateDepositTx;
CreateDepositTx.run(this::handleCreateDepositTxResult, this::handleFault, walletService, tradeId, offererInputAmount,
tradePubKeyAsHex, arbitratorPubKey);
}
*/
///////////////////////////////////////////////////////////////////////////////////////////
// Triggered UI event
///////////////////////////////////////////////////////////////////////////////////////////
// Triggered from UI event: Button click "Bank transfer inited"
public void onUIEventBankTransferInited() {
log.debug("onUIEventBankTransferInited called " + step++);
// 9. SendSignedPayoutTx
public void handleUIEventBankTransferInited() {
log.debug("onUIEventBankTransferInited called: state = " + state);
log.debug("state " + state);
// validation
checkState(state.ordinal() >= State.SignAndPublishDepositTx.ordinal() &&
state.ordinal() <= State.onResultSetupListenerForBlockChainConfirmation.ordinal());
state.ordinal() <= State.SetupListenerForBlockChainConfirmation.ordinal());
state = State.onUIEventBankTransferInited;
state = State.handleUIEventBankTransferInited;
// next task
String depositTransactionId = trade.getDepositTx().getHashAsString();
Coin tradeAmount = trade.getTradeAmount();
Coin securityDeposit = trade.getSecurityDeposit();
state = State.SendSignedPayoutTx;
SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx,
this::onFault,
SendSignedPayoutTx.run(this::handleFault,
peer,
tradeMessageService,
walletService,
@ -403,50 +405,40 @@ public class BuyerAcceptsOfferProtocol {
tradeAmount);
}
public void onResultSendSignedPayoutTx() {
log.debug("onResultSendSignedPayoutTx called " + step++);
listener.onWaitingForPeerResponse(state);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage message) {
log.debug("onPayoutTxPublishedMessage called " + step++);
log.debug("state " + state);
// 10. handlePayoutTxPublishedMessage
public void handlePayoutTxPublishedMessage(PayoutTxPublishedMessage message) {
log.debug("onPayoutTxPublishedMessage called: state = " + state);
// validation
checkState(state == State.SendSignedPayoutTx);
checkArgument(tradeId.equals(message.getTradeId()));
checkTradeId(tradeId, message);
String payoutTxAsHex = nonEmptyStringOf(message.getPayoutTxAsHex());
state = State.onPayoutTxPublishedMessage;
Transaction payoutTx = new Transaction(walletService.getWallet().getParams(),
Utils.parseAsHexOrBase58(payoutTxAsHex));
// apply new state
state = State.handlePayoutTxPublishedMessage;
Transaction payoutTx = new Transaction(walletService.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
listener.onPayoutTxPublished(payoutTx);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters, Setters
///////////////////////////////////////////////////////////////////////////////////////////
public String getId() {
return tradeId;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
// generic fault handler
private void onFault(Throwable throwable) {
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));
}
}

View File

@ -21,12 +21,14 @@ import io.bitsquare.trade.protocol.trade.TradeMessage;
import java.io.Serializable;
import org.jetbrains.annotations.NotNull;
public class RespondToTakeOfferRequestMessage implements Serializable, TradeMessage {
private static final long serialVersionUID = 6177387534087739018L;
private final String tradeId;
private final boolean takeOfferRequestAccepted;
public RespondToTakeOfferRequestMessage(String tradeId, boolean takeOfferRequestAccepted) {
public RespondToTakeOfferRequestMessage(@NotNull String tradeId, boolean takeOfferRequestAccepted) {
this.tradeId = tradeId;
this.takeOfferRequestAccepted = takeOfferRequestAccepted;
}

View File

@ -22,7 +22,7 @@ import io.bitsquare.trade.protocol.trade.TradeMessage;
import java.io.Serializable;
public class RequestTakerDepositPaymentMessage implements Serializable, TradeMessage {
public class TakerDepositPaymentRequestMessage implements Serializable, TradeMessage {
private static final long serialVersionUID = -3988720410493712913L;
private final String tradeId;
@ -32,7 +32,7 @@ public class RequestTakerDepositPaymentMessage implements Serializable, TradeMes
private final String preparedOffererDepositTxAsHex;
private final long offererTxOutIndex;
public RequestTakerDepositPaymentMessage(String tradeId, BankAccount bankAccount, String accountID,
public TakerDepositPaymentRequestMessage(String tradeId, BankAccount bankAccount, String accountID,
String offererPubKey, String preparedOffererDepositTxAsHex,
long offererTxOutIndex) {
this.tradeId = tradeId;

View File

@ -38,20 +38,19 @@ public class CreateDepositTx {
Coin offererInputAmount,
String takerMultiSigPubKey,
String arbitratorPubKeyAsHex) {
log.trace("Run task");
log.trace("Run CreateDepositTx task");
try {
String offererPubKey = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
Transaction transaction = walletService.offererCreatesMSTxAndAddPayment(
offererInputAmount, offererPubKey, takerMultiSigPubKey, arbitratorPubKeyAsHex, tradeId);
Transaction transaction = walletService.offererCreatesMSTxAndAddPayment(offererInputAmount, offererPubKey, takerMultiSigPubKey,
arbitratorPubKeyAsHex, tradeId);
String preparedOffererDepositTxAsHex = Utils.HEX.encode(transaction.bitcoinSerialize());
long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex();
resultHandler.onResult(offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
} catch (InsufficientMoneyException e) {
log.error("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e);
exceptionHandler.handleException(
new Exception("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e));
log.error("Create deposit tx failed due InsufficientMoneyException " + e);
exceptionHandler.handleException(e);
}
}

View File

@ -22,38 +22,38 @@ import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HandleTakeOfferRequest {
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
public class RespondToTakeOfferRequest {
private static final Logger log = LoggerFactory.getLogger(RespondToTakeOfferRequest.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, Peer peer,
TradeMessageService tradeMessageService, Trade.State tradeState, String tradeId) {
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler,
TradeMessageService tradeMessageService, Peer peer, Trade.State tradeState, String tradeId) {
log.trace("Run HandleTakeOfferRequest task");
boolean isTradeIsOpen = tradeState == Trade.State.OPEN;
if (!isTradeIsOpen) {
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, isTradeIsOpen);
RespondToTakeOfferRequestMessage tradeMessage = new RespondToTakeOfferRequestMessage(tradeId, takeOfferRequestAccepted);
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() {
@Override
public void handleResult() {
log.trace("RespondToTakeOfferRequestMessage successfully arrived at peer");
resultHandler.handleResult(isTradeIsOpen);
resultHandler.handleResult();
}
@Override
public void handleFault() {
log.error("AcceptTakeOfferRequestMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("AcceptTakeOfferRequestMessage did not arrive at peer"));
errorMessageHandler.handleErrorMessage("AcceptTakeOfferRequestMessage did not arrive at peer");
}
});
}
public interface ResultHandler {
void handleResult(boolean takeOfferRequestAccepted);
void handleResult();
}
}

View File

@ -17,11 +17,11 @@
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.network.Peer;
import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import io.bitsquare.util.handlers.ResultHandler;
import org.bitcoinj.core.Transaction;
@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
public class SendDepositTxIdToTaker {
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, Peer peer,
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, Peer peer,
TradeMessageService tradeMessageService, String tradeId, Transaction depositTransaction) {
log.trace("Run task");
DepositTxPublishedMessage tradeMessage =
@ -49,7 +49,7 @@ public class SendDepositTxIdToTaker {
@Override
public void handleFault() {
log.error("DepositTxPublishedMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("DepositTxPublishedMessage did not arrive at peer"));
errorMessageHandler.handleErrorMessage("DepositTxPublishedMessage did not arrive at peer");
}
});
}

View File

@ -18,12 +18,11 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.WalletService;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ResultHandler;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.ECKey;
@ -36,8 +35,7 @@ import org.slf4j.LoggerFactory;
public class SendSignedPayoutTx {
private static final Logger log = LoggerFactory.getLogger(SendSignedPayoutTx.class);
public static void run(ResultHandler resultHandler,
ExceptionHandler exceptionHandler,
public static void run(ExceptionHandler exceptionHandler,
Peer peer,
TradeMessageService tradeMessageService,
WalletService walletService,
@ -72,7 +70,6 @@ public class SendSignedPayoutTx {
@Override
public void handleResult() {
log.trace("BankTransferInitedMessage successfully arrived at peer");
resultHandler.handleResult();
}
@Override

View File

@ -18,21 +18,19 @@
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.network.Peer;
import io.bitsquare.trade.protocol.trade.offerer.messages.RequestTakerDepositPaymentMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RequestTakerDepositPayment {
private static final Logger log = LoggerFactory.getLogger(RequestTakerDepositPayment.class);
public class SendTakerDepositPaymentRequest {
private static final Logger log = LoggerFactory.getLogger(SendTakerDepositPaymentRequest.class);
public static void run(ResultHandler resultHandler,
ExceptionHandler exceptionHandler,
public static void run(ErrorMessageHandler errorMessageHandler,
Peer peer,
TradeMessageService tradeMessageService,
String tradeId,
@ -41,21 +39,19 @@ public class RequestTakerDepositPayment {
String offererPubKey,
String preparedOffererDepositTxAsHex,
long offererTxOutIndex) {
log.trace("Run task");
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(
log.trace("Run SendTakerDepositPaymentRequest task");
TakerDepositPaymentRequestMessage tradeMessage = new TakerDepositPaymentRequestMessage(
tradeId, bankAccount, accountId, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
tradeMessageService.sendMessage(peer, tradeMessage, new SendMessageListener() {
@Override
public void handleResult() {
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
resultHandler.handleResult();
}
@Override
public void handleFault() {
log.error("RequestTakerDepositPaymentMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("RequestTakerDepositPaymentMessage did not arrive at " +
"peer"));
errorMessageHandler.handleErrorMessage("RequestTakerDepositPaymentMessage did not arrive at peer");
}
});
}

View File

@ -17,8 +17,7 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocolListener;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.trade.listeners.BuyerAcceptsOfferProtocolListener;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
@ -29,9 +28,8 @@ import org.slf4j.LoggerFactory;
public class SetupListenerForBlockChainConfirmation {
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
public static void run(ResultHandler resultHandler,
Transaction depositTransaction, BuyerAcceptsOfferProtocolListener listener) {
log.trace("Run task");
public static void run(Transaction depositTransaction, BuyerAcceptsOfferProtocolListener listener) {
log.trace("Run SetupListenerForBlockChainConfirmation task");
//TODO
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
@ -44,7 +42,6 @@ public class SetupListenerForBlockChainConfirmation {
listener.onDepositTxConfirmedInBlockchain();
depositTransaction.getConfidence().removeEventListener(this);
log.trace("Tx is in blockchain");
resultHandler.handleResult();
}
}
});

View File

@ -29,7 +29,7 @@ public class VerifyTakeOfferFeePayment {
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService,
String takeOfferFeeTxId) {
log.trace("Run task");
log.trace("Run VerifyTakeOfferFeePayment task");
//TODO mocked yet, need a confidence listeners
int numOfPeersSeenTx = walletService.getNumOfPeersSeenTx(takeOfferFeeTxId);
if (numOfPeersSeenTx > 2) {

View File

@ -26,10 +26,11 @@ import io.bitsquare.offer.Offer;
import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SellerTakesOfferProtocolListener;
import io.bitsquare.trade.protocol.trade.offerer.messages.BankTransferInitedMessage;
import io.bitsquare.trade.protocol.trade.offerer.messages.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.offerer.messages.RequestTakerDepositPaymentMessage;
import io.bitsquare.trade.protocol.trade.offerer.messages.RespondToTakeOfferRequestMessage;
import io.bitsquare.trade.protocol.trade.offerer.messages.TakerDepositPaymentRequestMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.CreateAndSignContract;
import io.bitsquare.trade.protocol.trade.taker.tasks.GetPeerAddress;
import io.bitsquare.trade.protocol.trade.taker.tasks.PayDeposit;
@ -37,8 +38,9 @@ import io.bitsquare.trade.protocol.trade.taker.tasks.PayTakeOfferFee;
import io.bitsquare.trade.protocol.trade.taker.tasks.RequestTakeOffer;
import io.bitsquare.trade.protocol.trade.taker.tasks.SendPayoutTxToOfferer;
import io.bitsquare.trade.protocol.trade.taker.tasks.SendSignedTakerDepositTxAsHex;
import io.bitsquare.trade.protocol.trade.taker.tasks.SendTakeOfferFeePayedTxId;
import io.bitsquare.trade.protocol.trade.taker.tasks.SendTakeOfferFeePayedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.SignAndPublishPayoutTx;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCommitDepositTx;
import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOffererAccount;
import io.bitsquare.user.User;
@ -54,6 +56,7 @@ 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.
@ -69,16 +72,20 @@ public class SellerTakesOfferProtocol {
Init,
GetPeerAddress,
RequestTakeOffer,
handleRespondToTakeOfferRequestMessage,
PayTakeOfferFee,
SendTakeOfferFeePayedMessage,
onRequestTakerDepositPaymentMessage,
SendTakeOfferFeePayedTxId,
handleTakerDepositPaymentRequestMessage,
VerifyOffererAccount,
CreateAndSignContract,
PayDeposit,
SendSignedTakerDepositTxAsHex,
onBankTransferInitedMessage,
handleDepositTxPublishedMessage,
TakerCommitDepositTx,
handleBankTransferInitedMessage,
SignAndPublishPayoutTx,
SendPayoutTxToOfferer
}
@ -98,7 +105,7 @@ public class SellerTakesOfferProtocol {
private final String accountId;
private final PublicKey messagePublicKey;
private final Coin tradeAmount;
private final String pubKeyForThatTrade;
private final String tradePubKeyAsHex;
private final ECKey accountKey;
private final PublicKey offererMessagePublicKey;
private final Coin securityDeposit;
@ -120,12 +127,9 @@ public class SellerTakesOfferProtocol {
private Coin offererPaybackAmount;
private Coin takerPaybackAmount;
private String offererPayoutAddress;
private int repeatCounter = 0;
// state
private State state;
private int step = 0;
///////////////////////////////////////////////////////////////////////////////////////////
@ -159,7 +163,7 @@ public class SellerTakesOfferProtocol {
accountId = user.getAccountId();
messagePublicKey = user.getMessagePublicKey();
pubKeyForThatTrade = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
tradePubKeyAsHex = walletService.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
accountKey = walletService.getRegistrationAddressEntry().getKey();
state = State.Init;
@ -170,38 +174,18 @@ public class SellerTakesOfferProtocol {
}
// 1. GetPeerAddress
// Async
// In case of an error: Repeat once, then give up. No rollback activity needed
private void getPeerAddress() {
log.debug("getPeerAddress called " + step++);
log.debug("getPeerAddress called: state = " + state);
state = State.GetPeerAddress;
GetPeerAddress.run(this::onResultGetPeerAddress, this::onGetPeerAddressFault, tradeMessageService, offererMessagePublicKey);
}
private void onGetPeerAddressFault(String errorMessage) {
log.debug("Run getPeerAddress again after onGetPeerAddressFault" + step);
GetPeerAddress.run(this::onResultGetPeerAddress, this::onErrorMessage, tradeMessageService, offererMessagePublicKey);
GetPeerAddress.run(this::handleGetPeerAddressResult, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey);
}
// 2. RequestTakeOffer
// Async
// In case of an error: Repeat once, then give up. No rollback activity needed
public void onResultGetPeerAddress(Peer peer) {
log.debug("onResultGetPeerAddress called " + step++);
private void handleGetPeerAddressResult(Peer peer) {
log.debug("handleGetPeerAddressResult called: state = " + state);
this.peer = peer;
state = State.RequestTakeOffer;
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onRequestTakeOfferFault, peer, tradeMessageService, tradeId);
}
private void onRequestTakeOfferFault(Throwable throwable) {
log.debug("Run getPeerAddress again after onGetPeerAddressFault" + step);
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, peer, tradeMessageService, tradeId);
}
public void onResultRequestTakeOffer() {
log.debug("onResultRequestTakeOffer called " + step++);
listener.onWaitingForPeerResponse(state);
RequestTakeOffer.run(this::handleErrorMessage, tradeMessageService, peer, tradeId);
}
@ -209,52 +193,57 @@ public class SellerTakesOfferProtocol {
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// 3. PayTakeOfferFee
// Async
// In case of an error: Repeat once, then give up. No rollback activity needed
public void onRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message) {
log.debug("onRespondToTakeOfferRequestMessage called " + step++);
log.debug("state " + state);
checkState(state == State.RequestTakeOffer);
checkArgument(tradeId.equals(message.getTradeId()));
if (message.isTakeOfferRequestAccepted()) {
state = State.PayTakeOfferFee;
listener.onTakeOfferRequestAccepted(trade);
PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletService, tradeId);
}
else {
listener.onTakeOfferRequestRejected(trade);
// exit case
}
}
public void onResultPayTakeOfferFee(String takeOfferFeeTxId) {
log.debug("onResultPayTakeOfferFee called " + step++);
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
state = State.SendTakeOfferFeePayedTxId;
SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId, this::onFault, peer,
tradeMessageService, tradeId, takeOfferFeeTxId, tradeAmount, pubKeyForThatTrade);
}
public void onResultSendTakeOfferFeePayedTxId() {
log.debug("onResultSendTakeOfferFeePayedTxId called " + step++);
listener.onWaitingForPeerResponse(state);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message) {
log.debug("onRequestTakerDepositPaymentMessage called " + step++);
log.debug("state " + state);
// 5. handleRespondToTakeOfferRequestMessage
public void handleRespondToTakeOfferRequestMessage(RespondToTakeOfferRequestMessage message) {
log.debug("handleRespondToTakeOfferRequestMessage called: state = " + state);
// validation
checkState(state == State.SendTakeOfferFeePayedTxId);
checkArgument(tradeId.equals(message.getTradeId()));
checkState(state == State.RequestTakeOffer);
checkTradeId(tradeId, message);
// apply new state
state = State.handleRespondToTakeOfferRequestMessage;
if (message.isTakeOfferRequestAccepted()) {
trade.setState(Trade.State.OFFERER_ACCEPTED);
listener.onTakeOfferRequestAccepted();
// next task
payTakeOfferFee();
}
else {
// exit case
trade.setState(Trade.State.OFFERER_REJECTED);
listener.onTakeOfferRequestRejected();
}
}
// 6. PayTakeOfferFee
private void payTakeOfferFee() {
state = State.PayTakeOfferFee;
PayTakeOfferFee.run(this::handlePayTakeOfferFeeResult, this::handleFault, walletService, tradeId);
}
// 7. SendTakeOfferFeePayedMessage
private void handlePayTakeOfferFeeResult(String takeOfferFeeTxId) {
log.debug("handlePayTakeOfferFeeResult called: state = " + state);
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
state = State.SendTakeOfferFeePayedMessage;
SendTakeOfferFeePayedMessage.run(this::handleErrorMessage, peer,
tradeMessageService, tradeId, takeOfferFeeTxId, tradeAmount, tradePubKeyAsHex);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// 5. VerifyOffererAccount
public void handleTakerDepositPaymentRequestMessage(TakerDepositPaymentRequestMessage message) {
log.debug("handleTakerDepositPaymentRequestMessage called: state = " + state);
// validation
checkState(state == State.SendTakeOfferFeePayedMessage);
checkTradeId(tradeId, message);
String peersAccountId = nonEmptyStringOf(message.getAccountId());
BankAccount peersBankAccount = checkNotNull(message.getBankAccount());
String offererPubKey = nonEmptyStringOf(message.getOffererPubKey());
@ -262,7 +251,7 @@ public class SellerTakesOfferProtocol {
long offererTxOutIndex = nonNegativeLongOf(message.getOffererTxOutIndex());
// apply new state
state = State.onRequestTakerDepositPaymentMessage;
state = State.handleTakerDepositPaymentRequestMessage;
this.peersAccountId = peersAccountId;
this.peersBankAccount = peersBankAccount;
this.peersPubKey = offererPubKey;
@ -271,16 +260,17 @@ public class SellerTakesOfferProtocol {
// next task
state = State.VerifyOffererAccount;
VerifyOffererAccount.run(this::onResultVerifyOffererAccount, this::onFault, blockChainService, peersAccountId,
peersBankAccount);
VerifyOffererAccount.run(this::handleVerifyOffererAccountResult, this::handleFault, blockChainService, peersAccountId, peersBankAccount);
}
public void onResultVerifyOffererAccount() {
log.debug("onResultVerifyOffererAccount called " + step++);
// 6. CreateAndSignContract
private void handleVerifyOffererAccountResult() {
log.debug("handleVerifyOffererAccountResult called: state = " + state);
checkState(state == State.VerifyOffererAccount);
String takeOfferFeeTxId = trade.getTakeOfferFeeTxId();
state = State.CreateAndSignContract;
CreateAndSignContract.run(this::onResultCreateAndSignContract,
this::onFault,
CreateAndSignContract.run(this::handleCreateAndSignContractResult,
this::handleFault,
signatureService,
offer,
tradeAmount,
@ -294,26 +284,26 @@ public class SellerTakesOfferProtocol {
accountKey);
}
public void onResultCreateAndSignContract(Contract contract, String contractAsJson, String signature) {
log.debug("onResultCreateAndSignContract called " + step++);
// 7. PayDeposit
private void handleCreateAndSignContractResult(Contract contract, String contractAsJson, String signature) {
log.debug("handleCreateAndSignContractResult called: state = " + state);
checkState(state == State.CreateAndSignContract);
trade.setContract(contract);
trade.setContractAsJson(contractAsJson);
trade.setContractTakerSignature(signature);
trade.setTakerContractSignature(signature);
state = State.PayDeposit;
PayDeposit.run(this::onResultPayDeposit, this::onFault, walletService, securityDeposit, tradeAmount, tradeId,
pubKeyForThatTrade, arbitratorPubKey, peersPubKey, preparedPeersDepositTxAsHex);
PayDeposit.run(this::handlePayDepositResult, this::handleFault, walletService, securityDeposit, tradeAmount, tradeId,
tradePubKeyAsHex, arbitratorPubKey, peersPubKey, preparedPeersDepositTxAsHex);
}
public void onResultPayDeposit(Transaction signedTakerDepositTx) {
log.debug("onResultPayDeposit called " + step++);
// 8. SendSignedTakerDepositTxAsHex
private void handlePayDepositResult(Transaction signedTakerDepositTx) {
log.debug("handlePayDepositResult called: state = " + state);
checkState(state == State.PayDeposit);
String contractAsJson = trade.getContractAsJson();
String takerSignature = trade.getTakerSignature();
String takerContractSignature = trade.getTakerContractSignature();
state = State.SendSignedTakerDepositTxAsHex;
SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex,
this::onFault,
SendSignedTakerDepositTxAsHex.run(this::handleErrorMessage,
peer,
tradeMessageService,
walletService,
@ -322,30 +312,39 @@ public class SellerTakesOfferProtocol {
messagePublicKey,
tradeId,
contractAsJson,
takerSignature,
takerContractSignature,
signedTakerDepositTx,
peersTxOutIndex);
}
public void onResultSendSignedTakerDepositTxAsHex() {
log.debug("onResultSendSignedTakerDepositTxAsHex called " + step++);
listener.onWaitingForPeerResponse(state);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// informational, does only trigger UI feedback/update
public void onDepositTxPublishedMessage(DepositTxPublishedMessage message) {
log.debug("onDepositTxPublishedMessage called " + step++);
// 9.a TakerCommitDepositTx
public void handleDepositTxPublishedMessage(DepositTxPublishedMessage message) {
log.debug("onDepositTxPublishedMessage called: state = " + state);
log.debug("state " + state);
// validation
checkState(state.ordinal() >= State.SendSignedTakerDepositTxAsHex.ordinal());
checkArgument(tradeId.equals(message.getTradeId()));
//TODO takerCommitDepositTx should be in task as well
Transaction tx = walletService.takerCommitDepositTx(message.getDepositTxAsHex());
listener.onDepositTxPublished(tx);
checkTradeId(tradeId, message);
nonEmptyStringOf(message.getDepositTxAsHex());
// apply new state
state = State.handleDepositTxPublishedMessage;
String depositTxAsHex = message.getDepositTxAsHex();
// next task
state = State.TakerCommitDepositTx;
TakerCommitDepositTx.run(this::handleTakerCommitDepositTxResult, this::handleFault, walletService, depositTxAsHex);
}
private void handleTakerCommitDepositTxResult(Transaction transaction) {
log.debug("handleTakerCommitDepositTxResult called: state = " + state);
listener.onDepositTxPublished(transaction);
}
@ -353,14 +352,15 @@ public class SellerTakesOfferProtocol {
// Incoming message from peer
///////////////////////////////////////////////////////////////////////////////////////////
// informational, store data for later, does only trigger UI feedback/update
public void onBankTransferInitedMessage(BankTransferInitedMessage message) {
log.debug("onBankTransferInitedMessage called " + step++);
// 9.b. handleBankTransferInitedMessage
public void handleBankTransferInitedMessage(BankTransferInitedMessage message) {
log.debug("onBankTransferInitedMessage called: state = " + state);
log.debug("state " + state);
// validate
checkState(state.ordinal() >= State.SendSignedTakerDepositTxAsHex.ordinal() &&
state.ordinal() < State.SignAndPublishPayoutTx.ordinal());
checkArgument(tradeId.equals(message.getTradeId()));
checkTradeId(tradeId, message);
String depositTxAsHex = nonEmptyStringOf(message.getDepositTxAsHex());
String offererSignatureR = nonEmptyStringOf(message.getOffererSignatureR());
String offererSignatureS = nonEmptyStringOf(message.getOffererSignatureS());
@ -369,7 +369,7 @@ public class SellerTakesOfferProtocol {
String offererPayoutAddress = nonEmptyStringOf(message.getOffererPayoutAddress());
// apply state
state = State.onBankTransferInitedMessage;
state = State.handleBankTransferInitedMessage;
this.depositTxAsHex = depositTxAsHex;
this.offererSignatureR = offererSignatureR;
this.offererSignatureS = offererSignatureS;
@ -386,14 +386,15 @@ public class SellerTakesOfferProtocol {
///////////////////////////////////////////////////////////////////////////////////////////
// User clicked the "bank transfer received" button, so we release the funds for pay out
public void onUIEventFiatReceived() {
log.debug("onUIEventFiatReceived called " + step++);
// 10. SignAndPublishPayoutTx
public void handleUIEventFiatReceived() {
log.debug("onUIEventFiatReceived called: state = " + state);
log.debug("state " + state);
checkState(state == State.onBankTransferInitedMessage);
checkState(state == State.handleBankTransferInitedMessage || state == State.TakerCommitDepositTx);
state = State.SignAndPublishPayoutTx;
SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx,
this::onFault,
SignAndPublishPayoutTx.run(this::handleSignAndPublishPayoutTxResult,
this::handleFault,
walletService,
tradeId,
depositTxAsHex,
@ -404,26 +405,17 @@ public class SellerTakesOfferProtocol {
offererPayoutAddress);
}
public void onResultSignAndPublishPayoutTx(Transaction transaction, String payoutTxAsHex) {
log.debug("onResultSignAndPublishPayoutTx called " + step++);
// 11. SendPayoutTxToOfferer
private void handleSignAndPublishPayoutTxResult(Transaction transaction, String payoutTxAsHex) {
log.debug("handleSignAndPublishPayoutTxResult called: state = " + state);
listener.onPayoutTxPublished(trade, transaction);
state = State.SendPayoutTxToOfferer;
SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peer, tradeMessageService,
SendPayoutTxToOfferer.run(this::handleSendPayoutTxToOffererResult, this::handleErrorMessage, peer, tradeMessageService,
tradeId, payoutTxAsHex);
}
public void onResultSendPayoutTxToOfferer() {
log.debug("onResultSendPayoutTxToOfferer called " + step++);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters, Setters
///////////////////////////////////////////////////////////////////////////////////////////
public String getId() {
return tradeId;
private void handleSendPayoutTxToOffererResult() {
log.debug("onResultSendPayoutTxToOfferer called: state = " + state);
}
@ -432,12 +424,14 @@ public class SellerTakesOfferProtocol {
///////////////////////////////////////////////////////////////////////////////////////////
// generic fault handler
private void onFault(Throwable throwable) {
private void handleFault(Throwable throwable) {
trade.setFault(throwable);
trade.setState(Trade.State.FAILED);
listener.onFault(throwable, state);
}
private void onErrorMessage(String errorMessage) {
listener.onFault(new Exception(errorMessage), state);
private void handleErrorMessage(String errorMessage) {
handleFault(new Exception(errorMessage));
}
}

View File

@ -29,13 +29,13 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage {
private final Coin tradeAmount;
private final String takeOfferFeeTxID;
private final String takerPubKey;
private final String tradePubKeyAsHex;
public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, Coin tradeAmount, String takerPubKey) {
public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, Coin tradeAmount, String tradePubKeyAsHex) {
this.tradeId = tradeId;
this.takeOfferFeeTxID = takeOfferFeeTxID;
this.tradeAmount = tradeAmount;
this.takerPubKey = takerPubKey;
this.tradePubKeyAsHex = tradePubKeyAsHex;
}
@Override
@ -51,8 +51,8 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage {
return takeOfferFeeTxID;
}
public String getTakerPubKey() {
return takerPubKey;
public String getTakerPubKeyAsHex() {
return tradePubKeyAsHex;
}
}

View File

@ -48,7 +48,7 @@ public class CreateAndSignContract {
String peersAccountId,
BankAccount peersBankAccount,
ECKey registrationKey) {
log.trace("Run task");
log.trace("Run CreateAndSignContract task");
try {
Contract contract = new Contract(offer, tradeAmount, takeOfferFeeTxId, peersAccountId, accountId,
peersBankAccount, bankAccount, peersMessagePublicKey, messagePublicKey);

View File

@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory;
public class GetPeerAddress {
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler,
TradeMessageService tradeMessageService, PublicKey messagePublicKey) {
log.trace("Run GetPeerAddress task");
@ -42,8 +42,8 @@ public class GetPeerAddress {
@Override
public void onFailed() {
log.error("Lookup for peer address failed.");
errorMessageHandler.handleErrorMessage("Lookup for peer address failed.");
log.error("DHT lookup for peer address failed.");
errorMessageHandler.handleErrorMessage("DHT lookup for peer address failed.");
}
});
}

View File

@ -40,7 +40,7 @@ public class PayDeposit {
String arbitratorPubKey,
String offererPubKey,
String preparedOffererDepositTxAsHex) {
log.trace("Run task");
log.trace("Run PayDeposit task");
try {
Coin amountToPay = tradeAmount.add(securityDeposit);
Coin msOutputAmount = amountToPay.add(securityDeposit);
@ -53,18 +53,15 @@ public class PayDeposit {
preparedOffererDepositTxAsHex,
tradeId);
log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx);
log.trace("signedTakerDepositTx: " + signedTakerDepositTx);
resultHandler.onResult(signedTakerDepositTx);
} catch (InsufficientMoneyException e) {
log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e);
exceptionHandler.handleException(
new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e));
log.error("Pay deposit failed due InsufficientMoneyException " + e);
exceptionHandler.handleException(e);
}
}
public interface ResultHandler {
void onResult(Transaction signedTakerDepositTx);
}
}

View File

@ -35,7 +35,7 @@ public class PayTakeOfferFee {
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService,
String tradeId) {
log.trace("Run task");
log.trace("Run PayTakeOfferFee task");
try {
walletService.payTakeOfferFee(tradeId, new FutureCallback<Transaction>() {
@Override
@ -46,15 +46,13 @@ public class PayTakeOfferFee {
@Override
public void onFailure(@NotNull Throwable t) {
log.error("Take offer fee paid faultHandler.onFault with exception: " + t);
exceptionHandler.handleException(
new Exception("Take offer fee paid faultHandler.onFault with exception: " + t));
log.error("Pay take offer fee caused an exception: " + t);
exceptionHandler.handleException(t);
}
});
} catch (InsufficientMoneyException e) {
log.error("Take offer fee paid faultHandler.onFault due InsufficientMoneyException " + e);
exceptionHandler.handleException(
new Exception("Take offer fee paid faultHandler.onFault due to InsufficientMoneyException " + e));
log.error("Pay take offer fee caused an exception: " + e);
exceptionHandler.handleException(e);
}
}

View File

@ -17,12 +17,11 @@
package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -30,21 +29,20 @@ import org.slf4j.LoggerFactory;
public class RequestTakeOffer {
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, Peer peer,
TradeMessageService tradeMessageService, String tradeId) {
public static void run(ErrorMessageHandler errorMessageHandler,
TradeMessageService tradeMessageService, Peer peer, String tradeId) {
log.trace("Run RequestTakeOffer task");
tradeMessageService.sendMessage(peer, new RequestTakeOfferMessage(tradeId),
new SendMessageListener() {
@Override
public void handleResult() {
log.trace("RequestTakeOfferMessage successfully arrived at peer");
resultHandler.handleResult();
log.trace("Sending RequestTakeOfferMessage succeeded.");
}
@Override
public void handleFault() {
log.error("RequestTakeOfferMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("RequestTakeOfferMessage did not arrive at peer"));
log.error("Sending RequestTakeOfferMessage failed.");
errorMessageHandler.handleErrorMessage("Sending RequestTakeOfferMessage failed.");
}
});
}

View File

@ -17,11 +17,11 @@
package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.taker.messages.PayoutTxPublishedMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import io.bitsquare.util.handlers.ResultHandler;
import org.slf4j.Logger;
@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
public class SendPayoutTxToOfferer {
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, Peer peer,
public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, Peer peer,
TradeMessageService tradeMessageService, String tradeId, String payoutTxAsHex) {
log.trace("Run task");
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(tradeId, payoutTxAsHex);
@ -44,7 +44,7 @@ public class SendPayoutTxToOfferer {
@Override
public void handleFault() {
log.error("PayoutTxPublishedMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("PayoutTxPublishedMessage did not arrive at peer"));
errorMessageHandler.handleErrorMessage("PayoutTxPublishedMessage did not arrive at peer");
}
});

View File

@ -19,12 +19,11 @@ package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.btc.WalletService;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestOffererPublishDepositTxMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Utils;
@ -37,8 +36,7 @@ import org.slf4j.LoggerFactory;
public class SendSignedTakerDepositTxAsHex {
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
public static void run(ResultHandler resultHandler,
ExceptionHandler exceptionHandler,
public static void run(ErrorMessageHandler errorMessageHandler,
Peer peer,
TradeMessageService tradeMessageService,
WalletService walletService,
@ -47,10 +45,10 @@ public class SendSignedTakerDepositTxAsHex {
PublicKey messagePublicKey,
String tradeId,
String contractAsJson,
String takerSignature,
String takerContractSignature,
Transaction signedTakerDepositTx,
long offererTxOutIndex) {
log.trace("Run task");
log.trace("Run SendSignedTakerDepositTxAsHex task");
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(tradeId,
@ -64,7 +62,7 @@ public class SendSignedTakerDepositTxAsHex {
.getParentTransaction()
.bitcoinSerialize()),
contractAsJson,
takerSignature,
takerContractSignature,
walletService.getAddressInfoByTradeID(tradeId).getAddressString(),
takerTxOutIndex,
offererTxOutIndex);
@ -72,14 +70,12 @@ public class SendSignedTakerDepositTxAsHex {
@Override
public void handleResult() {
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
resultHandler.handleResult();
}
@Override
public void handleFault() {
log.error("RequestOffererDepositPublicationMessage did not arrive at peer");
exceptionHandler.handleException(
new Exception("RequestOffererDepositPublicationMessage did not arrive at peer"));
errorMessageHandler.handleErrorMessage("RequestOffererDepositPublicationMessage did not arrive at peer");
}
});
}

View File

@ -17,44 +17,41 @@
package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.TradeMessageService;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.network.Peer;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.util.handlers.ExceptionHandler;
import io.bitsquare.util.handlers.ResultHandler;
import io.bitsquare.util.handlers.ErrorMessageHandler;
import org.bitcoinj.core.Coin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SendTakeOfferFeePayedTxId {
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedTxId.class);
public class SendTakeOfferFeePayedMessage {
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedMessage.class);
public static void run(ResultHandler resultHandler,
ExceptionHandler exceptionHandler,
public static void run(ErrorMessageHandler errorMessageHandler,
Peer peer,
TradeMessageService tradeMessageService,
String tradeId,
String takeOfferFeeTxId,
Coin tradeAmount,
String pubKeyForThatTradeAsHex) {
log.trace("Run task");
String tradePubKeyAsHex) {
log.trace("Run SendTakeOfferFeePayedMessage task");
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId, takeOfferFeeTxId, tradeAmount,
pubKeyForThatTradeAsHex);
tradePubKeyAsHex);
tradeMessageService.sendMessage(peer, msg, new SendMessageListener() {
@Override
public void handleResult() {
log.trace("TakeOfferFeePayedMessage successfully arrived at peer");
resultHandler.handleResult();
log.trace("TakeOfferFeePayedMessage succeeded.");
}
@Override
public void handleFault() {
log.error("TakeOfferFeePayedMessage did not arrive at peer");
exceptionHandler.handleException(new Exception("TakeOfferFeePayedMessage did not arrive at peer"));
log.error("Sending TakeOfferFeePayedMessage failed.");
errorMessageHandler.handleErrorMessage("Sending TakeOfferFeePayedMessage failed.");
}
});
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.btc.WalletService;
import io.bitsquare.util.handlers.ExceptionHandler;
import org.bitcoinj.core.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TakerCommitDepositTx {
private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class);
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler, WalletService walletService, String depositTxAsHex) {
log.trace("Run PayDeposit task");
try {
Transaction transaction = walletService.takerCommitDepositTx(depositTxAsHex);
resultHandler.onResult(transaction);
} catch (Exception e) {
log.error("takerCommitDepositTx failed with exception " + e);
exceptionHandler.handleException(e);
}
}
public interface ResultHandler {
void onResult(Transaction transaction);
}
}

View File

@ -31,7 +31,7 @@ public class VerifyOffererAccount {
public static void run(ResultHandler resultHandler, ExceptionHandler exceptionHandler,
BlockChainService blockChainService, String peersAccountId, BankAccount peersBankAccount) {
log.trace("Run task");
log.trace("Run VerifyOffererAccount task");
VerifyPeerAccount.run(resultHandler, exceptionHandler, blockChainService, peersAccountId, peersBankAccount);
}
}

View File

@ -17,6 +17,8 @@
package io.bitsquare.util;
import io.bitsquare.trade.protocol.trade.TradeMessage;
import org.bitcoinj.core.Coin;
import static com.google.common.base.Preconditions.*;
@ -49,4 +51,9 @@ public class Validator {
return value;
}
public static void checkTradeId(String tradeId, TradeMessage tradeMessage) {
checkArgument(tradeId.equals(tradeMessage.getTradeId()));
}
}

View File

@ -48,7 +48,7 @@
<logger name="org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
<logger name="org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
<logger name="org.bitcoinj.wallet.DeterministicKeyChain" level="WARN"/>
<logger name="io.bitsquare.btc.WalletService" level="WARN"/>
<!-- <logger name="io.bitsquare.btc.WalletService" level="WARN"/>-->
<!--
<logger name="org.bitcoinj.core.Wallet" level="OFF"/>