mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 07:15:54 -04:00
Change protocol to support timelock correctly
This commit is contained in:
parent
36c2e4f1f7
commit
973aa73c76
@ -23,8 +23,6 @@ import org.bitcoinj.crypto.DeterministicKey;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@ -102,9 +100,10 @@ public class AddressEntry implements Serializable {
|
||||
return "AddressEntry{" +
|
||||
"offerId='" + offerId + '\'' +
|
||||
", context=" + context +
|
||||
", pubKey=" + Arrays.toString(pubKey) +
|
||||
", address=" + getAddressString() +
|
||||
/* ", pubKey=" + Arrays.toString(pubKey) +
|
||||
", pubKeyHash=" + Arrays.toString(pubKeyHash) +
|
||||
", params=" + params +
|
||||
", params=" + params +*/
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -411,22 +411,27 @@ public class TradeWalletService {
|
||||
return wallet.getTransaction(tx.getHash());
|
||||
}
|
||||
|
||||
public byte[] createAndSignPayoutTx(Transaction depositTx,
|
||||
Coin buyerPayoutAmount,
|
||||
Coin sellerPayoutAmount,
|
||||
AddressEntry buyerAddressEntry,
|
||||
String sellerPayoutAddressString,
|
||||
long lockTimeDelta,
|
||||
byte[] buyerPubKey,
|
||||
byte[] sellerPubKey,
|
||||
byte[] arbitratorPubKey)
|
||||
public int getLastBlockSeenHeight() {
|
||||
return wallet.getLastBlockSeenHeight();
|
||||
}
|
||||
|
||||
public byte[] signPayoutTx(Transaction depositTx,
|
||||
Coin buyerPayoutAmount,
|
||||
Coin sellerPayoutAmount,
|
||||
String buyerPayoutAddressString,
|
||||
AddressEntry sellerAddressEntry,
|
||||
long lockTime,
|
||||
byte[] buyerPubKey,
|
||||
byte[] sellerPubKey,
|
||||
byte[] arbitratorPubKey)
|
||||
throws AddressFormatException, TransactionVerificationException, SigningException {
|
||||
log.trace("createAndSignPayoutTx called");
|
||||
log.trace("depositTx " + depositTx.toString());
|
||||
log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
|
||||
log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
|
||||
log.trace("buyerAddressEntry " + buyerAddressEntry.toString());
|
||||
log.trace("sellerPayoutAddressString " + sellerPayoutAddressString);
|
||||
log.trace("buyerPayoutAddressString " + buyerPayoutAddressString);
|
||||
log.trace("sellerAddressEntry " + sellerAddressEntry.toString());
|
||||
log.trace("lockTime " + lockTime);
|
||||
log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
|
||||
log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
|
||||
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
|
||||
@ -434,45 +439,46 @@ public class TradeWalletService {
|
||||
Transaction preparedPayoutTx = createPayoutTx(depositTx,
|
||||
buyerPayoutAmount,
|
||||
sellerPayoutAmount,
|
||||
buyerAddressEntry.getAddressString(),
|
||||
sellerPayoutAddressString);
|
||||
preparedPayoutTx.setLockTime(wallet.getLastBlockSeenHeight() + lockTimeDelta);
|
||||
preparedPayoutTx.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||
buyerPayoutAddressString,
|
||||
sellerAddressEntry.getAddressString(),
|
||||
lockTime
|
||||
);
|
||||
// MS redeemScript
|
||||
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
||||
Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
||||
ECKey.ECDSASignature buyerSignature = buyerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
||||
ECKey.ECDSASignature sellerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
||||
|
||||
verifyTransaction(preparedPayoutTx);
|
||||
|
||||
printTxWithInputs("preparedPayoutTx", preparedPayoutTx);
|
||||
log.trace("buyerSignature r " + buyerSignature.toCanonicalised().r.toString());
|
||||
log.trace("buyerSignature s " + buyerSignature.toCanonicalised().s.toString());
|
||||
log.trace("sellerSignature r " + sellerSignature.toCanonicalised().r.toString());
|
||||
log.trace("sellerSignature s " + sellerSignature.toCanonicalised().s.toString());
|
||||
Sha256Hash hashForSignature = preparedPayoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1);
|
||||
log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes()));
|
||||
|
||||
return buyerSignature.encodeToDER();
|
||||
return sellerSignature.encodeToDER();
|
||||
}
|
||||
|
||||
public Transaction signAndFinalizePayoutTx(Transaction depositTx,
|
||||
byte[] buyerSignature,
|
||||
byte[] sellerSignature,
|
||||
Coin buyerPayoutAmount,
|
||||
Coin sellerPayoutAmount,
|
||||
String buyerAddressString,
|
||||
AddressEntry sellerAddressEntry,
|
||||
long lockTimeDelta,
|
||||
AddressEntry buyerAddressEntry,
|
||||
String sellerAddressString,
|
||||
long lockTime,
|
||||
byte[] buyerPubKey,
|
||||
byte[] sellerPubKey,
|
||||
byte[] arbitratorPubKey)
|
||||
throws AddressFormatException, TransactionVerificationException, WalletException, SigningException {
|
||||
log.trace("signAndPublishPayoutTx called");
|
||||
log.trace("depositTx " + depositTx.toString());
|
||||
log.trace("buyerSignature r " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).r.toString());
|
||||
log.trace("buyerSignature s " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).s.toString());
|
||||
log.trace("sellerSignature r " + ECKey.ECDSASignature.decodeFromDER(sellerSignature).r.toString());
|
||||
log.trace("sellerSignature s " + ECKey.ECDSASignature.decodeFromDER(sellerSignature).s.toString());
|
||||
log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
|
||||
log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
|
||||
log.trace("buyerAddressString " + buyerAddressString);
|
||||
log.trace("sellerAddressEntry " + sellerAddressEntry);
|
||||
log.trace("buyerAddressEntry " + buyerAddressEntry);
|
||||
log.trace("sellerAddressString " + sellerAddressString);
|
||||
log.trace("lockTime " + lockTime);
|
||||
log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
|
||||
log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
|
||||
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
|
||||
@ -480,28 +486,26 @@ public class TradeWalletService {
|
||||
Transaction payoutTx = createPayoutTx(depositTx,
|
||||
buyerPayoutAmount,
|
||||
sellerPayoutAmount,
|
||||
buyerAddressString,
|
||||
sellerAddressEntry.getAddressString());
|
||||
payoutTx.setLockTime(wallet.getLastBlockSeenHeight() + lockTimeDelta);
|
||||
payoutTx.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||
buyerAddressEntry.getAddressString(),
|
||||
sellerAddressString,
|
||||
lockTime);
|
||||
Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
|
||||
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
|
||||
ECKey.ECDSASignature sellerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
||||
ECKey.ECDSASignature buyerSignature = buyerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
|
||||
|
||||
log.trace("sellerSignature r " + sellerSignature.r.toString());
|
||||
log.trace("sellerSignature s " + sellerSignature.s.toString());
|
||||
log.trace("buyerSignature r " + buyerSignature.r.toString());
|
||||
log.trace("buyerSignature s " + buyerSignature.s.toString());
|
||||
|
||||
Sha256Hash hashForSignature = payoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1);
|
||||
log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes()));
|
||||
|
||||
TransactionSignature buyerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature),
|
||||
Transaction.SigHash.ALL, false);
|
||||
TransactionSignature sellerTxSig = new TransactionSignature(sellerSignature, Transaction.SigHash.ALL, false);
|
||||
TransactionSignature sellerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(sellerSignature), Transaction.SigHash.ALL, false);
|
||||
TransactionSignature buyerTxSig = new TransactionSignature(buyerSignature, Transaction.SigHash.ALL, false);
|
||||
// Take care of order of signatures. See comment below at getMultiSigRedeemScript
|
||||
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);
|
||||
TransactionInput input = payoutTx.getInput(0);
|
||||
input.setScriptSig(inputScript);
|
||||
|
||||
printTxWithInputs("payoutTx", payoutTx);
|
||||
verifyTransaction(payoutTx);
|
||||
checkWalletConsistency();
|
||||
checkScriptSig(payoutTx, input, 0);
|
||||
@ -561,13 +565,15 @@ public class TradeWalletService {
|
||||
Coin buyerPayoutAmount,
|
||||
Coin sellerPayoutAmount,
|
||||
String buyerAddressString,
|
||||
String sellerAddressString) throws AddressFormatException {
|
||||
|
||||
String sellerAddressString,
|
||||
long lockTime) throws AddressFormatException {
|
||||
TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
|
||||
Transaction transaction = new Transaction(params);
|
||||
transaction.addInput(p2SHMultiSigOutput);
|
||||
transaction.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString));
|
||||
transaction.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString));
|
||||
transaction.setLockTime(lockTime);
|
||||
transaction.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,7 @@ abstract public class Trade implements Model, Serializable {
|
||||
private String sellerContractSignature;
|
||||
private String buyerContractSignature;
|
||||
private Transaction payoutTx;
|
||||
private long lockTime;
|
||||
|
||||
// Transient/Mutable
|
||||
transient private String errorMessage;
|
||||
@ -168,12 +169,13 @@ abstract public class Trade implements Model, Serializable {
|
||||
|
||||
createProtocol();
|
||||
|
||||
tradeProtocol.checkPayoutTxTimeLock(this);
|
||||
|
||||
if (mailboxMessage != null) {
|
||||
tradeProtocol.applyMailboxMessage(mailboxMessage, this);
|
||||
// After applied to protocol we remove it
|
||||
mailboxMessage = null;
|
||||
}
|
||||
tradeProtocol.checkPayoutTxTimeLock(this);
|
||||
}
|
||||
|
||||
protected void initStateProperties() {
|
||||
@ -334,16 +336,19 @@ abstract public class Trade implements Model, Serializable {
|
||||
tradeVolumeProperty.set(getTradeVolume());
|
||||
}
|
||||
|
||||
// TODO support case of multiple fiat accounts
|
||||
public long getLockTimeDelta() {
|
||||
return getOffer().getFiatAccountType().lockTimeDelta;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Coin getTradeAmount() {
|
||||
return tradeAmount;
|
||||
}
|
||||
|
||||
public void setLockTime(long lockTime) {
|
||||
this.lockTime = lockTime;
|
||||
}
|
||||
|
||||
public long getLockTime() {
|
||||
return lockTime;
|
||||
}
|
||||
|
||||
public void setSellerContractSignature(String takerSignature) {
|
||||
this.sellerContractSignature = takerSignature;
|
||||
}
|
||||
@ -466,4 +471,5 @@ abstract public class Trade implements Model, Serializable {
|
||||
", throwable=" + throwable +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
@ -25,23 +25,24 @@ import io.bitsquare.trade.BuyerAsOffererTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
|
||||
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakerAccount;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
|
||||
@ -82,8 +83,8 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||
// Might be called twice, so check that its only processed once
|
||||
if (!processModel.isMailboxMessageProcessed()) {
|
||||
processModel.mailboxMessageProcessed();
|
||||
if (mailboxMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) mailboxMessage);
|
||||
if (mailboxMessage instanceof RequestFinalizePayoutTxMessage) {
|
||||
handle((RequestFinalizePayoutTxMessage) mailboxMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -173,7 +174,6 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||
this::handleTaskRunnerFault);
|
||||
taskRunner.addTasks(
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
CreateAndSignPayoutTx.class,
|
||||
SendFiatTransferStartedMessage.class
|
||||
);
|
||||
taskRunner.run();
|
||||
@ -184,7 +184,8 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||
// Incoming message handling
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||
private void handle(RequestFinalizePayoutTxMessage tradeMessage) {
|
||||
log.debug("handle RequestFinalizePayoutTxMessage called");
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
|
||||
@ -196,8 +197,10 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessPayoutTxFinalizedMessage.class,
|
||||
ProcessRequestFinalizePayoutTxMessage.class,
|
||||
SignAndFinalizePayoutTx.class,
|
||||
CommitPayoutTx.class,
|
||||
SendPayoutTxFinalizedMessage.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class
|
||||
);
|
||||
taskRunner.run();
|
||||
@ -224,8 +227,8 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
|
||||
else if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
||||
handle((RequestPublishDepositTxMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||
else if (tradeMessage instanceof RequestFinalizePayoutTxMessage) {
|
||||
handle((RequestFinalizePayoutTxMessage) tradeMessage);
|
||||
}
|
||||
else {
|
||||
log.error("Incoming tradeMessage not supported. " + tradeMessage);
|
||||
|
@ -22,19 +22,21 @@ import io.bitsquare.p2p.Message;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.trade.BuyerAsTakerTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.VerifyAndSignContract;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||
@ -79,8 +81,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
// Might be called twice, so check that its only processed once
|
||||
if (!processModel.isMailboxMessageProcessed()) {
|
||||
processModel.mailboxMessageProcessed();
|
||||
if (mailboxMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) mailboxMessage);
|
||||
if (mailboxMessage instanceof RequestFinalizePayoutTxMessage) {
|
||||
handle((RequestFinalizePayoutTxMessage) mailboxMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +138,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
this::handleTaskRunnerFault);
|
||||
taskRunner.addTasks(
|
||||
VerifyOfferFeePayment.class,
|
||||
CreateAndSignPayoutTx.class,
|
||||
SignPayoutTx.class,
|
||||
SendFiatTransferStartedMessage.class
|
||||
);
|
||||
taskRunner.run();
|
||||
@ -144,10 +146,10 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// After peer has received Fiat tx
|
||||
// Incoming message handling
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||
private void handle(RequestFinalizePayoutTxMessage tradeMessage) {
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
|
||||
@ -159,13 +161,15 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessPayoutTxFinalizedMessage.class,
|
||||
ProcessRequestFinalizePayoutTxMessage.class,
|
||||
SignAndFinalizePayoutTx.class,
|
||||
CommitPayoutTx.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class);
|
||||
SendPayoutTxFinalizedMessage.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class
|
||||
);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Massage dispatcher
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -180,8 +184,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
|
||||
if (tradeMessage instanceof RequestPublishDepositTxMessage) {
|
||||
handle((RequestPublishDepositTxMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||
else if (tradeMessage instanceof RequestFinalizePayoutTxMessage) {
|
||||
handle((RequestFinalizePayoutTxMessage) tradeMessage);
|
||||
}
|
||||
else {
|
||||
log.error("Incoming message not supported. " + tradeMessage);
|
||||
|
@ -30,7 +30,6 @@ import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.crypto.DeterministicKey;
|
||||
@ -70,7 +69,7 @@ public class ProcessModel implements Model, Serializable {
|
||||
transient private TradeMessage tradeMessage;
|
||||
private String takeOfferFeeTxId;
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private Coin payoutAmount;
|
||||
// private Coin payoutAmount;
|
||||
private Transaction preparedDepositTx;
|
||||
private List<TransactionOutput> outputs; // used to verify amounts with change outputs
|
||||
private byte[] payoutTxSignature;
|
||||
@ -215,14 +214,14 @@ public class ProcessModel implements Model, Serializable {
|
||||
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
/* @Nullable
|
||||
public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
}*/
|
||||
|
||||
@Nullable
|
||||
public Transaction getPreparedDepositTx() {
|
||||
|
@ -27,6 +27,7 @@ import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailability
|
||||
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment;
|
||||
@ -36,10 +37,12 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignContract;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
|
||||
@ -193,8 +196,6 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
|
||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||
@Override
|
||||
public void onFiatPaymentReceived() {
|
||||
sellerAsOffererTrade.setProcessState(OffererTradeState.ProcessState.FIAT_PAYMENT_RECEIVED);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleFiatReceivedUIEvent completed");
|
||||
@ -206,13 +207,26 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
|
||||
|
||||
taskRunner.addTasks(
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
SignAndFinalizePayoutTx.class,
|
||||
SendPayoutTxFinalizedMessage.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class
|
||||
SignPayoutTx.class,
|
||||
SendRequestFinalizePayoutTxMessage.class
|
||||
);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
|
||||
() -> log.debug("taskRunner at handleFiatTransferStartedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessPayoutTxFinalizedMessage.class,
|
||||
CommitPayoutTx.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class
|
||||
);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Massage dispatcher
|
||||
@ -236,6 +250,9 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
|
||||
else if (tradeMessage instanceof FiatTransferStartedMessage) {
|
||||
handle((FiatTransferStartedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||
}
|
||||
else {
|
||||
log.error("Incoming tradeMessage not supported. " + tradeMessage);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import io.bitsquare.trade.SellerAsTakerTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.CommitDepositTx;
|
||||
@ -31,17 +32,18 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignContract;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.BroadcastTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOffererAccount;
|
||||
import io.bitsquare.trade.states.TakerTradeState;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -87,6 +89,9 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
else if (mailboxMessage instanceof DepositTxPublishedMessage) {
|
||||
handle((DepositTxPublishedMessage) mailboxMessage);
|
||||
}
|
||||
else if (mailboxMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) mailboxMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,7 +121,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
|
||||
() -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"),
|
||||
() -> log.debug("taskRunner at RequestPayDepositMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
@ -135,7 +140,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
|
||||
() -> log.debug("taskRunner at handleDepositTxPublishedMessage completed"),
|
||||
() -> log.debug("taskRunner at DepositTxPublishedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
@ -154,7 +159,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
|
||||
() -> log.debug("taskRunner at handleFiatTransferStartedMessage completed"),
|
||||
() -> log.debug("taskRunner at FiatTransferStartedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(ProcessFiatTransferStartedMessage.class);
|
||||
@ -169,11 +174,9 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||
@Override
|
||||
public void onFiatPaymentReceived() {
|
||||
sellerAsTakerTrade.setProcessState(TakerTradeState.ProcessState.FIAT_PAYMENT_RECEIVED);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleFiatReceivedUIEvent completed");
|
||||
log.debug("taskRunner at onFiatPaymentReceived completed");
|
||||
|
||||
// we are done!
|
||||
processModel.onComplete();
|
||||
@ -182,13 +185,28 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
|
||||
taskRunner.addTasks(
|
||||
VerifyOfferFeePayment.class,
|
||||
SignAndFinalizePayoutTx.class,
|
||||
SendPayoutTxFinalizedMessage.class,
|
||||
SignPayoutTx.class,
|
||||
SendRequestFinalizePayoutTxMessage.class
|
||||
);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
private void handle(PayoutTxFinalizedMessage tradeMessage) {
|
||||
processModel.setTradeMessage(tradeMessage);
|
||||
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
|
||||
() -> log.debug("taskRunner at PayoutTxFinalizedMessage completed"),
|
||||
this::handleTaskRunnerFault);
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessPayoutTxFinalizedMessage.class,
|
||||
CommitPayoutTx.class,
|
||||
SetupPayoutTxLockTimeReachedListener.class
|
||||
);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Massage dispatcher
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -209,7 +227,11 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
|
||||
else if (tradeMessage instanceof FiatTransferStartedMessage) {
|
||||
handle((FiatTransferStartedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxFinalizedMessage) {
|
||||
handle((PayoutTxFinalizedMessage) tradeMessage);
|
||||
}
|
||||
else {
|
||||
|
||||
log.error("Incoming message not supported. " + tradeMessage);
|
||||
}
|
||||
}
|
||||
|
@ -61,11 +61,9 @@ public abstract class TradeProtocol {
|
||||
|
||||
boolean needPayoutTxBroadcast = false;
|
||||
if (trade instanceof TakerTrade)
|
||||
needPayoutTxBroadcast = trade.processStateProperty().get() == TakerTradeState.ProcessState.PAYOUT_FINALIZED
|
||||
|| trade.processStateProperty().get() == TakerTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT;
|
||||
needPayoutTxBroadcast = trade.processStateProperty().get() == TakerTradeState.ProcessState.PAYOUT_FINALIZED;
|
||||
else if (trade instanceof OffererTrade)
|
||||
needPayoutTxBroadcast = trade.processStateProperty().get() == OffererTradeState.ProcessState.PAYOUT_FINALIZED
|
||||
|| trade.processStateProperty().get() == OffererTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT;
|
||||
needPayoutTxBroadcast = trade.processStateProperty().get() == OffererTradeState.ProcessState.PAYOUT_FINALIZED;
|
||||
|
||||
if (needPayoutTxBroadcast) {
|
||||
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
|
||||
@ -92,7 +90,7 @@ public abstract class TradeProtocol {
|
||||
log.debug("Timeout reached");
|
||||
if (trade instanceof TakerTrade)
|
||||
trade.setProcessState(TakerTradeState.ProcessState.TIMEOUT);
|
||||
else
|
||||
else if (trade instanceof OffererTrade)
|
||||
trade.setProcessState(OffererTradeState.ProcessState.TIMEOUT);
|
||||
});
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ package io.bitsquare.trade.protocol.trade;
|
||||
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
|
||||
@ -49,11 +48,12 @@ public class TradingPeer implements Serializable {
|
||||
private Transaction preparedDepositTx;
|
||||
private List<TransactionOutput> connectedOutputsForAllInputs;
|
||||
private List<TransactionOutput> outputs;
|
||||
private Coin payoutAmount;
|
||||
// private Coin payoutAmount;
|
||||
private String payoutAddressString;
|
||||
private byte[] signature;
|
||||
// private byte[] signature;
|
||||
private String contractAsJson;
|
||||
private String contractSignature;
|
||||
private byte[] signature;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -138,13 +138,13 @@ public class TradingPeer implements Serializable {
|
||||
this.outputs = outputs;
|
||||
}
|
||||
|
||||
public Coin getPayoutAmount() {
|
||||
/* public Coin getPayoutAmount() {
|
||||
return payoutAmount;
|
||||
}
|
||||
|
||||
public void setPayoutAmount(Coin payoutAmount) {
|
||||
this.payoutAmount = payoutAmount;
|
||||
}
|
||||
}*/
|
||||
|
||||
public String getPayoutAddressString() {
|
||||
return payoutAddressString;
|
||||
@ -154,13 +154,13 @@ public class TradingPeer implements Serializable {
|
||||
this.payoutAddressString = payoutAddressString;
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
/* public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(byte[] signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
}*/
|
||||
|
||||
public String getContractAsJson() {
|
||||
return contractAsJson;
|
||||
@ -177,4 +177,12 @@ public class TradingPeer implements Serializable {
|
||||
public void setContractSignature(String contractSignature) {
|
||||
this.contractSignature = contractSignature;
|
||||
}
|
||||
|
||||
public void setSignature(byte[] signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ package io.bitsquare.trade.protocol.trade.messages;
|
||||
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@ -30,20 +28,11 @@ public class FiatTransferStartedMessage extends TradeMessage implements MailboxM
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final byte[] buyerSignature;
|
||||
public final Coin buyerPayoutAmount;
|
||||
public final String buyerPayoutAddress;
|
||||
public final Coin sellerPayoutAmount;
|
||||
|
||||
public FiatTransferStartedMessage(String tradeId,
|
||||
byte[] buyerSignature,
|
||||
Coin buyerPayoutAmount,
|
||||
String buyerPayoutAddress,
|
||||
Coin sellerPayoutAmount) {
|
||||
String buyerPayoutAddress) {
|
||||
super(tradeId);
|
||||
this.buyerSignature = buyerSignature;
|
||||
this.buyerPayoutAmount = buyerPayoutAmount;
|
||||
this.buyerPayoutAddress = buyerPayoutAddress;
|
||||
this.sellerPayoutAmount = sellerPayoutAmount;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.messages;
|
||||
|
||||
import io.bitsquare.p2p.MailboxMessage;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
public class RequestFinalizePayoutTxMessage extends TradeMessage implements MailboxMessage, Serializable {
|
||||
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final byte[] sellerSignature;
|
||||
public final String sellerPayoutAddress;
|
||||
public final long lockTime;
|
||||
|
||||
public RequestFinalizePayoutTxMessage(String tradeId,
|
||||
byte[] sellerSignature,
|
||||
String sellerPayoutAddress,
|
||||
long lockTime) {
|
||||
super(tradeId);
|
||||
this.sellerSignature = sellerSignature;
|
||||
this.sellerPayoutAddress = sellerPayoutAddress;
|
||||
this.lockTime = lockTime;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.states.StateUtil;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static io.bitsquare.util.Validator.*;
|
||||
|
||||
public class ProcessRequestFinalizePayoutTxMessage extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProcessRequestFinalizePayoutTxMessage.class);
|
||||
|
||||
public ProcessRequestFinalizePayoutTxMessage(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
RequestFinalizePayoutTxMessage message = (RequestFinalizePayoutTxMessage) processModel.getTradeMessage();
|
||||
checkTradeId(processModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
processModel.tradingPeer.setSignature(checkNotNull(message.sellerSignature));
|
||||
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(message.sellerPayoutAddress));
|
||||
trade.setLockTime(nonNegativeLongOf(message.lockTime));
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
trade.setThrowable(t);
|
||||
StateUtil.setOfferOpenState(trade);
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
@ -42,10 +42,7 @@ public class SendFiatTransferStartedMessage extends TradeTask {
|
||||
protected void doRun() {
|
||||
try {
|
||||
FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(processModel.getId(),
|
||||
processModel.getPayoutTxSignature(),
|
||||
processModel.getPayoutAmount(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
processModel.tradingPeer.getPayoutAmount()
|
||||
processModel.getAddressEntry().getAddressString()
|
||||
);
|
||||
|
||||
processModel.getMessageService().sendMessage(trade.getTradingPeer(), tradeMessage,
|
||||
|
@ -15,18 +15,14 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.p2p.listener.SendMessageListener;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
import io.bitsquare.trade.TakerTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
import io.bitsquare.trade.states.StateUtil;
|
||||
import io.bitsquare.trade.states.TakerTradeState;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -49,19 +45,14 @@ public class SendPayoutTxFinalizedMessage extends TradeTask {
|
||||
new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||
|
||||
if (trade instanceof TakerTrade)
|
||||
trade.setProcessState(TakerTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT);
|
||||
else if (trade instanceof OffererTrade)
|
||||
trade.setProcessState(OffererTradeState.ProcessState.PAYOUT_FINALIZED_MSG_SENT);
|
||||
log.trace("PayoutTxFinalizedMessage successfully arrived at peer");
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFault() {
|
||||
appendToErrorMessage("Sending PayoutTxPublishedMessage failed");
|
||||
appendToErrorMessage("Sending PayoutTxFinalizedMessage failed");
|
||||
trade.setErrorMessage(errorMessage);
|
||||
StateUtil.setSendFailedState(trade);
|
||||
failed();
|
@ -15,7 +15,7 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
@ -25,6 +25,7 @@ import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
import io.bitsquare.trade.states.TakerTradeState;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -40,16 +41,21 @@ public class SignAndFinalizePayoutTx extends TradeTask {
|
||||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
assert trade.getTradeAmount() != null;
|
||||
assert trade.getSecurityDeposit() != null;
|
||||
Coin sellerPayoutAmount = trade.getSecurityDeposit();
|
||||
Coin buyerPayoutAmount = sellerPayoutAmount.add(trade.getTradeAmount());
|
||||
|
||||
Transaction transaction = processModel.getTradeWalletService().signAndFinalizePayoutTx(
|
||||
trade.getDepositTx(),
|
||||
processModel.tradingPeer.getSignature(),
|
||||
processModel.tradingPeer.getPayoutAmount(),
|
||||
processModel.getPayoutAmount(),
|
||||
processModel.tradingPeer.getPayoutAddressString(),
|
||||
buyerPayoutAmount,
|
||||
sellerPayoutAmount,
|
||||
processModel.getAddressEntry(),
|
||||
trade.getLockTimeDelta(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.tradingPeer.getPayoutAddressString(),
|
||||
trade.getLockTime(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey()
|
||||
);
|
||||
|
@ -46,9 +46,6 @@ public class ProcessFiatTransferStartedMessage extends TradeTask {
|
||||
checkTradeId(processModel.getId(), message);
|
||||
checkNotNull(message);
|
||||
|
||||
processModel.tradingPeer.setSignature(checkNotNull(message.buyerSignature));
|
||||
processModel.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.sellerPayoutAmount)));
|
||||
processModel.tradingPeer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.buyerPayoutAmount)));
|
||||
processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(message.buyerPayoutAddress));
|
||||
|
||||
if (trade instanceof OffererTrade)
|
||||
|
@ -15,7 +15,7 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.OffererTrade;
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.tasks.seller;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.p2p.listener.SendMessageListener;
|
||||
import io.bitsquare.trade.OffererTrade;
|
||||
import io.bitsquare.trade.TakerTrade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.TradeTask;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestFinalizePayoutTxMessage;
|
||||
import io.bitsquare.trade.states.OffererTradeState;
|
||||
import io.bitsquare.trade.states.StateUtil;
|
||||
import io.bitsquare.trade.states.TakerTradeState;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendRequestFinalizePayoutTxMessage extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SendRequestFinalizePayoutTxMessage.class);
|
||||
|
||||
public SendRequestFinalizePayoutTxMessage(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
RequestFinalizePayoutTxMessage message = new RequestFinalizePayoutTxMessage(
|
||||
processModel.getId(),
|
||||
processModel.getPayoutTxSignature(),
|
||||
processModel.getAddressEntry().getAddressString(),
|
||||
trade.getLockTime()
|
||||
);
|
||||
|
||||
processModel.getMessageService().sendMessage(trade.getTradingPeer(),
|
||||
message,
|
||||
processModel.tradingPeer.getP2pSigPubKey(),
|
||||
processModel.tradingPeer.getP2pEncryptPubKey(),
|
||||
new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||
|
||||
if (trade instanceof TakerTrade)
|
||||
trade.setProcessState(TakerTradeState.ProcessState.REQUEST_PAYOUT_FINALIZE_MSG_SENT);
|
||||
else if (trade instanceof OffererTrade)
|
||||
trade.setProcessState(OffererTradeState.ProcessState.REQUEST_PAYOUT_FINALIZE_MSG_SENT);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFault() {
|
||||
appendToErrorMessage("Sending PayoutTxPublishedMessage failed");
|
||||
trade.setErrorMessage(errorMessage);
|
||||
StateUtil.setSendFailedState(trade);
|
||||
failed();
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
trade.setThrowable(t);
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
package io.bitsquare.trade.protocol.trade.tasks.seller;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
@ -26,10 +26,10 @@ import org.bitcoinj.core.Coin;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateAndSignPayoutTx extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignPayoutTx.class);
|
||||
public class SignPayoutTx extends TradeTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(SignPayoutTx.class);
|
||||
|
||||
public CreateAndSignPayoutTx(TaskRunner taskHandler, Trade trade) {
|
||||
public SignPayoutTx(TaskRunner taskHandler, Trade trade) {
|
||||
super(taskHandler, trade);
|
||||
}
|
||||
|
||||
@ -41,20 +41,21 @@ public class CreateAndSignPayoutTx extends TradeTask {
|
||||
Coin sellerPayoutAmount = trade.getSecurityDeposit();
|
||||
Coin buyerPayoutAmount = sellerPayoutAmount.add(trade.getTradeAmount());
|
||||
|
||||
byte[] buyerPayoutTxSignature = processModel.getTradeWalletService().createAndSignPayoutTx(
|
||||
long lockTime = processModel.getTradeWalletService().getLastBlockSeenHeight() + trade.getOffer().getFiatAccountType().lockTimeDelta;
|
||||
trade.setLockTime(lockTime);
|
||||
|
||||
byte[] payoutTxSignature = processModel.getTradeWalletService().signPayoutTx(
|
||||
trade.getDepositTx(),
|
||||
buyerPayoutAmount,
|
||||
sellerPayoutAmount,
|
||||
processModel.getAddressEntry(),
|
||||
processModel.tradingPeer.getPayoutAddressString(),
|
||||
trade.getLockTimeDelta(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getAddressEntry(),
|
||||
lockTime,
|
||||
processModel.tradingPeer.getTradeWalletPubKey(),
|
||||
processModel.getTradeWalletPubKey(),
|
||||
processModel.getArbitratorPubKey());
|
||||
|
||||
processModel.setPayoutTxSignature(buyerPayoutTxSignature);
|
||||
processModel.setPayoutAmount(buyerPayoutAmount);
|
||||
processModel.tradingPeer.setPayoutAmount(sellerPayoutAmount);
|
||||
processModel.setPayoutTxSignature(payoutTxSignature);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
@ -15,7 +15,7 @@
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.trade.protocol.trade.tasks.buyer;
|
||||
package io.bitsquare.trade.protocol.trade.tasks.shared;
|
||||
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
@ -49,7 +49,8 @@ public class SetupPayoutTxLockTimeReachedListener extends TradeTask {
|
||||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
if (processModel.getTradeWalletService().getBestChainHeight() >= trade.getPayoutTx().getLockTime()) {
|
||||
log.debug("ChainHeight/LockTime: {} / {}", processModel.getTradeWalletService().getBestChainHeight(), trade.getLockTime());
|
||||
if (processModel.getTradeWalletService().getBestChainHeight() >= trade.getLockTime()) {
|
||||
broadcastTx();
|
||||
}
|
||||
else {
|
||||
|
@ -35,15 +35,15 @@ public class OffererTradeState {
|
||||
public enum ProcessState implements TradeState.ProcessState {
|
||||
UNDEFINED,
|
||||
DEPOSIT_PUBLISHED,
|
||||
DEPOSIT_CONFIRMED,
|
||||
DEPOSIT_CONFIRMED,
|
||||
|
||||
FIAT_PAYMENT_STARTED,
|
||||
|
||||
FIAT_PAYMENT_RECEIVED,
|
||||
REQUEST_PAYOUT_FINALIZE_MSG_SENT, // seller only
|
||||
PAYOUT_FINALIZED,
|
||||
PAYOUT_FINALIZED_MSG_SENT,
|
||||
|
||||
PAYOUT_BROAD_CASTED,
|
||||
PAYOUT_BROAD_CASTED_FAILED,
|
||||
PAYOUT_BROAD_CASTED_FAILED,
|
||||
|
||||
MESSAGE_SENDING_FAILED,
|
||||
TIMEOUT,
|
||||
|
@ -40,9 +40,9 @@ public class TakerTradeState {
|
||||
|
||||
FIAT_PAYMENT_STARTED,
|
||||
|
||||
FIAT_PAYMENT_RECEIVED,
|
||||
REQUEST_PAYOUT_FINALIZE_MSG_SENT, // seller only
|
||||
PAYOUT_FINALIZED,
|
||||
PAYOUT_FINALIZED_MSG_SENT,
|
||||
|
||||
PAYOUT_BROAD_CASTED,
|
||||
PAYOUT_BROAD_CASTED_FAILED,
|
||||
|
||||
|
@ -30,14 +30,14 @@ import io.bitsquare.trade.protocol.placeoffer.tasks.CreateOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.placeoffer.tasks.ValidateOffer;
|
||||
import io.bitsquare.trade.protocol.trade.BuyerAsOffererProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.SellerAsTakerProtocol;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateAndSignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.CreateDepositTxInputs;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.ProcessRequestPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SendRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.buyer.SignAndPublishDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakerAccount;
|
||||
@ -45,10 +45,10 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.CommitDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.CreateAndSignDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessDepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessFiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.ProcessRequestPayDepositMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendPayoutTxFinalizedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignAndFinalizePayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.seller.SignPayoutTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.CreateTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.tasks.taker.VerifyOffererAccount;
|
||||
@ -107,7 +107,7 @@ public class DebugView extends InitializableView {
|
||||
SignAndPublishDepositTx.class,
|
||||
SendDepositTxPublishedMessage.class,
|
||||
|
||||
CreateAndSignPayoutTx.class,
|
||||
SignPayoutTx.class,
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
SendFiatTransferStartedMessage.class,
|
||||
|
||||
|
@ -255,8 +255,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
"Please try later again." + msg);
|
||||
takeOfferRequested = false;
|
||||
break;
|
||||
case PAYOUT_FINALIZED:
|
||||
break;
|
||||
case EXCEPTION:
|
||||
errorMessage.set(msg);
|
||||
takeOfferRequested = false;
|
||||
@ -292,8 +290,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
"Please try later again." + msg);
|
||||
takeOfferRequested = false;
|
||||
break;
|
||||
case PAYOUT_FINALIZED:
|
||||
break;
|
||||
case EXCEPTION:
|
||||
errorMessage.set(msg);
|
||||
takeOfferRequested = false;
|
||||
|
@ -50,8 +50,8 @@ public class BuyerSubView extends TradeSubView {
|
||||
@Override
|
||||
protected void addWizards() {
|
||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||
startFiat = new TradeWizardItem(StartFiatView.class, "Start payment");
|
||||
waitFiatReceived = new TradeWizardItem(WaitFiatReceivedView.class, "Wait until payment has arrived");
|
||||
startFiat = new TradeWizardItem(StartFiatView.class, "Start EUR payment");
|
||||
waitFiatReceived = new TradeWizardItem(WaitFiatReceivedView.class, "Wait until EUR payment arrived");
|
||||
payoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||
|
||||
|
@ -299,7 +299,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
||||
}
|
||||
|
||||
public long getLockTime() {
|
||||
return trade.getPayoutTx().getLockTime();
|
||||
return trade.getLockTime();
|
||||
}
|
||||
|
||||
public int getBestChainHeight() {
|
||||
|
@ -58,7 +58,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
SELLER_WAIT_TX_CONF,
|
||||
SELLER_WAIT_PAYMENT_STARTED,
|
||||
SELLER_CONFIRM_RECEIVE_PAYMENT,
|
||||
SELLER_SEND_PUBLISHED_MSG,
|
||||
SELLER_REQUEST_PAYOUT_FINALIZE_MSG_SENT,
|
||||
SELLER_PAYOUT_FINALIZED,
|
||||
SELLER_COMPLETED,
|
||||
|
||||
@ -329,14 +329,13 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
viewState.set(ViewState.SELLER_CONFIRM_RECEIVE_PAYMENT);
|
||||
break;
|
||||
|
||||
case FIAT_PAYMENT_RECEIVED:
|
||||
case REQUEST_PAYOUT_FINALIZE_MSG_SENT:
|
||||
viewState.set(ViewState.SELLER_REQUEST_PAYOUT_FINALIZE_MSG_SENT);
|
||||
break;
|
||||
case PAYOUT_FINALIZED:
|
||||
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
||||
break;
|
||||
case PAYOUT_FINALIZED_MSG_SENT:
|
||||
viewState.set(ViewState.SELLER_PAYOUT_FINALIZED);
|
||||
break;
|
||||
|
||||
case PAYOUT_BROAD_CASTED:
|
||||
viewState.set(ViewState.SELLER_COMPLETED);
|
||||
break;
|
||||
@ -376,14 +375,13 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
viewState.set(ViewState.SELLER_CONFIRM_RECEIVE_PAYMENT);
|
||||
break;
|
||||
|
||||
case FIAT_PAYMENT_RECEIVED:
|
||||
case REQUEST_PAYOUT_FINALIZE_MSG_SENT:
|
||||
viewState.set(ViewState.SELLER_REQUEST_PAYOUT_FINALIZE_MSG_SENT);
|
||||
break;
|
||||
case PAYOUT_FINALIZED:
|
||||
viewState.set(ViewState.SELLER_SEND_PUBLISHED_MSG);
|
||||
break;
|
||||
case PAYOUT_FINALIZED_MSG_SENT:
|
||||
viewState.set(ViewState.SELLER_PAYOUT_FINALIZED);
|
||||
break;
|
||||
|
||||
case PAYOUT_BROAD_CASTED:
|
||||
viewState.set(ViewState.SELLER_COMPLETED);
|
||||
break;
|
||||
@ -431,11 +429,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
viewState.set(ViewState.BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED);
|
||||
break;
|
||||
|
||||
case FIAT_PAYMENT_RECEIVED:
|
||||
case PAYOUT_FINALIZED:
|
||||
case PAYOUT_FINALIZED_MSG_SENT:
|
||||
case PAYOUT_FINALIZED:
|
||||
viewState.set(ViewState.BUYER_PAYOUT_FINALIZED);
|
||||
break;
|
||||
|
||||
case PAYOUT_BROAD_CASTED:
|
||||
viewState.set(ViewState.BUYER_COMPLETED);
|
||||
break;
|
||||
@ -477,11 +474,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
viewState.set(ViewState.BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED);
|
||||
break;
|
||||
|
||||
case FIAT_PAYMENT_RECEIVED:
|
||||
case PAYOUT_FINALIZED:
|
||||
case PAYOUT_FINALIZED_MSG_SENT:
|
||||
case PAYOUT_FINALIZED:
|
||||
viewState.set(ViewState.BUYER_PAYOUT_FINALIZED);
|
||||
break;
|
||||
|
||||
case PAYOUT_BROAD_CASTED:
|
||||
viewState.set(ViewState.BUYER_COMPLETED);
|
||||
break;
|
||||
|
@ -21,6 +21,7 @@ import io.bitsquare.gui.components.Popups;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.CompletedView;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.ConfirmFiatReceivedView;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeWizardItem;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitPayoutFinalizedView;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitPayoutLockTimeView;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.WaitTxInBlockchainView;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
@ -49,8 +50,8 @@ public class SellerSubView extends TradeSubView {
|
||||
@Override
|
||||
protected void addWizards() {
|
||||
waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation");
|
||||
waitFiatStarted = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for payment started");
|
||||
confirmFiatReceived = new TradeWizardItem(ConfirmFiatReceivedView.class, "Confirm payment received");
|
||||
waitFiatStarted = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait until EUR payment has started");
|
||||
confirmFiatReceived = new TradeWizardItem(ConfirmFiatReceivedView.class, "Confirm EUR payment received");
|
||||
payoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock");
|
||||
completed = new TradeWizardItem(CompletedView.class, "Completed");
|
||||
|
||||
@ -118,14 +119,18 @@ public class SellerSubView extends TradeSubView {
|
||||
model.getCurrencyCode()));*/
|
||||
|
||||
break;
|
||||
case SELLER_SEND_PUBLISHED_MSG:
|
||||
if (tradeStepDetailsView == null) {
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitFiatStarted.setCompleted();
|
||||
showItem(confirmFiatReceived);
|
||||
}
|
||||
case SELLER_REQUEST_PAYOUT_FINALIZE_MSG_SENT:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
waitFiatStarted.setCompleted();
|
||||
confirmFiatReceived.setCompleted();
|
||||
showItem(payoutUnlock);
|
||||
|
||||
((ConfirmFiatReceivedView) tradeStepDetailsView).setStatusText("Sending message to trading peer transaction...");
|
||||
// We dont use a wizard for that step as it only gets displayed in case the other peer is offline
|
||||
tradeStepDetailsView = new WaitPayoutFinalizedView(model);
|
||||
contentPane.getChildren().setAll(tradeStepDetailsView);
|
||||
|
||||
((WaitPayoutFinalizedView) tradeStepDetailsView).setInfoLabelText("We requested the trading peer to sign and finalize the payout transaction." +
|
||||
"\nIt might be that the other peer is offline, so we need to wait until he finalize the transaction when he goes online again.");
|
||||
break;
|
||||
case SELLER_PAYOUT_FINALIZED:
|
||||
waitTxInBlockchain.setCompleted();
|
||||
|
@ -83,7 +83,7 @@ public class ConfirmFiatReceivedView extends TradeStepDetailsView {
|
||||
log.debug("onPaymentReceived");
|
||||
model.fiatPaymentReceived();
|
||||
confirmFiatReceivedButton.setDisable(true);
|
||||
statusLabel.setText("Finalizing payout transaction...");
|
||||
statusLabel.setText("Sending message to trading peer...");
|
||||
statusProgressIndicator.setVisible(true);
|
||||
statusProgressIndicator.setProgress(-1);
|
||||
root = statusProgressIndicator.getScene().getRoot();
|
||||
@ -106,10 +106,6 @@ public class ConfirmFiatReceivedView extends TradeStepDetailsView {
|
||||
infoDisplay.setText(text);
|
||||
}
|
||||
|
||||
public void setStatusText(String text) {
|
||||
statusLabel.setText(text);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
@ -123,11 +119,10 @@ public class ConfirmFiatReceivedView extends TradeStepDetailsView {
|
||||
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information", Layout.GROUP_DISTANCE);
|
||||
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
|
||||
ButtonWithProgressIndicatorAndLabelBucket bucket = getAndAddButtonWithStatus(gridPane, gridRow++, "Confirm payment receipt", this::onPaymentReceived);
|
||||
ButtonWithProgressIndicatorAndLabel bucket = getAndAddButtonWithStatus(gridPane, gridRow++, "Confirm payment receipt", this::onPaymentReceived);
|
||||
confirmFiatReceivedButton = bucket.button;
|
||||
statusProgressIndicator = bucket.progressIndicator;
|
||||
statusLabel = bucket.label;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,7 +133,7 @@ public class StartFiatView extends TradeStepDetailsView {
|
||||
primaryIdTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "IBAN:").textFieldWithCopyIcon;
|
||||
secondaryIdTextField = getAndAddLabelTextFieldWithCopyIconPair(gridPane, gridRow++, "BIC:").textFieldWithCopyIcon;
|
||||
paymentsInfoDisplay = getAndAddInfoDisplay(gridPane, gridRow++, "infoDisplay", this::onOpenHelp);
|
||||
ButtonWithProgressIndicatorAndLabelBucket bucket = getAndAddButtonWithStatus(gridPane, gridRow++, "Payment started", this::onPaymentStarted);
|
||||
ButtonWithProgressIndicatorAndLabel bucket = getAndAddButtonWithStatus(gridPane, gridRow++, "Payment started", this::onPaymentStarted);
|
||||
paymentStartedButton = bucket.button;
|
||||
statusProgressIndicator = bucket.progressIndicator;
|
||||
statusLabel = bucket.label;
|
||||
|
@ -39,7 +39,7 @@ public class TradeWizardItem extends Button {
|
||||
setMouseTransparent(true);
|
||||
setText(title);
|
||||
setPrefHeight(40);
|
||||
setPrefWidth(270);
|
||||
setPrefWidth(340);
|
||||
setPadding(new Insets(0, 20, 0, 10));
|
||||
setAlignment(Pos.CENTER_LEFT);
|
||||
setDisabled();
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.gui.main.portfolio.pendingtrades.steps;
|
||||
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
|
||||
import javafx.scene.control.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static io.bitsquare.gui.util.ComponentBuilder.*;
|
||||
|
||||
public class WaitPayoutFinalizedView extends TradeStepDetailsView {
|
||||
private static final Logger log = LoggerFactory.getLogger(WaitPayoutFinalizedView.class);
|
||||
|
||||
private Label infoLabel;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public WaitPayoutFinalizedView(PendingTradesViewModel model) {
|
||||
super(model);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate() {
|
||||
super.activate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
public void setInfoLabelText(String text) {
|
||||
if (infoLabel != null)
|
||||
infoLabel.setText(text);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void buildGridEntries() {
|
||||
getAndAddTitledGroupBg(gridPane, gridRow, 1, "Information");
|
||||
infoLabel = getAndAddInfoLabel(gridPane, gridRow++, Layout.FIRST_ROW_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ public class WaitPayoutLockTimeView extends TradeStepDetailsView {
|
||||
private Label infoLabel;
|
||||
private TextField timeTextField;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, Initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -114,6 +113,7 @@ public class WaitPayoutLockTimeView extends TradeStepDetailsView {
|
||||
timeTextField.setText(model.getUnlockDate(missingBlocks));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Build view
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -195,7 +195,7 @@ public class ComponentBuilder {
|
||||
return button;
|
||||
}
|
||||
|
||||
public static ButtonWithProgressIndicatorAndLabelBucket getAndAddButtonWithStatus(GridPane gridPane,
|
||||
public static ButtonWithProgressIndicatorAndLabel getAndAddButtonWithStatus(GridPane gridPane,
|
||||
int rowIndex,
|
||||
String ButtonTitle,
|
||||
EventHandler<ActionEvent> onActionHandler) {
|
||||
@ -220,7 +220,7 @@ public class ComponentBuilder {
|
||||
GridPane.setMargin(hBox, new Insets(15, 0, 40, 0));
|
||||
gridPane.getChildren().add(hBox);
|
||||
|
||||
return new ButtonWithProgressIndicatorAndLabelBucket(button, progressIndicator, label);
|
||||
return new ButtonWithProgressIndicatorAndLabel(button, progressIndicator, label);
|
||||
}
|
||||
|
||||
public static class LabelTextFieldPair {
|
||||
@ -263,12 +263,12 @@ public class ComponentBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ButtonWithProgressIndicatorAndLabelBucket {
|
||||
public static class ButtonWithProgressIndicatorAndLabel {
|
||||
public Button button;
|
||||
public ProgressIndicator progressIndicator;
|
||||
public Label label;
|
||||
|
||||
public ButtonWithProgressIndicatorAndLabelBucket(Button button, ProgressIndicator progressIndicator, Label label) {
|
||||
public ButtonWithProgressIndicatorAndLabel(Button button, ProgressIndicator progressIndicator, Label label) {
|
||||
this.button = button;
|
||||
this.progressIndicator = progressIndicator;
|
||||
this.label = label;
|
||||
|
Loading…
x
Reference in New Issue
Block a user