Second trade process basically working (WIP)

This commit is contained in:
Manfred Karrer 2015-04-01 23:07:47 +02:00
parent 37a358b716
commit 21fb0920c8
70 changed files with 1071 additions and 583 deletions

View file

@ -61,23 +61,23 @@ import static com.google.inject.internal.util.$Preconditions.*;
Deposit tx: Deposit tx:
To keep the multiple partial deposit tx consistent with the final deposit tx used for publishing To keep the multiple partial deposit tx consistent with the final deposit tx used for publishing
we use always use offerers in/outputs first then takers in/outputs. we use always use buyers in/outputs first then sellers in/outputs.
IN[0] offerer (mandatory) e.g. 0.1 BTC IN[0] buyer (mandatory) e.g. 0.1 BTC
IN[...] optional additional offerer inputs (normally never used as we pay from trade fee tx and always have 1 output there) IN[...] optional additional buyer inputs (normally never used as we pay from trade fee tx and always have 1 output there)
IN[...] taker (mandatory) e.g. 1.1001 BTC IN[...] seller (mandatory) e.g. 1.1001 BTC
IN[...] optional additional taker inputs (normally never used as we pay from trade fee tx and always have 1 output there) IN[...] optional additional seller inputs (normally never used as we pay from trade fee tx and always have 1 output there)
OUT[0] Multisig output (include tx fee for payout tx) e.g. 1.2001 OUT[0] Multisig output (include tx fee for payout tx) e.g. 1.2001
OUT[1] offerer change (normally never used as we pay from trade fee tx and always have 1 output there) OUT[1] buyer change (normally never used as we pay from trade fee tx and always have 1 output there)
OUT[...] optional additional offerer outputs (supported but no use case yet for that) OUT[...] optional additional buyer outputs (supported but no use case yet for that)
OUT[...] taker change (normally never used as we pay from trade fee tx and always have 1 output there) OUT[...] seller change (normally never used as we pay from trade fee tx and always have 1 output there)
OUT[...] optional additional taker outputs (supported but no use case yet for that) OUT[...] optional additional seller outputs (supported but no use case yet for that)
FEE tx fee 0.0001 BTC FEE tx fee 0.0001 BTC
Payout tx: Payout tx:
IN[0] Multisig output form deposit Tx (signed by offerer and trader) IN[0] Multisig output form deposit Tx (signed by buyer and trader)
OUT[0] Offerer payout address OUT[0] Buyer payout address
OUT[1] Taker payout address OUT[1] Seller payout address
*/ */
public class TradeWalletService { public class TradeWalletService {
@ -103,7 +103,7 @@ public class TradeWalletService {
// Trade fee // Trade fee
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public Transaction createOfferFeeTx(AddressEntry offererAddressEntry) throws InsufficientMoneyException { public Transaction createOfferFeeTx(AddressEntry buyerAddressEntry) throws InsufficientMoneyException {
Transaction createOfferFeeTx = new Transaction(params); Transaction createOfferFeeTx = new Transaction(params);
Coin fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE); Coin fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
createOfferFeeTx.addOutput(fee, feePolicy.getAddressForCreateOfferFee()); createOfferFeeTx.addOutput(fee, feePolicy.getAddressForCreateOfferFee());
@ -111,8 +111,8 @@ public class TradeWalletService {
sendRequest.shuffleOutputs = false; sendRequest.shuffleOutputs = false;
// we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to // we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to
// wait for 1 confirmation) // wait for 1 confirmation)
sendRequest.coinSelector = new AddressBasedCoinSelector(params, offererAddressEntry, true); sendRequest.coinSelector = new AddressBasedCoinSelector(params, buyerAddressEntry, true);
sendRequest.changeAddress = offererAddressEntry.getAddress(); sendRequest.changeAddress = buyerAddressEntry.getAddress();
wallet.completeTx(sendRequest); wallet.completeTx(sendRequest);
printTxWithInputs("createOfferFeeTx", createOfferFeeTx); printTxWithInputs("createOfferFeeTx", createOfferFeeTx);
return createOfferFeeTx; return createOfferFeeTx;
@ -123,7 +123,7 @@ public class TradeWalletService {
Futures.addCallback(future, callback); Futures.addCallback(future, callback);
} }
public Transaction createTakeOfferFeeTx(AddressEntry takerAddressEntry) throws InsufficientMoneyException { public Transaction createTakeOfferFeeTx(AddressEntry sellerAddressEntry) throws InsufficientMoneyException {
Transaction takeOfferFeeTx = new Transaction(params); Transaction takeOfferFeeTx = new Transaction(params);
Coin fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE); Coin fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
takeOfferFeeTx.addOutput(fee, feePolicy.getAddressForTakeOfferFee()); takeOfferFeeTx.addOutput(fee, feePolicy.getAddressForTakeOfferFee());
@ -132,8 +132,8 @@ public class TradeWalletService {
sendRequest.shuffleOutputs = false; sendRequest.shuffleOutputs = false;
// we allow spending of unconfirmed takeOfferFeeTx (double spend risk is low and usability would suffer if we need to // we allow spending of unconfirmed takeOfferFeeTx (double spend risk is low and usability would suffer if we need to
// wait for 1 confirmation) // wait for 1 confirmation)
sendRequest.coinSelector = new AddressBasedCoinSelector(params, takerAddressEntry, true); sendRequest.coinSelector = new AddressBasedCoinSelector(params, sellerAddressEntry, true);
sendRequest.changeAddress = takerAddressEntry.getAddress(); sendRequest.changeAddress = sellerAddressEntry.getAddress();
wallet.completeTx(sendRequest); wallet.completeTx(sendRequest);
printTxWithInputs("takeOfferFeeTx", takeOfferFeeTx); printTxWithInputs("takeOfferFeeTx", takeOfferFeeTx);
return takeOfferFeeTx; return takeOfferFeeTx;
@ -162,22 +162,22 @@ public class TradeWalletService {
} }
public Result createOffererDepositTxInputs(Coin offererInputAmount, AddressEntry offererAddressEntry) throws public Result createDepositTxInputs(Coin buyerInputAmount, AddressEntry buyerAddressEntry) throws
TransactionVerificationException, WalletException { TransactionVerificationException, WalletException {
log.trace("createOffererDepositTxInputs called"); log.trace("createDepositTxInputs called");
log.trace("offererInputAmount " + offererInputAmount.toFriendlyString()); log.trace("buyerInputAmount " + buyerInputAmount.toFriendlyString());
log.trace("offererAddressEntry " + offererAddressEntry.toString()); log.trace("buyerAddressEntry " + buyerAddressEntry.toString());
Coin balance = getBalance(wallet.calculateAllSpendCandidates(true), offererAddressEntry.getAddress()); Coin balance = getBalance(wallet.calculateAllSpendCandidates(true), buyerAddressEntry.getAddress());
log.trace("balance " + balance.toFriendlyString()); log.trace("balance " + balance.toFriendlyString());
// We pay the tx fee 2 times to the deposit tx: // We pay the tx fee 2 times to the deposit tx:
// 1. Will be spent when publishing the deposit tx (paid by offerer) // 1. Will be spent when publishing the deposit tx (paid by buyer)
// 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction // 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction
// The fee for the payout will be paid by the taker. // The fee for the payout will be paid by the seller.
// offererInputAmount includes the tx fee. So we subtract the fee to get the dummyOutputAmount. // buyerInputAmount includes the tx fee. So we subtract the fee to get the dummyOutputAmount.
Coin dummyOutputAmount = offererInputAmount.subtract(FeePolicy.TX_FEE); Coin dummyOutputAmount = buyerInputAmount.subtract(FeePolicy.TX_FEE);
Transaction dummyTX = new Transaction(params); Transaction dummyTX = new Transaction(params);
// The output is just used to get the right inputs and change outputs, so we use an anonymous ECKey, as it will never be used for anything. // The output is just used to get the right inputs and change outputs, so we use an anonymous ECKey, as it will never be used for anything.
@ -188,7 +188,7 @@ public class TradeWalletService {
// Fin the needed inputs to pay the output, optional add change output. // Fin the needed inputs to pay the output, optional add change output.
// Normally only 1 input and no change output is used, but we support multiple inputs and outputs. Our spending transaction output is from the create // Normally only 1 input and no change output is used, but we support multiple inputs and outputs. Our spending transaction output is from the create
// offer fee payment. In future changes (in case of no offer fee) multiple inputs might become used. // offer fee payment. In future changes (in case of no offer fee) multiple inputs might become used.
addAvailableInputsAndChangeOutputs(dummyTX, offererAddressEntry); addAvailableInputsAndChangeOutputs(dummyTX, buyerAddressEntry);
// The completeTx() call signs the input, but we don't want to pass over signed tx inputs // The completeTx() call signs the input, but we don't want to pass over signed tx inputs
// But to be safe and to support future changes (in case of no offer fee) we handle potential multiple inputs // But to be safe and to support future changes (in case of no offer fee) we handle potential multiple inputs
@ -198,10 +198,10 @@ public class TradeWalletService {
// The created tx looks like: // The created tx looks like:
/* /*
IN[0] any input > offererInputAmount (including tx fee) (unsigned) IN[0] any input > buyerInputAmount (including tx fee) (unsigned)
IN[1...n] optional inputs supported, but currently there is just 1 input (unsigned) IN[1...n] optional inputs supported, but currently there is just 1 input (unsigned)
OUT[0] dummyOutputAmount (offererInputAmount - tx fee) OUT[0] dummyOutputAmount (buyerInputAmount - tx fee)
OUT[1] Optional Change = offererInputAmount - dummyOutputAmount - tx fee OUT[1] Optional Change = buyerInputAmount - dummyOutputAmount - tx fee
OUT[2...n] optional more outputs are supported, but currently there is just max. 1 optional change output OUT[2...n] optional more outputs are supported, but currently there is just max. 1 optional change output
*/ */
@ -210,7 +210,7 @@ public class TradeWalletService {
List<TransactionOutput> connectedOutputsForAllInputs = dummyTX.getInputs().stream().map(TransactionInput::getConnectedOutput) List<TransactionOutput> connectedOutputsForAllInputs = dummyTX.getInputs().stream().map(TransactionInput::getConnectedOutput)
.collect(Collectors.toList()); .collect(Collectors.toList());
// Only save offerer outputs, the dummy output (index 1) is ignored // Only save buyer outputs, the dummy output (index 1) is ignored
List<TransactionOutput> outputs = new ArrayList<>(); List<TransactionOutput> outputs = new ArrayList<>();
for (int i = 1; i < dummyTX.getOutputs().size(); i++) { for (int i = 1; i < dummyTX.getOutputs().size(); i++) {
outputs.add(dummyTX.getOutputs().get(i)); outputs.add(dummyTX.getOutputs().get(i));
@ -219,150 +219,148 @@ public class TradeWalletService {
return new Result(connectedOutputsForAllInputs, outputs); return new Result(connectedOutputsForAllInputs, outputs);
} }
public Result takerCreatesAndSignsDepositTx(Coin takerInputAmount, public Result createAndSignDepositTx(Coin sellerInputAmount,
Coin msOutputAmount, Coin msOutputAmount,
List<TransactionOutput> offererConnectedOutputsForAllInputs, List<TransactionOutput> buyerConnectedOutputsForAllInputs,
List<TransactionOutput> offererOutputs, List<TransactionOutput> buyerOutputs,
AddressEntry takerAddressInfo, AddressEntry sellerAddressInfo,
byte[] offererPubKey, byte[] buyerPubKey,
byte[] takerPubKey, byte[] sellerPubKey,
byte[] arbitratorPubKey) throws SigningException, TransactionVerificationException, WalletException { byte[] arbitratorPubKey) throws SigningException, TransactionVerificationException, WalletException {
log.trace("takerCreatesAndSignsDepositTx called"); log.trace("createAndSignDepositTx called");
log.trace("takerInputAmount " + takerInputAmount.toFriendlyString()); log.trace("sellerInputAmount " + sellerInputAmount.toFriendlyString());
log.trace("msOutputAmount " + msOutputAmount.toFriendlyString()); log.trace("msOutputAmount " + msOutputAmount.toFriendlyString());
log.trace("offererConnectedOutputsForAllInputs " + offererConnectedOutputsForAllInputs.toString()); log.trace("buyerConnectedOutputsForAllInputs " + buyerConnectedOutputsForAllInputs.toString());
log.trace("offererOutputs " + offererOutputs.toString()); log.trace("buyerOutputs " + buyerOutputs.toString());
log.trace("takerAddressInfo " + takerAddressInfo.toString()); log.trace("sellerAddressInfo " + sellerAddressInfo.toString());
log.trace("offererPubKey " + ECKey.fromPublicOnly(offererPubKey).toString()); log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("takerPubKey " + ECKey.fromPublicOnly(takerPubKey).toString()); log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString()); log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
checkArgument(offererConnectedOutputsForAllInputs.size() > 0); checkArgument(buyerConnectedOutputsForAllInputs.size() > 0);
if (!Utils.HEX.encode(takerAddressInfo.getPubKey()).equals(Utils.HEX.encode(takerPubKey)))
throw new SigningException("TakerPubKey not matching key pair from addressEntry");
// First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx. // First we construct a dummy TX to get the inputs and outputs we want to use for the real deposit tx.
Transaction dummyTx = new Transaction(params); Transaction dummyTx = new Transaction(params);
Coin dummyOutputAmount = takerInputAmount.subtract(FeePolicy.TX_FEE); Coin dummyOutputAmount = sellerInputAmount.subtract(FeePolicy.TX_FEE);
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, dummyOutputAmount, new ECKey().toAddress(params)); TransactionOutput dummyOutput = new TransactionOutput(params, dummyTx, dummyOutputAmount, new ECKey().toAddress(params));
dummyTx.addOutput(dummyOutput); dummyTx.addOutput(dummyOutput);
addAvailableInputsAndChangeOutputs(dummyTx, takerAddressInfo); addAvailableInputsAndChangeOutputs(dummyTx, sellerAddressInfo);
List<TransactionInput> takerInputs = dummyTx.getInputs(); List<TransactionInput> sellererInputs = dummyTx.getInputs();
List<TransactionOutput> takerOutputs = new ArrayList<>(); List<TransactionOutput> sellerOutputs = new ArrayList<>();
// we store optional change outputs (ignoring dummyOutput) // we store optional change outputs (ignoring dummyOutput)
for (int i = 1; i < dummyTx.getOutputs().size(); i++) { for (int i = 1; i < dummyTx.getOutputs().size(); i++) {
takerOutputs.add(dummyTx.getOutput(i)); sellerOutputs.add(dummyTx.getOutput(i));
} }
// Now we construct the real deposit tx // Now we construct the real deposit tx
Transaction preparedDepositTx = new Transaction(params); Transaction preparedDepositTx = new Transaction(params);
// Add offerer inputs (normally its just 1 input) // Add buyer inputs (normally its just 1 input)
for (TransactionOutput connectedOutputForInput : offererConnectedOutputsForAllInputs) { for (TransactionOutput connectedOutputForInput : buyerConnectedOutputsForAllInputs) {
TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction()); TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction());
TransactionInput transactionInput = new TransactionInput(params, preparedDepositTx, new byte[]{}, outPoint, connectedOutputForInput.getValue()); TransactionInput transactionInput = new TransactionInput(params, preparedDepositTx, new byte[]{}, outPoint, connectedOutputForInput.getValue());
preparedDepositTx.addInput(transactionInput); preparedDepositTx.addInput(transactionInput);
} }
// Add taker inputs // Add seller inputs
List<TransactionOutput> takerConnectedOutputsForAllInputs = new ArrayList<>(); List<TransactionOutput> sellerConnectedOutputsForAllInputs = new ArrayList<>();
for (TransactionInput input : takerInputs) { for (TransactionInput input : sellererInputs) {
preparedDepositTx.addInput(input); preparedDepositTx.addInput(input);
takerConnectedOutputsForAllInputs.add(input.getConnectedOutput()); sellerConnectedOutputsForAllInputs.add(input.getConnectedOutput());
} }
// Add MultiSig output // Add MultiSig output
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
// Tx fee for deposit tx will be paid by offerer. // Tx fee for deposit tx will be paid by buyer.
TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, preparedDepositTx, msOutputAmount, p2SHMultiSigOutputScript.getProgram()); TransactionOutput p2SHMultiSigOutput = new TransactionOutput(params, preparedDepositTx, msOutputAmount, p2SHMultiSigOutputScript.getProgram());
preparedDepositTx.addOutput(p2SHMultiSigOutput); preparedDepositTx.addOutput(p2SHMultiSigOutput);
// Add optional offerer outputs // Add optional buyer outputs
offererOutputs.forEach(preparedDepositTx::addOutput); buyerOutputs.forEach(preparedDepositTx::addOutput);
Coin takersSpendingAmount = Coin.ZERO; Coin sellersSpendingAmount = Coin.ZERO;
// Add optional taker outputs // Add optional seller outputs
for (TransactionOutput output : takerOutputs) { for (TransactionOutput output : sellerOutputs) {
preparedDepositTx.addOutput(output); preparedDepositTx.addOutput(output);
// subtract change amount // subtract change amount
takersSpendingAmount = takersSpendingAmount.subtract(output.getValue()); sellersSpendingAmount = sellersSpendingAmount.subtract(output.getValue());
} }
// Sign inputs (start after offerer inputs) // Sign inputs (start after buyer inputs)
for (int i = offererConnectedOutputsForAllInputs.size(); i < preparedDepositTx.getInputs().size(); i++) { for (int i = buyerConnectedOutputsForAllInputs.size(); i < preparedDepositTx.getInputs().size(); i++) {
TransactionInput input = preparedDepositTx.getInput(i); TransactionInput input = preparedDepositTx.getInput(i);
signInput(preparedDepositTx, input, i); signInput(preparedDepositTx, input, i);
checkScriptSig(preparedDepositTx, input, i); checkScriptSig(preparedDepositTx, input, i);
// add up spending amount // add up spending amount
assert input.getConnectedOutput() != null; assert input.getConnectedOutput() != null;
takersSpendingAmount = takersSpendingAmount.add(input.getConnectedOutput().getValue()); sellersSpendingAmount = sellersSpendingAmount.add(input.getConnectedOutput().getValue());
} }
if (takerInputAmount.compareTo(takersSpendingAmount) != 0) if (sellerInputAmount.compareTo(sellersSpendingAmount) != 0)
throw new TransactionVerificationException("Takers input amount does not match required value."); throw new TransactionVerificationException("Sellers input amount does not match required value.");
verifyTransaction(preparedDepositTx); verifyTransaction(preparedDepositTx);
printTxWithInputs("preparedDepositTx", preparedDepositTx); printTxWithInputs("preparedDepositTx", preparedDepositTx);
return new Result(preparedDepositTx, takerConnectedOutputsForAllInputs, takerOutputs); return new Result(preparedDepositTx, sellerConnectedOutputsForAllInputs, sellerOutputs);
} }
public void signAndPublishDepositTx(Transaction preparedDepositTx, public void signAndPublishDepositTx(Transaction preparedDepositTx,
List<TransactionOutput> offererConnectedOutputsForAllInputs, List<TransactionOutput> buyerConnectedOutputsForAllInputs,
List<TransactionOutput> takerConnectedOutputsForAllInputs, List<TransactionOutput> sellerConnectedOutputsForAllInputs,
List<TransactionOutput> buyerOutputs, List<TransactionOutput> buyerOutputs,
Coin buyerInputAmount, Coin buyerInputAmount,
byte[] offererPubKey, byte[] buyerPubKey,
byte[] takerPubKey, byte[] sellerPubKey,
byte[] arbitratorPubKey, byte[] arbitratorPubKey,
FutureCallback<Transaction> callback) throws SigningException, TransactionVerificationException, FutureCallback<Transaction> callback) throws SigningException, TransactionVerificationException,
WalletException { WalletException {
log.trace("offererSignsAndPublishTx called"); log.trace("signAndPublishDepositTx called");
log.trace("preparedDepositTx " + preparedDepositTx.toString()); log.trace("preparedDepositTx " + preparedDepositTx.toString());
log.trace("offererConnectedOutputsForAllInputs " + offererConnectedOutputsForAllInputs.toString()); log.trace("buyerConnectedOutputsForAllInputs " + buyerConnectedOutputsForAllInputs.toString());
log.trace("takerConnectedOutputsForAllInputs " + takerConnectedOutputsForAllInputs.toString()); log.trace("sellerConnectedOutputsForAllInputs " + sellerConnectedOutputsForAllInputs.toString());
log.trace("buyerOutputs " + buyerOutputs.toString()); log.trace("buyerOutputs " + buyerOutputs.toString());
log.trace("buyerInputAmount " + buyerInputAmount.toFriendlyString()); log.trace("buyerInputAmount " + buyerInputAmount.toFriendlyString());
log.trace("offererPubKey " + ECKey.fromPublicOnly(offererPubKey).toString()); log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("takerPubKey " + ECKey.fromPublicOnly(takerPubKey).toString()); log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString()); log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
checkArgument(offererConnectedOutputsForAllInputs.size() > 0); checkArgument(buyerConnectedOutputsForAllInputs.size() > 0);
checkArgument(takerConnectedOutputsForAllInputs.size() > 0); checkArgument(sellerConnectedOutputsForAllInputs.size() > 0);
// Check if takers Multisig script is identical to mine // Check if sellers Multisig script is identical to mine
Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(offererPubKey, takerPubKey, arbitratorPubKey); Script p2SHMultiSigOutputScript = getP2SHMultiSigOutputScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
if (!preparedDepositTx.getOutput(0).getScriptPubKey().equals(p2SHMultiSigOutputScript)) if (!preparedDepositTx.getOutput(0).getScriptPubKey().equals(p2SHMultiSigOutputScript))
throw new TransactionVerificationException("Takers p2SHMultiSigOutputScript does not match to my p2SHMultiSigOutputScript"); throw new TransactionVerificationException("Sellers p2SHMultiSigOutputScript does not match to my p2SHMultiSigOutputScript");
// The outpoints are not available from the serialized preparedDepositTx, so we cannot use that tx directly, but we use it to construct a new // The outpoints are not available from the serialized preparedDepositTx, so we cannot use that tx directly, but we use it to construct a new
// depositTx // depositTx
Transaction depositTx = new Transaction(params); Transaction depositTx = new Transaction(params);
// Add offerer inputs // Add buyer inputs
Coin offererSpendingAmount = Coin.ZERO; Coin buyerSpendingAmount = Coin.ZERO;
for (TransactionOutput connectedOutputForInput : offererConnectedOutputsForAllInputs) { for (TransactionOutput connectedOutputForInput : buyerConnectedOutputsForAllInputs) {
TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction()); TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction());
TransactionInput input = new TransactionInput(params, depositTx, new byte[]{}, outPoint, connectedOutputForInput.getValue()); TransactionInput input = new TransactionInput(params, depositTx, new byte[]{}, outPoint, connectedOutputForInput.getValue());
depositTx.addInput(input); depositTx.addInput(input);
// add up spending amount // add up spending amount
assert input.getConnectedOutput() != null; assert input.getConnectedOutput() != null;
offererSpendingAmount = offererSpendingAmount.add(input.getConnectedOutput().getValue()); buyerSpendingAmount = buyerSpendingAmount.add(input.getConnectedOutput().getValue());
} }
// Add taker inputs and apply signature // Add seller inputs and apply signature
for (TransactionOutput connectedOutputForInput : takerConnectedOutputsForAllInputs) { for (TransactionOutput connectedOutputForInput : sellerConnectedOutputsForAllInputs) {
TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction()); TransactionOutPoint outPoint = new TransactionOutPoint(params, connectedOutputForInput.getIndex(), connectedOutputForInput.getParentTransaction());
// We grab the signature from the preparedDepositTx and apply it to the new tx input // We grab the signature from the preparedDepositTx and apply it to the new tx input
TransactionInput takerInput = preparedDepositTx.getInputs().get(offererConnectedOutputsForAllInputs.size()); TransactionInput sellerInput = preparedDepositTx.getInputs().get(buyerConnectedOutputsForAllInputs.size());
byte[] scriptProgram = takerInput.getScriptSig().getProgram(); byte[] scriptProgram = sellerInput.getScriptSig().getProgram();
if (scriptProgram.length == 0) if (scriptProgram.length == 0)
throw new TransactionVerificationException("Inputs from taker not singed."); throw new TransactionVerificationException("Inputs from seller not singed.");
TransactionInput transactionInput = new TransactionInput(params, depositTx, scriptProgram, outPoint, connectedOutputForInput.getValue()); TransactionInput transactionInput = new TransactionInput(params, depositTx, scriptProgram, outPoint, connectedOutputForInput.getValue());
depositTx.addInput(transactionInput); depositTx.addInput(transactionInput);
@ -372,7 +370,7 @@ public class TradeWalletService {
preparedDepositTx.getOutputs().forEach(depositTx::addOutput); preparedDepositTx.getOutputs().forEach(depositTx::addOutput);
// Sign inputs // Sign inputs
for (int i = 0; i < offererConnectedOutputsForAllInputs.size(); i++) { for (int i = 0; i < buyerConnectedOutputsForAllInputs.size(); i++) {
TransactionInput input = depositTx.getInput(i); TransactionInput input = depositTx.getInput(i);
signInput(depositTx, input, i); signInput(depositTx, input, i);
checkScriptSig(depositTx, input, i); checkScriptSig(depositTx, input, i);
@ -380,11 +378,11 @@ public class TradeWalletService {
// subtract change amount // subtract change amount
for (int i = 1; i < buyerOutputs.size() + 1; i++) { for (int i = 1; i < buyerOutputs.size() + 1; i++) {
offererSpendingAmount = offererSpendingAmount.subtract(depositTx.getOutput(i).getValue()); buyerSpendingAmount = buyerSpendingAmount.subtract(depositTx.getOutput(i).getValue());
} }
if (buyerInputAmount.compareTo(offererSpendingAmount) != 0) if (buyerInputAmount.compareTo(buyerSpendingAmount) != 0)
throw new TransactionVerificationException("Offerers input amount does not match required value."); throw new TransactionVerificationException("Buyers input amount does not match required value.");
verifyTransaction(depositTx); verifyTransaction(depositTx);
checkWalletConsistency(); checkWalletConsistency();
@ -417,94 +415,88 @@ public class TradeWalletService {
} }
public byte[] createAndSignPayoutTx(Transaction depositTx, public byte[] createAndSignPayoutTx(Transaction depositTx,
Coin offererPayoutAmount, Coin buyerPayoutAmount,
Coin takerPayoutAmount, Coin sellerPayoutAmount,
AddressEntry buyerAddressEntry, AddressEntry buyerAddressEntry,
String sellerPayoutAddressString, String sellerPayoutAddressString,
byte[] offererPubKey, byte[] buyerPubKey,
byte[] takerPubKey, byte[] sellerPubKey,
byte[] arbitratorPubKey) byte[] arbitratorPubKey)
throws AddressFormatException, TransactionVerificationException, SigningException { throws AddressFormatException, TransactionVerificationException, SigningException {
log.trace("offererCreatesAndSignsPayoutTx called"); log.trace("createAndSignPayoutTx called");
log.trace("depositTx " + depositTx.toString()); log.trace("depositTx " + depositTx.toString());
log.trace("offererPayoutAmount " + offererPayoutAmount.toFriendlyString()); log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.trace("takerPayoutAmount " + takerPayoutAmount.toFriendlyString()); log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.trace("buyerAddressEntry " + buyerAddressEntry.toString()); log.trace("buyerAddressEntry " + buyerAddressEntry.toString());
log.trace("sellerPayoutAddressString " + sellerPayoutAddressString); log.trace("sellerPayoutAddressString " + sellerPayoutAddressString);
log.trace("offererPubKey " + ECKey.fromPublicOnly(offererPubKey).toString()); log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("takerPubKey " + ECKey.fromPublicOnly(takerPubKey).toString()); log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString()); log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
if (!Utils.HEX.encode(buyerAddressEntry.getPubKey()).equals(Utils.HEX.encode(offererPubKey)))
throw new SigningException("OffererPubKey not matching key pair from addressEntry");
Transaction preparedPayoutTx = createPayoutTx(depositTx, Transaction preparedPayoutTx = createPayoutTx(depositTx,
offererPayoutAmount, buyerPayoutAmount,
takerPayoutAmount, sellerPayoutAmount,
buyerAddressEntry.getAddressString(), buyerAddressEntry.getAddressString(),
sellerPayoutAddressString); sellerPayoutAddressString);
// MS redeemScript // MS redeemScript
Script redeemScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey); Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false); Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature offererSignature = buyerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised(); ECKey.ECDSASignature buyerSignature = buyerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
verifyTransaction(preparedPayoutTx); verifyTransaction(preparedPayoutTx);
printTxWithInputs("preparedPayoutTx", preparedPayoutTx); printTxWithInputs("preparedPayoutTx", preparedPayoutTx);
log.trace("offererSignature r " + offererSignature.toCanonicalised().r.toString()); log.trace("buyerSignature r " + buyerSignature.toCanonicalised().r.toString());
log.trace("offererSignature s " + offererSignature.toCanonicalised().s.toString()); log.trace("buyerSignature s " + buyerSignature.toCanonicalised().s.toString());
Sha256Hash hashForSignature = preparedPayoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1); Sha256Hash hashForSignature = preparedPayoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1);
log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes())); log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes()));
return offererSignature.encodeToDER(); return buyerSignature.encodeToDER();
} }
public void signAndPublishPayoutTx(Transaction depositTx, public void signAndPublishPayoutTx(Transaction depositTx,
byte[] buyerSignature, byte[] buyerSignature,
Coin offererPayoutAmount, Coin buyerPayoutAmount,
Coin takerPayoutAmount, Coin sellerPayoutAmount,
String buyerAddressString, String buyerAddressString,
AddressEntry sellerAddressEntry, AddressEntry sellerAddressEntry,
byte[] offererPubKey, byte[] buyerPubKey,
byte[] takerPubKey, byte[] sellerPubKey,
byte[] arbitratorPubKey, byte[] arbitratorPubKey,
FutureCallback<Transaction> callback) FutureCallback<Transaction> callback)
throws AddressFormatException, TransactionVerificationException, WalletException, SigningException { throws AddressFormatException, TransactionVerificationException, WalletException, SigningException {
log.trace("takerSignsAndPublishPayoutTx called"); log.trace("signAndPublishPayoutTx called");
log.trace("depositTx " + depositTx.toString()); log.trace("depositTx " + depositTx.toString());
log.trace("buyerSignature r " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).r.toString()); log.trace("buyerSignature r " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).r.toString());
log.trace("buyerSignature s " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).s.toString()); log.trace("buyerSignature s " + ECKey.ECDSASignature.decodeFromDER(buyerSignature).s.toString());
log.trace("offererPayoutAmount " + offererPayoutAmount.toFriendlyString()); log.trace("buyerPayoutAmount " + buyerPayoutAmount.toFriendlyString());
log.trace("takerPayoutAmount " + takerPayoutAmount.toFriendlyString()); log.trace("sellerPayoutAmount " + sellerPayoutAmount.toFriendlyString());
log.trace("buyerAddressString " + buyerAddressString); log.trace("buyerAddressString " + buyerAddressString);
log.trace("sellerAddressEntry " + sellerAddressEntry); log.trace("sellerAddressEntry " + sellerAddressEntry);
log.trace("offererPubKey " + ECKey.fromPublicOnly(offererPubKey).toString()); log.trace("buyerPubKey " + ECKey.fromPublicOnly(buyerPubKey).toString());
log.trace("takerPubKey " + ECKey.fromPublicOnly(takerPubKey).toString()); log.trace("sellerPubKey " + ECKey.fromPublicOnly(sellerPubKey).toString());
log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString()); log.trace("arbitratorPubKey " + ECKey.fromPublicOnly(arbitratorPubKey).toString());
if (!Utils.HEX.encode(sellerAddressEntry.getPubKey()).equals(Utils.HEX.encode(takerPubKey)))
throw new SigningException("TakerPubKey not matching key pair from addressEntry");
Transaction payoutTx = createPayoutTx(depositTx, Transaction payoutTx = createPayoutTx(depositTx,
offererPayoutAmount, buyerPayoutAmount,
takerPayoutAmount, sellerPayoutAmount,
buyerAddressString, buyerAddressString,
sellerAddressEntry.getAddressString()); sellerAddressEntry.getAddressString());
Script redeemScript = getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey); Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false); Sha256Hash sigHash = payoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature takerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised(); ECKey.ECDSASignature sellerSignature = sellerAddressEntry.getKeyPair().sign(sigHash).toCanonicalised();
log.trace("takerSignature r " + takerSignature.r.toString()); log.trace("sellerSignature r " + sellerSignature.r.toString());
log.trace("takerSignature s " + takerSignature.s.toString()); log.trace("sellerSignature s " + sellerSignature.s.toString());
Sha256Hash hashForSignature = payoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1); Sha256Hash hashForSignature = payoutTx.hashForSignature(0, redeemScript.getProgram(), (byte) 1);
log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes())); log.trace("hashForSignature " + Utils.HEX.encode(hashForSignature.getBytes()));
TransactionSignature offererTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature), TransactionSignature buyerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature),
Transaction.SigHash.ALL, false); Transaction.SigHash.ALL, false);
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false); TransactionSignature sellerTxSig = new TransactionSignature(sellerSignature, Transaction.SigHash.ALL, false);
// Take care of order of signatures. See comment below at getMultiSigRedeemScript // Take care of order of signatures. See comment below at getMultiSigRedeemScript
Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(takerTxSig, offererTxSig), redeemScript); Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);
TransactionInput input = payoutTx.getInput(0); TransactionInput input = payoutTx.getInput(0);
input.setScriptSig(inputScript); input.setScriptSig(inputScript);
@ -533,30 +525,30 @@ public class TradeWalletService {
// Furthermore the executed list is reversed to the provided. // Furthermore the executed list is reversed to the provided.
// Best practice is to provide the list sorted by the least probable successful candidates first (arbitrator is first -> will be last in execution loop, so // Best practice is to provide the list sorted by the least probable successful candidates first (arbitrator is first -> will be last in execution loop, so
// avoiding unneeded expensive ECKey.verify calls) // avoiding unneeded expensive ECKey.verify calls)
private Script getMultiSigRedeemScript(byte[] offererPubKey, byte[] takerPubKey, byte[] arbitratorPubKey) { private Script getMultiSigRedeemScript(byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) {
ECKey offererKey = ECKey.fromPublicOnly(offererPubKey); ECKey buyerKey = ECKey.fromPublicOnly(buyerPubKey);
ECKey takerKey = ECKey.fromPublicOnly(takerPubKey); ECKey sellerKey = ECKey.fromPublicOnly(sellerPubKey);
ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey); ECKey arbitratorKey = ECKey.fromPublicOnly(arbitratorPubKey);
// Take care of sorting! // Take care of sorting!
List<ECKey> keys = ImmutableList.of(arbitratorKey, takerKey, offererKey); List<ECKey> keys = ImmutableList.of(arbitratorKey, sellerKey, buyerKey);
return ScriptBuilder.createMultiSigOutputScript(2, keys); return ScriptBuilder.createMultiSigOutputScript(2, keys);
} }
private Script getP2SHMultiSigOutputScript(byte[] offererPubKey, byte[] takerPubKey, byte[] arbitratorPubKey) { private Script getP2SHMultiSigOutputScript(byte[] buyerPubKey, byte[] sellerPubKey, byte[] arbitratorPubKey) {
return ScriptBuilder.createP2SHOutputScript(getMultiSigRedeemScript(offererPubKey, takerPubKey, arbitratorPubKey)); return ScriptBuilder.createP2SHOutputScript(getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey));
} }
private Transaction createPayoutTx(Transaction depositTx, private Transaction createPayoutTx(Transaction depositTx,
Coin offererPayoutAmount, Coin buyerPayoutAmount,
Coin takerPayoutAmount, Coin sellerPayoutAmount,
String offererAddressString, String buyerAddressString,
String takerAddressString) throws AddressFormatException { String sellerAddressString) throws AddressFormatException {
TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0); TransactionOutput p2SHMultiSigOutput = depositTx.getOutput(0);
Transaction transaction = new Transaction(params); Transaction transaction = new Transaction(params);
transaction.addInput(p2SHMultiSigOutput); transaction.addInput(p2SHMultiSigOutput);
transaction.addOutput(offererPayoutAmount, new Address(params, offererAddressString)); transaction.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString));
transaction.addOutput(takerPayoutAmount, new Address(params, takerAddressString)); transaction.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString));
return transaction; return transaction;
} }
@ -657,7 +649,7 @@ public class TradeWalletService {
private Transaction depositTx; private Transaction depositTx;
private byte[] offererSignature; private byte[] buyerSignature;
public Result(List<TransactionOutput> connectedOutputsForAllInputs, List<TransactionOutput> outputs) { public Result(List<TransactionOutput> connectedOutputsForAllInputs, List<TransactionOutput> outputs) {
this.connectedOutputsForAllInputs = connectedOutputsForAllInputs; this.connectedOutputsForAllInputs = connectedOutputsForAllInputs;
@ -682,8 +674,8 @@ public class TradeWalletService {
return depositTx; return depositTx;
} }
public byte[] getOffererSignature() { public byte[] getBuyerSignature() {
return offererSignature; return buyerSignature;
} }
} }
} }

View file

@ -64,7 +64,7 @@ public class OffererAsBuyerSubView extends TradeSubView {
leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, completed); leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, completed);
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// State // State
@ -78,8 +78,10 @@ public class OffererAsBuyerSubView extends TradeSubView {
startFiat.inactive(); startFiat.inactive();
waitFiatReceived.inactive(); waitFiatReceived.inactive();
completed.inactive(); completed.inactive();
switch (viewState) { switch (viewState) {
case EMPTY:
break;
case OFFERER_BUYER_WAIT_TX_CONF: case OFFERER_BUYER_WAIT_TX_CONF:
showItem(waitTxInBlockchain); showItem(waitTxInBlockchain);
@ -126,7 +128,11 @@ public class OffererAsBuyerSubView extends TradeSubView {
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage()); Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break; break;
case EXCEPTION: case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException()); if (model.getTradeException() != null)
Popups.openExceptionPopup(model.getTradeException());
break;
default:
log.warn("unhandled viewState " + viewState);
break; break;
} }

View file

@ -0,0 +1,158 @@
/*
* 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.pending;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.portfolio.pending.steps.CompletedView;
import io.bitsquare.gui.main.portfolio.pending.steps.ConfirmFiatReceivedView;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeWizardItem;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitTxInBlockchainView;
import io.bitsquare.locale.BSResources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffererAsSellerSubView extends TradeSubView {
private static final Logger log = LoggerFactory.getLogger(OffererAsSellerSubView.class);
private TradeWizardItem waitTxInBlockchain;
private TradeWizardItem waitFiatStarted;
private TradeWizardItem confirmFiatReceived;
private TradeWizardItem completed;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public OffererAsSellerSubView(PendingTradesViewModel model) {
super(model);
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@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");
completed = new TradeWizardItem(CompletedView.class, "Completed");
leftVBox.getChildren().addAll(waitTxInBlockchain, waitFiatStarted, confirmFiatReceived, completed);
}
///////////////////////////////////////////////////////////////////////////////////////////
// State
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void applyState(PendingTradesViewModel.ViewState viewState) {
log.debug("applyState " + viewState);
waitTxInBlockchain.inactive();
waitFiatStarted.inactive();
confirmFiatReceived.inactive();
completed.inactive();
switch (viewState) {
case EMPTY:
break;
case OFFERER_SELLER_WAIT_TX_CONF:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. " +
"The Bitcoin buyer need to wait for at least one block chain confirmation.");
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("The Bitcoin buyer needs to wait for at least one " +
"block chain confirmation before starting the {0} payment. " +
"That is needed to assure that the deposit input funding has not been " +
"double-spent. " +
"For higher trade volumes it is recommended to wait up to 6 confirmations.",
model.getCurrencyCode()));
break;
case OFFERER_SELLER_WAIT_PAYMENT_STARTED:
waitTxInBlockchain.done();
showItem(waitFiatStarted);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Deposit transaction has at least one block chain " +
"confirmation. " +
"Waiting that other trader starts the {0} payment.",
model.getCurrencyCode()));
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("You will get informed when the other trader has " +
"indicated the {0} payment has been started.",
model.getCurrencyCode()));
break;
case OFFERER_SELLER_CONFIRM_RECEIVE_PAYMENT:
waitTxInBlockchain.done();
waitFiatStarted.done();
showItem(confirmFiatReceived);
((ConfirmFiatReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment." +
"Check your payments account and confirm when you have received the payment.",
model.getCurrencyCode()));
((ConfirmFiatReceivedView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("It is important that you confirm when you have " +
"received the {0} payment as this will publish the payout transaction where you get returned " +
"your security deposit and the Bitcoin buyer receive the Bitcoin amount you sold.",
model.getCurrencyCode()));
break;
case OFFERER_SELLER_COMPLETED:
waitTxInBlockchain.done();
waitFiatStarted.done();
confirmFiatReceived.done();
showItem(completed);
CompletedView completedView = (CompletedView) tradeStepDetailsView;
completedView.setBtcTradeAmountLabelText("You have sold:");
completedView.setFiatTradeAmountLabelText("You have received:");
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
completedView.setFeesTextFieldText(model.getTotalFees());
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
completedView.setSummaryInfoDisplayText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
if (model.getTradeException() != null)
Popups.openExceptionPopup(model.getTradeException());
break;
default:
log.warn("unhandled viewState " + viewState);
break;
}
if (tradeStepDetailsView != null)
tradeStepDetailsView.activate();
}
}

View file

@ -25,9 +25,9 @@ import io.bitsquare.gui.components.Popups;
import io.bitsquare.offer.Offer; import io.bitsquare.offer.Offer;
import io.bitsquare.trade.Contract; import io.bitsquare.trade.Contract;
import io.bitsquare.trade.OffererAsBuyerTrade; import io.bitsquare.trade.OffererAsBuyerTrade;
import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.OffererAsSellerTrade;
import io.bitsquare.trade.TakerAsBuyerTrade;
import io.bitsquare.trade.TakerAsSellerTrade; import io.bitsquare.trade.TakerAsSellerTrade;
import io.bitsquare.trade.TakerTrade;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User; import io.bitsquare.user.User;
@ -68,8 +68,11 @@ class PendingTradesDataModel implements Activatable, DataModel {
final StringProperty txId = new SimpleStringProperty(); final StringProperty txId = new SimpleStringProperty();
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1); final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
final ObjectProperty<Trade.ProcessState> takerProcessState = new SimpleObjectProperty<>(); final ObjectProperty<Trade.ProcessState> takerAsSellerProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade.ProcessState> offererProcessState = new SimpleObjectProperty<>(); final ObjectProperty<Trade.ProcessState> offererAsBuyerProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade.ProcessState> takerAsBuyerProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade.ProcessState> offererAsSellerProcessState = new SimpleObjectProperty<>();
final ObjectProperty<Trade> currentTrade = new SimpleObjectProperty<>(); final ObjectProperty<Trade> currentTrade = new SimpleObjectProperty<>();
@Inject @Inject
@ -95,7 +98,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
@Override @Override
public void deactivate() { public void deactivate() {
tradeManager.getPendingTrades().removeListener(tradesListChangeListener); tradeManager.getPendingTrades().removeListener(tradesListChangeListener);
removeListenerFromSelectedTrade(); unbindStates();
} }
private void onListChanged() { private void onListChanged() {
@ -111,17 +114,20 @@ class PendingTradesDataModel implements Activatable, DataModel {
} }
} }
boolean isBuyOffer() {
if (getTrade() != null)
return getTrade().getOffer().getDirection() == Offer.Direction.BUY;
else
return false;
}
void selectTrade(PendingTradesListItem item) { void selectTrade(PendingTradesListItem item) {
// clean up previous selectedItem // clean up previous selectedItem
removeListenerFromSelectedTrade(); unbindStates();
selectedItem = item; selectedItem = item;
if (item == null) { if (item == null) {
if (currentTrade != null) {
takerProcessState.unbind();
offererProcessState.unbind();
}
currentTrade.set(null); currentTrade.set(null);
} }
else { else {
@ -130,9 +136,13 @@ class PendingTradesDataModel implements Activatable, DataModel {
Trade trade = item.getTrade(); Trade trade = item.getTrade();
isOfferer = trade.getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey()); isOfferer = trade.getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
if (trade instanceof TakerAsSellerTrade) if (trade instanceof TakerAsSellerTrade)
takerProcessState.bind(trade.processStateProperty()); takerAsSellerProcessState.bind(trade.processStateProperty());
else else if (trade instanceof OffererAsBuyerTrade)
offererProcessState.bind(trade.processStateProperty()); offererAsBuyerProcessState.bind(trade.processStateProperty());
else if (trade instanceof TakerAsBuyerTrade)
takerAsBuyerProcessState.bind(trade.processStateProperty());
else if (trade instanceof OffererAsSellerTrade)
offererAsSellerProcessState.bind(trade.processStateProperty());
if (trade.getDepositTx() != null) if (trade.getDepositTx() != null)
txId.set(trade.getDepositTx().getHashAsString()); txId.set(trade.getDepositTx().getHashAsString());
@ -140,13 +150,17 @@ class PendingTradesDataModel implements Activatable, DataModel {
} }
void fiatPaymentStarted() { void fiatPaymentStarted() {
if (getTrade() != null) if (getTrade() instanceof OffererAsBuyerTrade)
((OffererAsBuyerTrade) getTrade()).onFiatPaymentStarted(); ((OffererAsBuyerTrade) getTrade()).onFiatPaymentStarted();
else if (getTrade() instanceof TakerAsBuyerTrade)
((TakerAsBuyerTrade) getTrade()).onFiatPaymentStarted();
} }
void fiatPaymentReceived() { void fiatPaymentReceived() {
if (getTrade() != null) if (getTrade() instanceof TakerAsSellerTrade)
((TakerAsSellerTrade) getTrade()).onFiatPaymentReceived(); ((TakerAsSellerTrade) getTrade()).onFiatPaymentReceived();
else if (getTrade() instanceof OffererAsSellerTrade)
((OffererAsSellerTrade) getTrade()).onFiatPaymentReceived();
} }
void withdraw(String toAddress) { void withdraw(String toAddress) {
@ -237,21 +251,18 @@ class PendingTradesDataModel implements Activatable, DataModel {
offer.getDirection() : offer.getMirroredDirection(); offer.getDirection() : offer.getMirroredDirection();
} }
private void removeListenerFromSelectedTrade() { private void unbindStates() {
if (selectedItem != null) { takerAsSellerProcessState.unbind();
Trade trade = selectedItem.getTrade(); takerAsBuyerProcessState.unbind();
if (trade instanceof TakerTrade) offererAsBuyerProcessState.unbind();
takerProcessState.unbind(); offererAsSellerProcessState.unbind();
else
offererProcessState.unbind();
}
} }
public Coin getAmountToWithdraw() { public Coin getAmountToWithdraw() {
Trade trade = selectedItem.getTrade(); Trade trade = selectedItem.getTrade();
Coin amountToWithdraw = trade.getSecurityDeposit(); Coin amountToWithdraw = trade.getSecurityDeposit();
assert trade.getTradeAmount() != null; assert trade.getTradeAmount() != null;
if (trade instanceof OffererTrade) if (trade instanceof OffererAsBuyerTrade || trade instanceof TakerAsBuyerTrade)
amountToWithdraw = amountToWithdraw.add(trade.getTradeAmount()); amountToWithdraw = amountToWithdraw.add(trade.getTradeAmount());
return amountToWithdraw; return amountToWithdraw;
} }

View file

@ -106,7 +106,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
else { else {
removeSubView(); removeSubView();
} }
if (currentSubView != null) if (currentSubView != null)
currentSubView.activate(); currentSubView.activate();
} }
@ -127,13 +127,20 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
private void addSubView() { private void addSubView() {
removeSubView(); removeSubView();
if (model.isOfferer()) if (model.isOfferer()) {
currentSubView = new OffererAsBuyerSubView(model); if (model.isBuyOffer())
else currentSubView = new OffererAsBuyerSubView(model);
currentSubView = new TakerAsSellerSubView(model); else
currentSubView = new OffererAsSellerSubView(model);
}
else {
if (model.isBuyOffer())
currentSubView = new TakerAsSellerSubView(model);
else
currentSubView = new TakerAsBuyerSubView(model);
}
currentSubView.activate(); currentSubView.activate();
AnchorPane.setTopAnchor(currentSubView, 0d); AnchorPane.setTopAnchor(currentSubView, 0d);
AnchorPane.setRightAnchor(currentSubView, 0d); AnchorPane.setRightAnchor(currentSubView, 0d);
AnchorPane.setBottomAnchor(currentSubView, 0d); AnchorPane.setBottomAnchor(currentSubView, 0d);

View file

@ -58,6 +58,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class); private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class);
enum ViewState { enum ViewState {
EMPTY,
TAKER_SELLER_WAIT_TX_CONF, TAKER_SELLER_WAIT_TX_CONF,
TAKER_SELLER_WAIT_PAYMENT_STARTED, TAKER_SELLER_WAIT_PAYMENT_STARTED,
TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT, TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT,
@ -68,20 +69,34 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED, OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED,
OFFERER_BUYER_COMPLETED, OFFERER_BUYER_COMPLETED,
TAKER_BUYER_WAIT_TX_CONF,
TAKER_BUYER_START_PAYMENT,
TAKER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED,
TAKER_BUYER_COMPLETED,
OFFERER_SELLER_WAIT_TX_CONF,
OFFERER_SELLER_WAIT_PAYMENT_STARTED,
OFFERER_SELLER_CONFIRM_RECEIVE_PAYMENT,
OFFERER_SELLER_COMPLETED,
MESSAGE_SENDING_FAILED, MESSAGE_SENDING_FAILED,
EXCEPTION EXCEPTION
} }
private Navigation navigation; private Navigation navigation;
private final BSFormatter formatter; private final BSFormatter formatter;
private final InvalidationListener takerStateListener; private final InvalidationListener takerAsSellerStateListener;
private final InvalidationListener offererStateListener; private final InvalidationListener offererAsBuyerStateListener;
private final InvalidationListener takerAsBuyerStateListener;
private final InvalidationListener offererAsSellerStateListener;
private final BtcAddressValidator btcAddressValidator; private final BtcAddressValidator btcAddressValidator;
public final StringProperty txId = new SimpleStringProperty(); public final StringProperty txId = new SimpleStringProperty();
public final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true); public final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1); final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
final ObjectProperty<ViewState> viewState = new SimpleObjectProperty<>(); final ObjectProperty<ViewState> viewState = new SimpleObjectProperty<>(ViewState.EMPTY);
@Inject @Inject
@ -92,8 +107,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
this.formatter = formatter; this.formatter = formatter;
this.btcAddressValidator = btcAddressValidator; this.btcAddressValidator = btcAddressValidator;
this.takerStateListener = (ov) -> updateTakerState(); this.takerAsSellerStateListener = (ov) -> updateTakerAsSellerState();
this.offererStateListener = (ov) -> updateOffererState(); this.offererAsBuyerStateListener = (ov) -> updateOffererAsBuyerState();
this.takerAsBuyerStateListener = (ov) -> updateTakerAsBuyerState();
this.offererAsSellerStateListener = (ov) -> updateOffererAsSellerState();
} }
@Override @Override
@ -101,11 +118,15 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
txId.bind(dataModel.txId); txId.bind(dataModel.txId);
selectedIndex.bind(dataModel.selectedIndex); selectedIndex.bind(dataModel.selectedIndex);
dataModel.takerProcessState.addListener(takerStateListener); dataModel.takerAsSellerProcessState.addListener(takerAsSellerStateListener);
dataModel.offererProcessState.addListener(offererStateListener); dataModel.offererAsBuyerProcessState.addListener(offererAsBuyerStateListener);
dataModel.takerAsBuyerProcessState.addListener(takerAsBuyerStateListener);
dataModel.offererAsSellerProcessState.addListener(offererAsSellerStateListener);
updateTakerState(); updateTakerAsSellerState();
updateOffererState(); updateOffererAsBuyerState();
updateTakerAsBuyerState();
updateOffererAsSellerState();
} }
@Override @Override
@ -113,17 +134,22 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
txId.unbind(); txId.unbind();
selectedIndex.unbind(); selectedIndex.unbind();
dataModel.takerProcessState.removeListener(takerStateListener); dataModel.takerAsSellerProcessState.removeListener(takerAsSellerStateListener);
dataModel.offererProcessState.removeListener(offererStateListener); dataModel.offererAsBuyerProcessState.removeListener(offererAsBuyerStateListener);
dataModel.takerAsBuyerProcessState.removeListener(takerAsBuyerStateListener);
dataModel.offererAsSellerProcessState.removeListener(offererAsSellerStateListener);
} }
void selectTrade(PendingTradesListItem item) { void selectTrade(PendingTradesListItem item) {
dataModel.selectTrade(item); dataModel.selectTrade(item);
/* updateTakerState();
updateOffererState();*/
} }
boolean isBuyOffer() {
return dataModel.isBuyOffer();
}
public void fiatPaymentStarted() { public void fiatPaymentStarted() {
dataModel.fiatPaymentStarted(); dataModel.fiatPaymentStarted();
} }
@ -141,7 +167,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid); withdrawalButtonDisable.set(!btcAddressValidator.validate(text).isValid);
} }
public String getAmountToWithdraw() { public String getAmountToWithdraw() {
return formatter.formatCoinWithCode(dataModel.getAmountToWithdraw()); return formatter.formatCoinWithCode(dataModel.getAmountToWithdraw());
} }
@ -191,7 +217,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
} }
// payment // payment
public String getPaymentMethod() { public String getPaymentMethod() {
assert dataModel.getContract() != null; assert dataModel.getContract() != null;
return BSResources.get(dataModel.getContract().takerFiatAccount.type.toString()); return BSResources.get(dataModel.getContract().takerFiatAccount.type.toString());
} }
@ -200,27 +226,27 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume()); return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
} }
public String getHolderName() { public String getHolderName() {
assert dataModel.getContract() != null; assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountHolderName; return dataModel.getContract().takerFiatAccount.accountHolderName;
} }
public String getPrimaryId() { public String getPrimaryId() {
assert dataModel.getContract() != null; assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountPrimaryID; return dataModel.getContract().takerFiatAccount.accountPrimaryID;
} }
public String getSecondaryId() { public String getSecondaryId() {
assert dataModel.getContract() != null; assert dataModel.getContract() != null;
return dataModel.getContract().takerFiatAccount.accountSecondaryID; return dataModel.getContract().takerFiatAccount.accountSecondaryID;
} }
// summary // summary
public String getTradeVolume() { public String getTradeVolume() {
return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount()); return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount());
} }
public String getFiatVolume() { public String getFiatVolume() {
return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume()); return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
} }
@ -249,160 +275,163 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
return dataModel.getErrorMessage(); return dataModel.getErrorMessage();
} }
private void updateTakerState() { private void updateTakerAsSellerState() {
if (dataModel.getTrade() instanceof TakerAsSellerTrade) { TakerAsSellerTrade.ProcessState processState = (TakerAsSellerTrade.ProcessState) dataModel.takerAsSellerProcessState.get();
TakerAsSellerTrade.ProcessState processState = (TakerAsSellerTrade.ProcessState) dataModel.takerProcessState.get(); log.debug("updateTakerAsSellerState " + processState);
log.debug("updateTakerState " + processState); if (processState != null) {
if (processState != null) { switch (processState) {
switch (processState) { case UNDEFINED:
case TAKE_OFFER_FEE_TX_CREATED: case TAKE_OFFER_FEE_TX_CREATED:
break; case TAKE_OFFER_FEE_PUBLISHED:
case TAKE_OFFER_FEE_PUBLISHED: break;
break; case TAKE_OFFER_FEE_PUBLISH_FAILED:
case TAKE_OFFER_FEE_PUBLISH_FAILED: viewState.set(ViewState.EXCEPTION);
break; break;
case DEPOSIT_PUBLISHED: case DEPOSIT_PUBLISHED:
viewState.set(ViewState.TAKER_SELLER_WAIT_TX_CONF); viewState.set(ViewState.TAKER_SELLER_WAIT_TX_CONF);
break; break;
case DEPOSIT_CONFIRMED: case DEPOSIT_CONFIRMED:
viewState.set(ViewState.TAKER_SELLER_WAIT_PAYMENT_STARTED); viewState.set(ViewState.TAKER_SELLER_WAIT_PAYMENT_STARTED);
break; break;
case FIAT_PAYMENT_STARTED: case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT); viewState.set(ViewState.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break; break;
case FIAT_PAYMENT_RECEIVED: case FIAT_PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED: case PAYOUT_PUBLISHED:
viewState.set(ViewState.TAKER_SELLER_COMPLETED); viewState.set(ViewState.TAKER_SELLER_COMPLETED);
break; break;
case MESSAGE_SENDING_FAILED: case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED); viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break; break;
case EXCEPTION: case EXCEPTION:
viewState.set(ViewState.EXCEPTION); viewState.set(ViewState.EXCEPTION);
break; break;
default: default:
log.warn("unhandled processState " + processState); log.warn("unhandled processState " + processState);
break; break;
}
} }
} }
else if (dataModel.getTrade() instanceof TakerAsBuyerTrade) {
TakerAsBuyerTrade.ProcessState processState = (TakerAsBuyerTrade.ProcessState) dataModel.takerProcessState.get();
log.debug("updateTakerState " + processState);
if (processState != null) {
switch (processState) {
case TAKE_OFFER_FEE_TX_CREATED:
break;
case TAKE_OFFER_FEE_PUBLISHED:
break;
case TAKE_OFFER_FEE_PUBLISH_FAILED:
break;
case DEPOSIT_PUBLISHED:
viewState.set(ViewState.TAKER_SELLER_WAIT_TX_CONF);
break;
case DEPOSIT_CONFIRMED:
viewState.set(ViewState.TAKER_SELLER_WAIT_PAYMENT_STARTED);
break;
case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break;
case FIAT_PAYMENT_RECEIVED:
viewState.set(ViewState.TAKER_SELLER_COMPLETED);
break;
case PAYOUT_PUBLISHED:
break;
case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
viewState.set(ViewState.EXCEPTION);
break;
default:
log.warn("unhandled processState " + processState);
break;
}
}
}
} }
private void updateOffererState() { private void updateOffererAsBuyerState() {
if (dataModel.getTrade() instanceof OffererAsBuyerTrade) { OffererAsBuyerTrade.ProcessState processState = (OffererAsBuyerTrade.ProcessState) dataModel.offererAsBuyerProcessState.get();
OffererAsBuyerTrade.ProcessState processState = (OffererAsBuyerTrade.ProcessState) dataModel.offererProcessState.get(); log.debug("updateOffererAsBuyerState " + processState);
log.debug("updateOffererState " + processState); if (processState != null) {
if (processState != null) { switch (processState) {
switch (processState) { case UNDEFINED:
case DEPOSIT_PUBLISHED: break;
viewState.set(ViewState.OFFERER_BUYER_WAIT_TX_CONF); case DEPOSIT_PUBLISHED:
break; viewState.set(ViewState.OFFERER_BUYER_WAIT_TX_CONF);
case DEPOSIT_CONFIRMED: break;
viewState.set(ViewState.OFFERER_BUYER_START_PAYMENT); case DEPOSIT_CONFIRMED:
break; viewState.set(ViewState.OFFERER_BUYER_START_PAYMENT);
break;
case FIAT_PAYMENT_STARTED: case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED); viewState.set(ViewState.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED);
break; break;
case PAYOUT_PUBLISHED: case PAYOUT_PUBLISHED:
viewState.set(ViewState.OFFERER_BUYER_COMPLETED); viewState.set(ViewState.OFFERER_BUYER_COMPLETED);
break; break;
case MESSAGE_SENDING_FAILED: case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED); viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break; break;
case EXCEPTION: case EXCEPTION:
viewState.set(ViewState.EXCEPTION); viewState.set(ViewState.EXCEPTION);
break; break;
default: default:
log.warn("unhandled viewState " + processState); log.warn("unhandled viewState " + processState);
break; break;
}
} }
} }
else if (dataModel.getTrade() instanceof OffererAsSellerTrade) {
OffererAsSellerTrade.ProcessState processState = (OffererAsSellerTrade.ProcessState) dataModel.offererProcessState.get();
log.debug("updateOffererState " + processState);
if (processState != null) {
switch (processState) {
case DEPOSIT_PUBLISHED:
viewState.set(ViewState.OFFERER_BUYER_WAIT_TX_CONF);
break;
case DEPOSIT_CONFIRMED:
viewState.set(ViewState.OFFERER_BUYER_START_PAYMENT);
break;
case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED);
break;
case PAYOUT_PUBLISHED:
viewState.set(ViewState.OFFERER_BUYER_COMPLETED);
break;
case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
viewState.set(ViewState.EXCEPTION);
break;
default:
log.warn("unhandled viewState " + processState);
break;
}
}
}
} }
private void updateTakerAsBuyerState() {
TakerAsBuyerTrade.ProcessState processState = (TakerAsBuyerTrade.ProcessState) dataModel.takerAsBuyerProcessState.get();
log.debug("updateTakerAsBuyerState " + processState);
if (processState != null) {
switch (processState) {
case UNDEFINED:
case TAKE_OFFER_FEE_TX_CREATED:
case TAKE_OFFER_FEE_PUBLISHED:
break;
case TAKE_OFFER_FEE_PUBLISH_FAILED:
viewState.set(ViewState.EXCEPTION);
break;
case DEPOSIT_PUBLISHED:
viewState.set(ViewState.TAKER_BUYER_WAIT_TX_CONF);
break;
case DEPOSIT_CONFIRMED:
viewState.set(ViewState.TAKER_BUYER_START_PAYMENT);
break;
case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.TAKER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED);
break;
case FIAT_PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:
viewState.set(ViewState.TAKER_BUYER_COMPLETED);
break;
case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
viewState.set(ViewState.EXCEPTION);
break;
default:
log.warn("unhandled viewState " + processState);
break;
}
}
}
private void updateOffererAsSellerState() {
OffererAsSellerTrade.ProcessState processState = (OffererAsSellerTrade.ProcessState) dataModel.offererAsSellerProcessState.get();
log.debug("updateOffererAsSellerState " + processState);
if (processState != null) {
switch (processState) {
case UNDEFINED:
break;
case DEPOSIT_PUBLISHED:
viewState.set(ViewState.OFFERER_SELLER_WAIT_TX_CONF);
break;
case DEPOSIT_CONFIRMED:
viewState.set(ViewState.OFFERER_SELLER_WAIT_PAYMENT_STARTED);
break;
case FIAT_PAYMENT_STARTED:
viewState.set(ViewState.OFFERER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break;
case FIAT_PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:
viewState.set(ViewState.OFFERER_SELLER_COMPLETED);
break;
case MESSAGE_SENDING_FAILED:
viewState.set(ViewState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
viewState.set(ViewState.EXCEPTION);
break;
default:
log.warn("unhandled processState " + processState);
break;
}
}
}
} }

View file

@ -0,0 +1,146 @@
/*
* 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.pending;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.main.portfolio.pending.steps.CompletedView;
import io.bitsquare.gui.main.portfolio.pending.steps.StartFiatView;
import io.bitsquare.gui.main.portfolio.pending.steps.TradeWizardItem;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitFiatReceivedView;
import io.bitsquare.gui.main.portfolio.pending.steps.WaitTxInBlockchainView;
import io.bitsquare.locale.BSResources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TakerAsBuyerSubView extends TradeSubView {
private static final Logger log = LoggerFactory.getLogger(TakerAsBuyerSubView.class);
private TradeWizardItem waitTxInBlockchain;
private TradeWizardItem startFiat;
private TradeWizardItem waitFiatReceived;
private TradeWizardItem completed;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, Initialisation
///////////////////////////////////////////////////////////////////////////////////////////
public TakerAsBuyerSubView(PendingTradesViewModel model) {
super(model);
}
@Override
public void activate() {
super.activate();
}
@Override
public void deactivate() {
super.deactivate();
}
@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");
completed = new TradeWizardItem(CompletedView.class, "Completed");
leftVBox.getChildren().addAll(waitTxInBlockchain, startFiat, waitFiatReceived, completed);
}
///////////////////////////////////////////////////////////////////////////////////////////
// State
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void applyState(PendingTradesViewModel.ViewState viewState) {
log.debug("applyState " + viewState);
waitTxInBlockchain.inactive();
startFiat.inactive();
waitFiatReceived.inactive();
completed.inactive();
switch (viewState) {
case EMPTY:
break;
case TAKER_BUYER_WAIT_TX_CONF:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Deposit transaction has been published. You need to wait for at least " +
"one block chain confirmation.");
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoDisplayField("You need to wait for at least one block chain confirmation to" +
" be sure that the deposit funding has not been double spent. For higher trade volumes we" +
" recommend to wait up to 6 confirmations.");
break;
case TAKER_BUYER_START_PAYMENT:
waitTxInBlockchain.done();
showItem(startFiat);
break;
case TAKER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED:
waitTxInBlockchain.done();
startFiat.done();
showItem(waitFiatReceived);
((WaitFiatReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("Waiting for the Bitcoin sellers confirmation " +
"that the {0} payment has arrived.",
model.getCurrencyCode()));
((WaitFiatReceivedView) tradeStepDetailsView).setInfoDisplayField(BSResources.get("When the confirmation that the {0} payment arrived at " +
"the Bitcoin sellers payment account, the payout transaction will be published.",
model.getCurrencyCode()));
break;
case TAKER_BUYER_COMPLETED:
waitTxInBlockchain.done();
startFiat.done();
waitFiatReceived.done();
showItem(completed);
CompletedView completedView = (CompletedView) tradeStepDetailsView;
completedView.setBtcTradeAmountLabelText("You have bought:");
completedView.setFiatTradeAmountLabelText("You have paid:");
completedView.setBtcTradeAmountTextFieldText(model.getTradeVolume());
completedView.setFiatTradeAmountTextFieldText(model.getFiatVolume());
completedView.setFeesTextFieldText(model.getTotalFees());
completedView.setSecurityDepositTextFieldText(model.getSecurityDeposit());
completedView.setSummaryInfoDisplayText("Your security deposit has been refunded to you. " +
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getAmountToWithdraw());
break;
case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;
case EXCEPTION:
if (model.getTradeException() != null)
Popups.openExceptionPopup(model.getTradeException());
break;
default:
log.warn("unhandled viewState " + viewState);
break;
}
if (tradeStepDetailsView != null)
tradeStepDetailsView.activate();
}
}

View file

@ -79,6 +79,8 @@ public class TakerAsSellerSubView extends TradeSubView {
completed.inactive(); completed.inactive();
switch (viewState) { switch (viewState) {
case EMPTY:
break;
case TAKER_SELLER_WAIT_TX_CONF: case TAKER_SELLER_WAIT_TX_CONF:
showItem(waitTxInBlockchain); showItem(waitTxInBlockchain);
@ -141,10 +143,14 @@ public class TakerAsSellerSubView extends TradeSubView {
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage()); Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break; break;
case EXCEPTION: case EXCEPTION:
Popups.openExceptionPopup(model.getTradeException()); if (model.getTradeException() != null)
Popups.openExceptionPopup(model.getTradeException());
break;
default:
log.warn("unhandled viewState " + viewState);
break; break;
} }
if (tradeStepDetailsView != null) if (tradeStepDetailsView != null)
tradeStepDetailsView.activate(); tradeStepDetailsView.activate();
} }

View file

@ -54,7 +54,7 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public TomP2PMessageService(TomP2PNode tomP2PNode, MailboxService mailboxService, EncryptionService<MailboxMessage> encryptionService) { public TomP2PMessageService(TomP2PNode tomP2PNode, MailboxService mailboxService, EncryptionService<MailboxMessage> encryptionService) {
super(tomP2PNode); super(tomP2PNode);
this.mailboxService = mailboxService; this.mailboxService = mailboxService;
this.encryptionService = encryptionService; this.encryptionService = encryptionService;
@ -80,7 +80,10 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
@Override @Override
public void sendMessage(Peer peer, Message message, PublicKey p2pSigPubKey, PublicKey p2pEncryptPubKey, public void sendMessage(Peer peer, Message message, PublicKey p2pSigPubKey, PublicKey p2pEncryptPubKey,
SendMessageListener listener) { SendMessageListener listener) {
if (!(peer instanceof TomP2PPeer))
if (peer == null)
throw new IllegalArgumentException("Peer must not be null");
else if (!(peer instanceof TomP2PPeer))
throw new IllegalArgumentException("Peer must be of type TomP2PPeer"); throw new IllegalArgumentException("Peer must be of type TomP2PPeer");
FutureDirect futureDirect = peerDHT.peer().sendDirect(((TomP2PPeer) peer).getPeerAddress()).object(message).start(); FutureDirect futureDirect = peerDHT.peer().sendDirect(((TomP2PPeer) peer).getPeerAddress()).object(message).start();

View file

@ -101,6 +101,7 @@ public class TakerAsBuyerTrade extends TakerTrade implements Serializable {
// API // API
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() { public void takeAvailableOffer() {
assert protocol instanceof TakerAsBuyerProtocol; assert protocol instanceof TakerAsBuyerProtocol;
((TakerAsBuyerProtocol) protocol).takeAvailableOffer(); ((TakerAsBuyerProtocol) protocol).takeAvailableOffer();

View file

@ -101,6 +101,7 @@ public class TakerAsSellerTrade extends TakerTrade implements Serializable {
// API // API
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() { public void takeAvailableOffer() {
assert protocol instanceof TakerAsSellerProtocol; assert protocol instanceof TakerAsSellerProtocol;
((TakerAsSellerProtocol) protocol).takeAvailableOffer(); ((TakerAsSellerProtocol) protocol).takeAvailableOffer();

View file

@ -95,6 +95,15 @@ public abstract class TakerTrade extends Trade implements Serializable {
return new TakerProcessModel(); return new TakerProcessModel();
} }
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
abstract public void takeAvailableOffer();
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Getter only // Getter only
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -91,7 +91,7 @@ public class TradeManager {
private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>(); private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>();
private final Storage<TradeList> pendingTradesStorage; private final Storage<TradeList> pendingTradesStorage;
private final Storage<TradeList> openOfferTradesStorage; private final Storage<TradeList> openOfferTradesStorage;
private final TradeList<OffererAsBuyerTrade> openOfferTrades; private final TradeList<OffererTrade> openOfferTrades;
private final TradeList<Trade> pendingTrades; private final TradeList<Trade> pendingTrades;
private final TradeList<Trade> closedTrades; private final TradeList<Trade> closedTrades;
@ -150,15 +150,15 @@ public class TradeManager {
// When all services are initialized we create the protocols for our open offers and persisted pendingTrades // When all services are initialized we create the protocols for our open offers and persisted pendingTrades
// OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early. // OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early.
public void onAllServicesInitialized() { public void onAllServicesInitialized() {
for (OffererAsBuyerTrade OffererAsBuyerTrade : openOfferTrades) { for (OffererTrade offererTrade : openOfferTrades) {
Offer offer = OffererAsBuyerTrade.getOffer(); Offer offer = offererTrade.getOffer();
// We add own offers to offerbook when we go online again // We add own offers to offerbook when we go online again
offerBookService.addOffer(offer, offerBookService.addOffer(offer,
() -> log.debug("Successful removed open offer from DHT"), () -> log.debug("Successful removed open offer from DHT"),
(message, throwable) -> log.error("Remove open offer from DHT failed. " + message)); (message, throwable) -> log.error("Remove open offer from DHT failed. " + message));
setupDepositPublishedListener(OffererAsBuyerTrade); setupDepositPublishedListener(offererTrade);
OffererAsBuyerTrade.setStorage(openOfferTradesStorage); offererTrade.setStorage(openOfferTradesStorage);
initTrade(OffererAsBuyerTrade); initTrade(offererTrade);
} }
List<Trade> failedTrades = new ArrayList<>(); List<Trade> failedTrades = new ArrayList<>();
@ -168,12 +168,11 @@ public class TradeManager {
// continue the trade, but that might fail. // continue the trade, but that might fail.
boolean failed = false; boolean failed = false;
if (trade instanceof TakerAsSellerTrade) { if (trade instanceof TakerAsSellerTrade)
failed = trade.lifeCycleState == TakerAsSellerTrade.LifeCycleState.FAILED; failed = trade.lifeCycleState == TakerAsSellerTrade.LifeCycleState.FAILED;
} else if (trade instanceof TakerAsBuyerTrade)
else if (trade instanceof TakerAsBuyerTrade) {
failed = trade.lifeCycleState == TakerAsBuyerTrade.LifeCycleState.FAILED; failed = trade.lifeCycleState == TakerAsBuyerTrade.LifeCycleState.FAILED;
}
if (failed) { if (failed) {
failedTrades.add(trade); failedTrades.add(trade);
} }
@ -229,8 +228,8 @@ public class TradeManager {
log.debug("shutDown"); log.debug("shutDown");
shutDownRequested = true; shutDownRequested = true;
// we remove own offers form offerbook when we go offline // we remove own offers form offerbook when we go offline
for (OffererAsBuyerTrade OffererAsBuyerTrade : openOfferTrades) { for (OffererTrade offererTrade : openOfferTrades) {
Offer offer = OffererAsBuyerTrade.getOffer(); Offer offer = offererTrade.getOffer();
offerBookService.removeOfferAtShutDown(offer); offerBookService.removeOfferAtShutDown(offer);
} }
} }
@ -277,23 +276,28 @@ public class TradeManager {
} }
private void handlePlaceOfferResult(Transaction transaction, Offer offer, TransactionResultHandler resultHandler) { private void handlePlaceOfferResult(Transaction transaction, Offer offer, TransactionResultHandler resultHandler) {
OffererAsBuyerTrade offererAsBuyerTrade = new OffererAsBuyerTrade(offer, openOfferTradesStorage); OffererTrade offererTrade;
openOfferTrades.add(offererAsBuyerTrade); if (offer.getDirection() == Offer.Direction.BUY)
initTrade(offererAsBuyerTrade); offererTrade = new OffererAsBuyerTrade(offer, openOfferTradesStorage);
setupDepositPublishedListener(offererAsBuyerTrade); else
offererTrade = new OffererAsSellerTrade(offer, openOfferTradesStorage);
openOfferTrades.add(offererTrade);
initTrade(offererTrade);
setupDepositPublishedListener(offererTrade);
resultHandler.handleResult(transaction); resultHandler.handleResult(transaction);
} }
private void setupDepositPublishedListener(OffererAsBuyerTrade offererAsBuyerTrade) { private void setupDepositPublishedListener(OffererTrade offererTrade) {
offererAsBuyerTrade.processStateProperty().addListener((ov, oldValue, newValue) -> { offererTrade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("OffererAsBuyerTrade state = " + newValue); log.debug("setupDepositPublishedListener state = " + newValue);
if (newValue == OffererAsBuyerTrade.ProcessState.DEPOSIT_PUBLISHED) { if (newValue == OffererAsBuyerTrade.ProcessState.DEPOSIT_PUBLISHED || newValue == OffererAsSellerTrade.ProcessState.DEPOSIT_PUBLISHED) {
removeOpenOffer(offererAsBuyerTrade.getOffer(), removeOpenOffer(offererTrade.getOffer(),
() -> log.debug("remove offer was successful"), () -> log.debug("remove offer was successful"),
log::error, log::error,
false); false);
pendingTrades.add(offererAsBuyerTrade); pendingTrades.add(offererTrade);
offererAsBuyerTrade.setStorage(pendingTradesStorage); offererTrade.setStorage(pendingTradesStorage);
} }
}); });
} }
@ -309,15 +313,18 @@ public class TradeManager {
offerBookService.removeOffer(offer, offerBookService.removeOffer(offer,
() -> { () -> {
offer.setState(Offer.State.REMOVED); offer.setState(Offer.State.REMOVED);
Optional<OffererAsBuyerTrade> OffererAsBuyerTradeOptional = openOfferTrades.stream().filter(e -> e.getId().equals(offer.getId())).findAny(); Optional<OffererTrade> offererTradeOptional = openOfferTrades.stream().filter(e -> e.getId().equals(offer.getId())).findAny();
if (OffererAsBuyerTradeOptional.isPresent()) { if (offererTradeOptional.isPresent()) {
OffererAsBuyerTrade offererAsBuyerTrade = OffererAsBuyerTradeOptional.get(); OffererTrade offererTrade = offererTradeOptional.get();
openOfferTrades.remove(offererAsBuyerTrade); openOfferTrades.remove(offererTrade);
if (isCancelRequest) { if (isCancelRequest) {
offererAsBuyerTrade.setLifeCycleState(OffererAsBuyerTrade.LifeCycleState.OFFER_CANCELED); if (offererTrade instanceof OffererAsBuyerTrade)
closedTrades.add(offererAsBuyerTrade); offererTrade.setLifeCycleState(OffererAsBuyerTrade.LifeCycleState.OFFER_CANCELED);
offererAsBuyerTrade.disposeProtocol(); else if (offererTrade instanceof OffererAsSellerTrade)
offererTrade.setLifeCycleState(OffererAsSellerTrade.LifeCycleState.OFFER_CANCELED);
closedTrades.add(offererTrade);
offererTrade.disposeProtocol();
} }
} }
@ -370,7 +377,12 @@ public class TradeManager {
takeOfferResultHandler) { takeOfferResultHandler) {
disposeCheckOfferAvailabilityRequest(offer); disposeCheckOfferAvailabilityRequest(offer);
if (offer.getState() == Offer.State.AVAILABLE) { if (offer.getState() == Offer.State.AVAILABLE) {
TakerAsSellerTrade takerTrade = new TakerAsSellerTrade(offer, amount, model.getPeer(), pendingTradesStorage); TakerTrade takerTrade;
if (offer.getDirection() == Offer.Direction.BUY)
takerTrade = new TakerAsSellerTrade(offer, amount, model.getPeer(), pendingTradesStorage);
else
takerTrade = new TakerAsBuyerTrade(offer, amount, model.getPeer(), pendingTradesStorage);
initTrade(takerTrade); initTrade(takerTrade);
pendingTrades.add(takerTrade); pendingTrades.add(takerTrade);
takerTrade.takeAvailableOffer(); takerTrade.takeAvailableOffer();
@ -390,7 +402,7 @@ public class TradeManager {
// TODO handle overpaid securityDeposit // TODO handle overpaid securityDeposit
Coin amountToWithdraw = trade.getSecurityDeposit(); Coin amountToWithdraw = trade.getSecurityDeposit();
assert trade.getTradeAmount() != null; assert trade.getTradeAmount() != null;
if (trade instanceof OffererAsBuyerTrade) if (trade instanceof OffererAsBuyerTrade || trade instanceof TakerAsBuyerTrade)
amountToWithdraw = amountToWithdraw.add(trade.getTradeAmount()); amountToWithdraw = amountToWithdraw.add(trade.getTradeAmount());
FutureCallback<Transaction> callback = new FutureCallback<Transaction>() { FutureCallback<Transaction> callback = new FutureCallback<Transaction>() {
@ -399,9 +411,13 @@ public class TradeManager {
if (transaction != null) { if (transaction != null) {
log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString()); log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
if (trade instanceof OffererAsBuyerTrade) if (trade instanceof OffererAsBuyerTrade)
((OffererAsBuyerTrade) trade).setLifeCycleState(OffererAsBuyerTrade.LifeCycleState.COMPLETED); trade.setLifeCycleState(OffererAsBuyerTrade.LifeCycleState.COMPLETED);
else else if (trade instanceof TakerAsSellerTrade)
((TakerAsSellerTrade) trade).setLifeCycleState(TakerAsSellerTrade.LifeCycleState.COMPLETED); trade.setLifeCycleState(TakerAsSellerTrade.LifeCycleState.COMPLETED);
else if (trade instanceof OffererAsSellerTrade)
trade.setLifeCycleState(OffererAsSellerTrade.LifeCycleState.COMPLETED);
else if (trade instanceof TakerAsBuyerTrade)
trade.setLifeCycleState(TakerAsBuyerTrade.LifeCycleState.COMPLETED);
pendingTrades.remove(trade); pendingTrades.remove(trade);
closedTrades.add(trade); closedTrades.add(trade);
@ -440,7 +456,7 @@ public class TradeManager {
// Getters // Getters
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public ObservableList<OffererAsBuyerTrade> getOpenOfferTrades() { public ObservableList<OffererTrade> getOpenOfferTrades() {
return openOfferTrades.getObservableList(); return openOfferTrades.getObservableList();
} }

View file

@ -31,19 +31,19 @@ public class FiatTransferStartedMessage extends TradeMessage implements MailboxM
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public final byte[] buyerSignature; public final byte[] buyerSignature;
public final Coin offererPayoutAmount; public final Coin buyerPayoutAmount;
public final Coin takerPayoutAmount; public final Coin sellerPayoutAmount;
public final String buyerPayoutAddress; public final String buyerPayoutAddress;
public FiatTransferStartedMessage(String tradeId, public FiatTransferStartedMessage(String tradeId,
byte[] buyerSignature, byte[] buyerSignature,
Coin offererPayoutAmount, Coin buyerPayoutAmount,
Coin takerPayoutAmount, Coin sellerPayoutAmount,
String buyerPayoutAddress) { String buyerPayoutAddress) {
super(tradeId); super(tradeId);
this.buyerSignature = buyerSignature; this.buyerSignature = buyerSignature;
this.offererPayoutAmount = offererPayoutAmount; this.buyerPayoutAmount = buyerPayoutAmount;
this.takerPayoutAmount = takerPayoutAmount; this.sellerPayoutAmount = sellerPayoutAmount;
this.buyerPayoutAddress = buyerPayoutAddress; this.buyerPayoutAddress = buyerPayoutAddress;
} }
} }

View file

@ -0,0 +1,60 @@
/*
* 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.fiat.FiatAccount;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.TransactionOutput;
import java.io.Serializable;
import java.security.PublicKey;
import java.util.List;
import javax.annotation.concurrent.Immutable;
@Immutable
public class RequestPayDepositFromOffererMessage extends RequestPayDepositMessage implements 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 Coin tradeAmount;
public RequestPayDepositFromOffererMessage(String tradeId,
Coin tradeAmount,
List<TransactionOutput> buyerConnectedOutputsForAllInputs,
List<TransactionOutput> buyerOutputs,
byte[] buyerTradeWalletPubKey,
PublicKey buyerP2PSigPublicKey,
PublicKey buyerP2PEncryptPublicKey,
FiatAccount buyerFiatAccount,
String buyerAccountId) {
super(tradeId,
buyerConnectedOutputsForAllInputs,
buyerOutputs,
buyerTradeWalletPubKey,
buyerP2PSigPublicKey,
buyerP2PEncryptPublicKey,
buyerFiatAccount,
buyerAccountId);
this.tradeAmount = tradeAmount;
}
}

View file

@ -0,0 +1,63 @@
/*
* 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.fiat.FiatAccount;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionOutput;
import java.io.Serializable;
import java.security.PublicKey;
import java.util.List;
import javax.annotation.concurrent.Immutable;
@Immutable
public class RequestPublishDepositTxFromTakerMessage extends RequestPublishDepositTxMessage implements Serializable {
// That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = 1L;
public byte[] sellerTradeWalletPubKey;
public RequestPublishDepositTxFromTakerMessage(String tradeId,
FiatAccount takerFiatAccount,
String takerAccountId,
byte[] sellerTradeWalletPubKey,
PublicKey takerP2PSigPublicKey,
PublicKey takerP2PEncryptPublicKey,
String takerContractAsJson,
String takerContractSignature,
String takerPayoutAddressString,
Transaction takersPreparedDepositTx,
List<TransactionOutput> takerConnectedOutputsForAllInputs) {
super(tradeId,
takerFiatAccount,
takerAccountId,
takerP2PSigPublicKey,
takerP2PEncryptPublicKey,
takerContractAsJson,
takerContractSignature,
takerPayoutAddressString,
takersPreparedDepositTx,
takerConnectedOutputsForAllInputs);
this.sellerTradeWalletPubKey = sellerTradeWalletPubKey;
}
}

View file

@ -37,12 +37,12 @@ import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererCreatesAndSignsCon
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererCreatesAndSignsDepositTx; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererCreatesAndSignsDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessDepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessDepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessFiatTransferStartedMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessFiatTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessRequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererProcessRequestPayDepositFromOffererMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSendsPayoutTxPublishedMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSendsPayoutTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSendsRequestPublishDepositTxMessage; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSendsRequestPublishDepositTxFromTakerMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSignsAndPublishPayoutTx; import io.bitsquare.trade.protocol.trade.offerer.tasks.OffererSignsAndPublishPayoutTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakerAccount; import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakerAccount;
import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOfferFeePayment;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -134,19 +134,21 @@ public class OffererAsSellerProtocol implements Protocol {
// Trade // Trade
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private void handle(RequestPayDepositMessage tradeMessage) { private void handle(RequestPayDepositMessage tradeMessage, Peer sender) {
offererTradeProcessModel.setTradeMessage(tradeMessage); offererTradeProcessModel.setTradeMessage(tradeMessage);
offererAsSellerTrade.setTradingPeer(sender);
TaskRunner<OffererAsSellerTrade> taskRunner = new TaskRunner<>(offererAsSellerTrade, TaskRunner<OffererAsSellerTrade> taskRunner = new TaskRunner<>(offererAsSellerTrade,
() -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"), () -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"),
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks( taskRunner.addTasks(
OffererProcessRequestPayDepositMessage.class, OffererProcessRequestPayDepositFromOffererMessage.class,
VerifyTakerAccount.class, VerifyTakerAccount.class,
OffererCreatesAndSignsContract.class, OffererCreatesAndSignsContract.class,
OffererCreatesAndSignsDepositTx.class, OffererCreatesAndSignsDepositTx.class,
OffererSendsRequestPublishDepositTxMessage.class OffererSendsRequestPublishDepositTxFromTakerMessage.class
); );
taskRunner.run(); taskRunner.run();
} }
@ -195,7 +197,7 @@ public class OffererAsSellerProtocol implements Protocol {
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks( taskRunner.addTasks(
VerifyOfferFeePayment.class, VerifyTakeOfferFeePayment.class,
OffererSignsAndPublishPayoutTx.class, OffererSignsAndPublishPayoutTx.class,
OffererSendsPayoutTxPublishedMessage.class OffererSendsPayoutTxPublishedMessage.class
); );
@ -217,7 +219,7 @@ public class OffererAsSellerProtocol implements Protocol {
handle((RequestIsOfferAvailableMessage) tradeMessage, sender); handle((RequestIsOfferAvailableMessage) tradeMessage, sender);
} }
else if (tradeMessage instanceof RequestPayDepositMessage) { else if (tradeMessage instanceof RequestPayDepositMessage) {
handle((RequestPayDepositMessage) tradeMessage); handle((RequestPayDepositMessage) tradeMessage, sender);
} }
else if (tradeMessage instanceof DepositTxPublishedMessage) { else if (tradeMessage instanceof DepositTxPublishedMessage) {
handle((DepositTxPublishedMessage) tradeMessage); handle((DepositTxPublishedMessage) tradeMessage);

View file

@ -57,7 +57,7 @@ public class Offerer implements Serializable {
private List<TransactionOutput> connectedOutputsForAllInputs; private List<TransactionOutput> connectedOutputsForAllInputs;
private List<TransactionOutput> outputs; // used to verify amounts with change outputs private List<TransactionOutput> outputs; // used to verify amounts with change outputs
private Transaction preparedDepositTx; private Transaction preparedDepositTx;
private PublicKey p2pSigPublicKey;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, initialization // Constructor, initialization
@ -169,14 +169,6 @@ public class Offerer implements Serializable {
this.preparedDepositTx = preparedDepositTx; this.preparedDepositTx = preparedDepositTx;
} }
public PublicKey getP2pSigPublicKey() {
return p2pSigPublicKey;
}
public void setP2pSigPublicKey(PublicKey p2pSigPublicKey) {
this.p2pSigPublicKey = p2pSigPublicKey;
}
@Override @Override
public String toString() { public String toString() {
return "Offerer{" + return "Offerer{" +

View file

@ -183,7 +183,7 @@ public class Taker implements Serializable {
return "Taker{" + return "Taker{" +
"accountId='" + accountId + '\'' + "accountId='" + accountId + '\'' +
", fiatAccount=" + fiatAccount + ", fiatAccount=" + fiatAccount +
", p2pSigPublicKey=" + p2pSigPubKey + ", p2pSigPubKey=" + p2pSigPubKey +
", p2pEncryptPubKey=" + p2pEncryptPubKey + ", p2pEncryptPubKey=" + p2pEncryptPubKey +
", contractAsJson='" + contractAsJson + '\'' + ", contractAsJson='" + contractAsJson + '\'' +
", contractSignature='" + contractSignature + '\'' + ", contractSignature='" + contractSignature + '\'' +

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class OffererCommitDepositTx extends OffererTradeTask { public class OffererCommitDepositTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCommitDepositTx.class); private static final Logger log = LoggerFactory.getLogger(OffererCommitDepositTx.class);
public OffererCommitDepositTx(TaskRunner taskHandler, OffererTrade model) { public OffererCommitDepositTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class OffererCommitsPayoutTx extends OffererTradeTask { public class OffererCommitsPayoutTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCommitsPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(OffererCommitsPayoutTx.class);
public OffererCommitsPayoutTx(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererCommitsPayoutTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -18,7 +18,6 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.OffererTrade;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
@ -29,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class OffererCreatesAndSignPayoutTx extends OffererTradeTask { public class OffererCreatesAndSignPayoutTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignPayoutTx.class);
public OffererCreatesAndSignPayoutTx(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererCreatesAndSignPayoutTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override
@ -38,15 +37,9 @@ public class OffererCreatesAndSignPayoutTx extends OffererTradeTask {
try { try {
assert offererTrade.getTradeAmount() != null; assert offererTrade.getTradeAmount() != null;
Coin securityDeposit = offererTrade.getSecurityDeposit(); Coin securityDeposit = offererTrade.getSecurityDeposit();
Coin offererPayoutAmount = securityDeposit.add(offererTrade.getTradeAmount());
Coin offererPayoutAmount = securityDeposit;
if (offererTrade.getOffer().getDirection() == Offer.Direction.BUY)
offererPayoutAmount = offererPayoutAmount.add(offererTrade.getTradeAmount());
Coin takerPayoutAmount = securityDeposit; Coin takerPayoutAmount = securityDeposit;
if (offererTrade.getOffer().getDirection() == Offer.Direction.SELL)
takerPayoutAmount = takerPayoutAmount.add(offererTrade.getTradeAmount());
byte[] offererPayoutTxSignature = offererTradeProcessModel.getTradeWalletService().createAndSignPayoutTx( byte[] offererPayoutTxSignature = offererTradeProcessModel.getTradeWalletService().createAndSignPayoutTx(
offererTrade.getDepositTx(), offererTrade.getDepositTx(),
offererPayoutAmount, offererPayoutAmount,

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class OffererCreatesAndSignsContract extends OffererTradeTask { public class OffererCreatesAndSignsContract extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignsContract.class); private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignsContract.class);
public OffererCreatesAndSignsContract(TaskRunner taskHandler, OffererTrade model) { public OffererCreatesAndSignsContract(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -30,19 +30,19 @@ import org.slf4j.LoggerFactory;
public class OffererCreatesAndSignsDepositTx extends OffererTradeTask { public class OffererCreatesAndSignsDepositTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignsDepositTx.class); private static final Logger log = LoggerFactory.getLogger(OffererCreatesAndSignsDepositTx.class);
public OffererCreatesAndSignsDepositTx(TaskRunner taskHandler, OffererTrade model) { public OffererCreatesAndSignsDepositTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
assert offererTrade.getTradeAmount() != null; assert offererTrade.getTradeAmount() != null;
Coin offererInputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE).add(offererTrade.getTradeAmount()); Coin inputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE).add(offererTrade.getTradeAmount());
Coin msOutputAmount = offererInputAmount.add(offererTrade.getSecurityDeposit()); Coin msOutputAmount = inputAmount.add(offererTrade.getSecurityDeposit());
TradeWalletService.Result result = offererTradeProcessModel.getTradeWalletService().takerCreatesAndSignsDepositTx( TradeWalletService.Result result = offererTradeProcessModel.getTradeWalletService().createAndSignDepositTx(
offererInputAmount, inputAmount,
msOutputAmount, msOutputAmount,
offererTradeProcessModel.taker.getConnectedOutputsForAllInputs(), offererTradeProcessModel.taker.getConnectedOutputsForAllInputs(),
offererTradeProcessModel.taker.getOutputs(), offererTradeProcessModel.taker.getOutputs(),

View file

@ -32,8 +32,8 @@ import org.slf4j.LoggerFactory;
public class OffererCreatesDepositTxInputs extends OffererTradeTask { public class OffererCreatesDepositTxInputs extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererCreatesDepositTxInputs.class); private static final Logger log = LoggerFactory.getLogger(OffererCreatesDepositTxInputs.class);
public OffererCreatesDepositTxInputs(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererCreatesDepositTxInputs(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override
@ -41,7 +41,7 @@ public class OffererCreatesDepositTxInputs extends OffererTradeTask {
try { try {
log.debug("offererTrade.id" + offererTrade.getId()); log.debug("offererTrade.id" + offererTrade.getId());
Coin inputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE); Coin inputAmount = offererTrade.getSecurityDeposit().add(FeePolicy.TX_FEE);
TradeWalletService.Result result = offererTradeProcessModel.getTradeWalletService().createOffererDepositTxInputs(inputAmount, TradeWalletService.Result result = offererTradeProcessModel.getTradeWalletService().createDepositTxInputs(inputAmount,
offererTradeProcessModel.offerer.getAddressEntry()); offererTradeProcessModel.offerer.getAddressEntry());
offererTradeProcessModel.offerer.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs()); offererTradeProcessModel.offerer.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs());

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.checkTradeId;
public class OffererProcessDepositTxPublishedMessage extends OffererTradeTask { public class OffererProcessDepositTxPublishedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessDepositTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessDepositTxPublishedMessage.class);
public OffererProcessDepositTxPublishedMessage(TaskRunner taskHandler, OffererTrade model) { public OffererProcessDepositTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.*;
public class OffererProcessFiatTransferStartedMessage extends OffererTradeTask { public class OffererProcessFiatTransferStartedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessFiatTransferStartedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessFiatTransferStartedMessage.class);
public OffererProcessFiatTransferStartedMessage(TaskRunner taskHandler, OffererTrade model) { public OffererProcessFiatTransferStartedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
@ -44,8 +44,8 @@ public class OffererProcessFiatTransferStartedMessage extends OffererTradeTask {
checkNotNull(message); checkNotNull(message);
offererTradeProcessModel.taker.setSignature(checkNotNull(message.buyerSignature)); offererTradeProcessModel.taker.setSignature(checkNotNull(message.buyerSignature));
offererTradeProcessModel.offerer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount))); offererTradeProcessModel.offerer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.sellerPayoutAmount)));
offererTradeProcessModel.taker.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount))); offererTradeProcessModel.taker.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.buyerPayoutAmount)));
offererTradeProcessModel.taker.setPayoutAddressString(nonEmptyStringOf(message.buyerPayoutAddress)); offererTradeProcessModel.taker.setPayoutAddressString(nonEmptyStringOf(message.buyerPayoutAddress));
if (offererTrade instanceof OffererAsBuyerTrade) if (offererTrade instanceof OffererAsBuyerTrade)

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.checkTradeId;
public class OffererProcessPayoutTxPublishedMessage extends OffererTradeTask { public class OffererProcessPayoutTxPublishedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessPayoutTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessPayoutTxPublishedMessage.class);
public OffererProcessPayoutTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererProcessPayoutTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.*;
public class OffererProcessRequestDepositTxInputsMessage extends OffererTradeTask { public class OffererProcessRequestDepositTxInputsMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestDepositTxInputsMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestDepositTxInputsMessage.class);
public OffererProcessRequestDepositTxInputsMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererProcessRequestDepositTxInputsMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.OffererTrade;
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositFromOffererMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,17 +27,17 @@ import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
import static io.bitsquare.util.Validator.*; import static io.bitsquare.util.Validator.*;
public class OffererProcessRequestPayDepositMessage extends OffererTradeTask { public class OffererProcessRequestPayDepositFromOffererMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestPayDepositMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestPayDepositFromOffererMessage.class);
public OffererProcessRequestPayDepositMessage(TaskRunner taskHandler, OffererTrade model) { public OffererProcessRequestPayDepositFromOffererMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
RequestPayDepositMessage message = (RequestPayDepositMessage) offererTradeProcessModel.getTradeMessage(); RequestPayDepositFromOffererMessage message = (RequestPayDepositFromOffererMessage) offererTradeProcessModel.getTradeMessage();
checkTradeId(offererTradeProcessModel.getId(), message); checkTradeId(offererTradeProcessModel.getId(), message);
checkNotNull(message); checkNotNull(message);
@ -49,6 +49,7 @@ public class OffererProcessRequestPayDepositMessage extends OffererTradeTask {
offererTradeProcessModel.taker.setP2pEncryptPubKey(checkNotNull(message.buyerP2PEncryptPublicKey)); offererTradeProcessModel.taker.setP2pEncryptPubKey(checkNotNull(message.buyerP2PEncryptPublicKey));
offererTradeProcessModel.taker.setFiatAccount(checkNotNull(message.buyerFiatAccount)); offererTradeProcessModel.taker.setFiatAccount(checkNotNull(message.buyerFiatAccount));
offererTradeProcessModel.taker.setAccountId(nonEmptyStringOf(message.buyerAccountId)); offererTradeProcessModel.taker.setAccountId(nonEmptyStringOf(message.buyerAccountId));
offererTrade.setTradeAmount(positiveCoinOf(nonZeroCoinOf(message.tradeAmount)));
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.*;
public class OffererProcessRequestPublishDepositTxMessage extends OffererTradeTask { public class OffererProcessRequestPublishDepositTxMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestPublishDepositTxMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererProcessRequestPublishDepositTxMessage.class);
public OffererProcessRequestPublishDepositTxMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererProcessRequestPublishDepositTxMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class OffererSendsDepositTxPublishedMessage extends OffererTradeTask { public class OffererSendsDepositTxPublishedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSendsDepositTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererSendsDepositTxPublishedMessage.class);
public OffererSendsDepositTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererSendsDepositTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class OffererSendsFiatTransferStartedMessage extends OffererTradeTask { public class OffererSendsFiatTransferStartedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSendsFiatTransferStartedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererSendsFiatTransferStartedMessage.class);
public OffererSendsFiatTransferStartedMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererSendsFiatTransferStartedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class OffererSendsPayoutTxPublishedMessage extends OffererTradeTask { public class OffererSendsPayoutTxPublishedMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSendsPayoutTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererSendsPayoutTxPublishedMessage.class);
public OffererSendsPayoutTxPublishedMessage(TaskRunner taskHandler, OffererTrade model) { public OffererSendsPayoutTxPublishedMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
@ -40,7 +40,7 @@ public class OffererSendsPayoutTxPublishedMessage extends OffererTradeTask {
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(offererTradeProcessModel.getId(), offererTradeProcessModel.getPayoutTx()); PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(offererTradeProcessModel.getId(), offererTradeProcessModel.getPayoutTx());
offererTradeProcessModel.getMessageService().sendMessage(offererTrade.getTradingPeer(), offererTradeProcessModel.getMessageService().sendMessage(offererTrade.getTradingPeer(),
tradeMessage, tradeMessage,
offererTradeProcessModel.offerer.getP2pSigPublicKey(), offererTradeProcessModel.offerer.getP2pSigPubKey(),
offererTradeProcessModel.offerer.getP2pEncryptPubKey(), offererTradeProcessModel.offerer.getP2pEncryptPubKey(),
new SendMessageListener() { new SendMessageListener() {
@Override @Override

View file

@ -22,25 +22,26 @@ import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.OffererAsBuyerTrade; import io.bitsquare.trade.OffererAsBuyerTrade;
import io.bitsquare.trade.OffererAsSellerTrade; import io.bitsquare.trade.OffererAsSellerTrade;
import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.OffererTrade;
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage; import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxFromTakerMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class OffererSendsRequestPublishDepositTxMessage extends OffererTradeTask { public class OffererSendsRequestPublishDepositTxFromTakerMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSendsRequestPublishDepositTxMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererSendsRequestPublishDepositTxFromTakerMessage.class);
public OffererSendsRequestPublishDepositTxMessage(TaskRunner taskHandler, OffererTrade model) { public OffererSendsRequestPublishDepositTxFromTakerMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
RequestPublishDepositTxMessage tradeMessage = new RequestPublishDepositTxMessage( RequestPublishDepositTxFromTakerMessage tradeMessage = new RequestPublishDepositTxFromTakerMessage(
offererTradeProcessModel.getId(), offererTradeProcessModel.getId(),
offererTradeProcessModel.offerer.getFiatAccount(), offererTradeProcessModel.offerer.getFiatAccount(),
offererTradeProcessModel.offerer.getAccountId(), offererTradeProcessModel.offerer.getAccountId(),
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
offererTradeProcessModel.offerer.getP2pSigPubKey(), offererTradeProcessModel.offerer.getP2pSigPubKey(),
offererTradeProcessModel.offerer.getP2pEncryptPublicKey(), offererTradeProcessModel.offerer.getP2pEncryptPublicKey(),
offererTrade.getContractAsJson(), offererTrade.getContractAsJson(),

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class OffererSendsRequestSellerDepositPaymentMessage extends OffererTradeTask { public class OffererSendsRequestSellerDepositPaymentMessage extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSendsRequestSellerDepositPaymentMessage.class); private static final Logger log = LoggerFactory.getLogger(OffererSendsRequestSellerDepositPaymentMessage.class);
public OffererSendsRequestSellerDepositPaymentMessage(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererSendsRequestSellerDepositPaymentMessage(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -36,8 +36,8 @@ import org.slf4j.LoggerFactory;
public class OffererSignsAndPublishDepositTx extends OffererTradeTask { public class OffererSignsAndPublishDepositTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSignsAndPublishDepositTx.class); private static final Logger log = LoggerFactory.getLogger(OffererSignsAndPublishDepositTx.class);
public OffererSignsAndPublishDepositTx(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererSignsAndPublishDepositTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -34,8 +34,8 @@ import org.slf4j.LoggerFactory;
public class OffererSignsAndPublishPayoutTx extends OffererTradeTask { public class OffererSignsAndPublishPayoutTx extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererSignsAndPublishPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(OffererSignsAndPublishPayoutTx.class);
public OffererSignsAndPublishPayoutTx(TaskRunner taskHandler, OffererTrade model) { public OffererSignsAndPublishPayoutTx(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
} }
@Override @Override
@ -44,12 +44,12 @@ public class OffererSignsAndPublishPayoutTx extends OffererTradeTask {
offererTradeProcessModel.getTradeWalletService().signAndPublishPayoutTx( offererTradeProcessModel.getTradeWalletService().signAndPublishPayoutTx(
offererTrade.getDepositTx(), offererTrade.getDepositTx(),
offererTradeProcessModel.taker.getSignature(), offererTradeProcessModel.taker.getSignature(),
offererTradeProcessModel.offerer.getPayoutAmount(),
offererTradeProcessModel.taker.getPayoutAmount(), offererTradeProcessModel.taker.getPayoutAmount(),
offererTradeProcessModel.offerer.getPayoutAmount(),
offererTradeProcessModel.taker.getPayoutAddressString(), offererTradeProcessModel.taker.getPayoutAddressString(),
offererTradeProcessModel.offerer.getAddressEntry(), offererTradeProcessModel.offerer.getAddressEntry(),
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
offererTradeProcessModel.taker.getTradeWalletPubKey(), offererTradeProcessModel.taker.getTradeWalletPubKey(),
offererTradeProcessModel.offerer.getTradeWalletPubKey(),
offererTradeProcessModel.getArbitratorPubKey(), offererTradeProcessModel.getArbitratorPubKey(),
new FutureCallback<Transaction>() { new FutureCallback<Transaction>() {
@Override @Override

View file

@ -17,9 +17,6 @@
package io.bitsquare.trade.protocol.trade.offerer.tasks; package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.btc.exceptions.SigningException;
import io.bitsquare.btc.exceptions.TransactionVerificationException;
import io.bitsquare.btc.exceptions.WalletException;
import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.Task;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.OffererTrade; import io.bitsquare.trade.OffererTrade;
@ -33,10 +30,10 @@ class OffererTradeTask extends Task<OffererTrade> {
protected final OffererProcessModel offererTradeProcessModel; protected final OffererProcessModel offererTradeProcessModel;
protected final OffererTrade offererTrade; protected final OffererTrade offererTrade;
OffererTradeTask(TaskRunner taskHandler, OffererTrade model) { OffererTradeTask(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, model); super(taskHandler, offererTrade);
offererTrade = model; this.offererTrade = offererTrade;
offererTradeProcessModel = offererTrade.getProcessModel(); offererTradeProcessModel = offererTrade.getProcessModel();
} }

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class OffererVerifiesAndSignsContract extends OffererTradeTask { public class OffererVerifiesAndSignsContract extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(OffererVerifiesAndSignsContract.class); private static final Logger log = LoggerFactory.getLogger(OffererVerifiesAndSignsContract.class);
public OffererVerifiesAndSignsContract(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public OffererVerifiesAndSignsContract(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory;
public class VerifyTakeOfferFeePayment extends OffererTradeTask { public class VerifyTakeOfferFeePayment extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class); private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class);
public VerifyTakeOfferFeePayment(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public VerifyTakeOfferFeePayment(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class VerifyTakerAccount extends OffererTradeTask { public class VerifyTakerAccount extends OffererTradeTask {
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class); private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
public VerifyTakerAccount(TaskRunner taskHandler, OffererTrade offererTradeProcessModel) { public VerifyTakerAccount(TaskRunner taskHandler, OffererTrade offererTrade) {
super(taskHandler, offererTradeProcessModel); super(taskHandler, offererTrade);
} }
@Override @Override

View file

@ -34,7 +34,7 @@ import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCommitsPayoutTx;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCreatesAndSignsPayoutTx; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCreatesAndSignsPayoutTx;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCreatesDepositTxInputs; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCreatesDepositTxInputs;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerProcessPayoutTxPublishedMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerProcessPayoutTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerProcessRequestPublishDepositTxMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerProcessRequestPublishDepositTxFromTakerMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsDepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsDepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsFiatTransferStartedMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsFiatTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsRequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.taker.tasks.TakerSendsRequestPayDepositMessage;
@ -119,7 +119,7 @@ public class TakerAsBuyerProtocol implements Protocol {
() -> log.debug("taskRunner at handleRequestPublishDepositTxMessage completed"), () -> log.debug("taskRunner at handleRequestPublishDepositTxMessage completed"),
this::handleTaskRunnerFault); this::handleTaskRunnerFault);
taskRunner.addTasks( taskRunner.addTasks(
TakerProcessRequestPublishDepositTxMessage.class, TakerProcessRequestPublishDepositTxFromTakerMessage.class,
VerifyOffererAccount.class, VerifyOffererAccount.class,
TakerVerifiesAndSignsContract.class, TakerVerifiesAndSignsContract.class,
TakerSignsAndPublishDepositTx.class, TakerSignsAndPublishDepositTx.class,

View file

@ -55,7 +55,6 @@ public class Offerer implements Serializable {
private byte[] signature; private byte[] signature;
private FiatAccount fiatAccount; private FiatAccount fiatAccount;
private String accountId; private String accountId;
private PublicKey p2pSigPublicKey;
private PublicKey p2pEncryptPubKey; private PublicKey p2pEncryptPubKey;
private String contractAsJson; private String contractAsJson;
private String contractSignature; private String contractSignature;
@ -153,15 +152,6 @@ public class Offerer implements Serializable {
this.accountId = accountId; this.accountId = accountId;
} }
@Nullable
public PublicKey getP2pSigPublicKey() {
return p2pSigPublicKey;
}
public void setP2pSigPublicKey(PublicKey p2pSigPublicKey) {
this.p2pSigPublicKey = p2pSigPublicKey;
}
@Nullable @Nullable
public PublicKey getP2pEncryptPubKey() { public PublicKey getP2pEncryptPubKey() {
return p2pEncryptPubKey; return p2pEncryptPubKey;
@ -218,7 +208,7 @@ public class Offerer implements Serializable {
", signature=" + Arrays.toString(signature) + ", signature=" + Arrays.toString(signature) +
", fiatAccount=" + fiatAccount + ", fiatAccount=" + fiatAccount +
", accountId='" + accountId + '\'' + ", accountId='" + accountId + '\'' +
", p2pSigPublicKey=" + p2pSigPublicKey + ", p2pSigPubKey=" + p2pSigPubKey +
", p2pEncryptPubKey=" + p2pEncryptPubKey + ", p2pEncryptPubKey=" + p2pEncryptPubKey +
'}'; '}';
} }

View file

@ -58,6 +58,7 @@ public class Taker implements Serializable {
private Transaction preparedDepositTx; private Transaction preparedDepositTx;
private List<TransactionOutput> outputs; // used to verify amounts with change outputs private List<TransactionOutput> outputs; // used to verify amounts with change outputs
private byte[] payoutTxSignature; private byte[] payoutTxSignature;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, initialization // Constructor, initialization

View file

@ -34,8 +34,8 @@ import org.slf4j.LoggerFactory;
public class BroadcastTakeOfferFeeTx extends TakerTradeTask { public class BroadcastTakeOfferFeeTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(BroadcastTakeOfferFeeTx.class); private static final Logger log = LoggerFactory.getLogger(BroadcastTakeOfferFeeTx.class);
public BroadcastTakeOfferFeeTx(TaskRunner taskHandler, TakerTrade model) { public BroadcastTakeOfferFeeTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class CreateTakeOfferFeeTx extends TakerTradeTask { public class CreateTakeOfferFeeTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(CreateTakeOfferFeeTx.class); private static final Logger log = LoggerFactory.getLogger(CreateTakeOfferFeeTx.class);
public CreateTakeOfferFeeTx(TaskRunner taskHandler, TakerTrade model) { public CreateTakeOfferFeeTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class TakerCommitDepositTx extends TakerTradeTask { public class TakerCommitDepositTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class); private static final Logger log = LoggerFactory.getLogger(TakerCommitDepositTx.class);
public TakerCommitDepositTx(TaskRunner taskHandler, TakerTrade model) { public TakerCommitDepositTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class TakerCommitsPayoutTx extends TakerTradeTask { public class TakerCommitsPayoutTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCommitsPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(TakerCommitsPayoutTx.class);
public TakerCommitsPayoutTx(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerCommitsPayoutTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class TakerCreatesAndSignContract extends TakerTradeTask { public class TakerCreatesAndSignContract extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignContract.class); private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignContract.class);
public TakerCreatesAndSignContract(TaskRunner taskHandler, TakerTrade model) { public TakerCreatesAndSignContract(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -30,19 +30,19 @@ import org.slf4j.LoggerFactory;
public class TakerCreatesAndSignsDepositTx extends TakerTradeTask { public class TakerCreatesAndSignsDepositTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignsDepositTx.class); private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignsDepositTx.class);
public TakerCreatesAndSignsDepositTx(TaskRunner taskHandler, TakerTrade model) { public TakerCreatesAndSignsDepositTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
assert takerTrade.getTradeAmount() != null; assert takerTrade.getTradeAmount() != null;
Coin takerInputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE); Coin inputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE).add(takerTrade.getTradeAmount());
Coin msOutputAmount = takerInputAmount.add(takerTrade.getSecurityDeposit()); Coin msOutputAmount = inputAmount.add(takerTrade.getSecurityDeposit());
TradeWalletService.Result result = takerTradeProcessModel.getTradeWalletService().takerCreatesAndSignsDepositTx( TradeWalletService.Result result = takerTradeProcessModel.getTradeWalletService().createAndSignDepositTx(
takerInputAmount, inputAmount,
msOutputAmount, msOutputAmount,
takerTradeProcessModel.offerer.getConnectedOutputsForAllInputs(), takerTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
takerTradeProcessModel.offerer.getOutputs(), takerTradeProcessModel.offerer.getOutputs(),
@ -51,7 +51,6 @@ public class TakerCreatesAndSignsDepositTx extends TakerTradeTask {
takerTradeProcessModel.taker.getTradeWalletPubKey(), takerTradeProcessModel.taker.getTradeWalletPubKey(),
takerTradeProcessModel.getArbitratorPubKey()); takerTradeProcessModel.getArbitratorPubKey());
takerTradeProcessModel.taker.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs()); takerTradeProcessModel.taker.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs());
takerTradeProcessModel.taker.setPreparedDepositTx(result.getDepositTx()); takerTradeProcessModel.taker.setPreparedDepositTx(result.getDepositTx());

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class TakerCreatesAndSignsPayoutTx extends TakerTradeTask { public class TakerCreatesAndSignsPayoutTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignsPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(TakerCreatesAndSignsPayoutTx.class);
public TakerCreatesAndSignsPayoutTx(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerCreatesAndSignsPayoutTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
@ -40,15 +40,16 @@ public class TakerCreatesAndSignsPayoutTx extends TakerTradeTask {
Coin offererPayoutAmount = securityDeposit; Coin offererPayoutAmount = securityDeposit;
Coin takerPayoutAmount = securityDeposit.add(takerTrade.getTradeAmount()); Coin takerPayoutAmount = securityDeposit.add(takerTrade.getTradeAmount());
byte[] takerPayoutTxSignature = takerTradeProcessModel.getTradeWalletService().createAndSignPayoutTx( byte[] takerPayoutTxSignature = takerTradeProcessModel.getTradeWalletService().createAndSignPayoutTx(
takerTrade.getDepositTx(), takerTrade.getDepositTx(),
offererPayoutAmount,
takerPayoutAmount, takerPayoutAmount,
offererPayoutAmount,
takerTradeProcessModel.taker.getAddressEntry(), takerTradeProcessModel.taker.getAddressEntry(),
takerTradeProcessModel.offerer.getPayoutAddressString(), takerTradeProcessModel.offerer.getPayoutAddressString(),
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
takerTradeProcessModel.taker.getTradeWalletPubKey(), takerTradeProcessModel.taker.getTradeWalletPubKey(),
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
takerTradeProcessModel.getArbitratorPubKey()); takerTradeProcessModel.getArbitratorPubKey());
takerTradeProcessModel.taker.setPayoutTxSignature(takerPayoutTxSignature); takerTradeProcessModel.taker.setPayoutTxSignature(takerPayoutTxSignature);

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class TakerCreatesDepositTxInputs extends TakerTradeTask { public class TakerCreatesDepositTxInputs extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerCreatesDepositTxInputs.class); private static final Logger log = LoggerFactory.getLogger(TakerCreatesDepositTxInputs.class);
public TakerCreatesDepositTxInputs(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerCreatesDepositTxInputs(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
@ -39,7 +39,7 @@ public class TakerCreatesDepositTxInputs extends TakerTradeTask {
try { try {
log.debug("takerTrade.id" + takerTrade.getId()); log.debug("takerTrade.id" + takerTrade.getId());
Coin inputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE); Coin inputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE);
TradeWalletService.Result result = takerTradeProcessModel.getTradeWalletService().createOffererDepositTxInputs(inputAmount, TradeWalletService.Result result = takerTradeProcessModel.getTradeWalletService().createDepositTxInputs(inputAmount,
takerTradeProcessModel.taker.getAddressEntry()); takerTradeProcessModel.taker.getAddressEntry());
takerTradeProcessModel.taker.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs()); takerTradeProcessModel.taker.setConnectedOutputsForAllInputs(result.getConnectedOutputsForAllInputs());

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.checkTradeId;
public class TakerProcessDepositTxPublishedMessage extends TakerTradeTask { public class TakerProcessDepositTxPublishedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerProcessDepositTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerProcessDepositTxPublishedMessage.class);
public TakerProcessDepositTxPublishedMessage(TaskRunner taskHandler, TakerTrade model) { public TakerProcessDepositTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.*;
public class TakerProcessFiatTransferStartedMessage extends TakerTradeTask { public class TakerProcessFiatTransferStartedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerProcessFiatTransferStartedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerProcessFiatTransferStartedMessage.class);
public TakerProcessFiatTransferStartedMessage(TaskRunner taskHandler, TakerTrade model) { public TakerProcessFiatTransferStartedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override
@ -44,8 +44,8 @@ public class TakerProcessFiatTransferStartedMessage extends TakerTradeTask {
checkNotNull(message); checkNotNull(message);
takerTradeProcessModel.offerer.setSignature(checkNotNull(message.buyerSignature)); takerTradeProcessModel.offerer.setSignature(checkNotNull(message.buyerSignature));
takerTradeProcessModel.offerer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount))); takerTradeProcessModel.offerer.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.buyerPayoutAmount)));
takerTradeProcessModel.taker.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.takerPayoutAmount))); takerTradeProcessModel.taker.setPayoutAmount(positiveCoinOf(nonZeroCoinOf(message.sellerPayoutAmount)));
takerTradeProcessModel.offerer.setPayoutAddressString(nonEmptyStringOf(message.buyerPayoutAddress)); takerTradeProcessModel.offerer.setPayoutAddressString(nonEmptyStringOf(message.buyerPayoutAddress));
if (takerTrade instanceof TakerAsBuyerTrade) if (takerTrade instanceof TakerAsBuyerTrade)

View file

@ -32,8 +32,8 @@ import static io.bitsquare.util.Validator.checkTradeId;
public class TakerProcessPayoutTxPublishedMessage extends TakerTradeTask { public class TakerProcessPayoutTxPublishedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerProcessPayoutTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerProcessPayoutTxPublishedMessage.class);
public TakerProcessPayoutTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerProcessPayoutTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.TakerTrade; import io.bitsquare.trade.TakerTrade;
import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxMessage; import io.bitsquare.trade.protocol.trade.messages.RequestPublishDepositTxFromTakerMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -27,23 +27,25 @@ import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.*; import static com.google.common.base.Preconditions.*;
import static io.bitsquare.util.Validator.*; import static io.bitsquare.util.Validator.*;
public class TakerProcessRequestPublishDepositTxMessage extends TakerTradeTask { public class TakerProcessRequestPublishDepositTxFromTakerMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerProcessRequestPublishDepositTxMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerProcessRequestPublishDepositTxFromTakerMessage.class);
public TakerProcessRequestPublishDepositTxMessage(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerProcessRequestPublishDepositTxFromTakerMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
RequestPublishDepositTxMessage message = (RequestPublishDepositTxMessage) takerTradeProcessModel.getTradeMessage(); RequestPublishDepositTxFromTakerMessage message = (RequestPublishDepositTxFromTakerMessage) takerTradeProcessModel.getTradeMessage();
checkTradeId(takerTradeProcessModel.getId(), message); checkTradeId(takerTradeProcessModel.getId(), message);
checkNotNull(message); checkNotNull(message);
takerTradeProcessModel.offerer.setFiatAccount(checkNotNull(message.takerFiatAccount)); takerTradeProcessModel.offerer.setFiatAccount(checkNotNull(message.takerFiatAccount));
takerTradeProcessModel.offerer.setAccountId(nonEmptyStringOf(message.takerAccountId)); takerTradeProcessModel.offerer.setAccountId(nonEmptyStringOf(message.takerAccountId));
takerTradeProcessModel.offerer.setP2pSigPublicKey(checkNotNull(message.takerP2PSigPublicKey)); takerTradeProcessModel.offerer.setP2pSigPubKey(checkNotNull(message.takerP2PSigPublicKey));
takerTradeProcessModel.offerer.setP2pSigPubKey(checkNotNull(message.takerP2PSigPublicKey));
takerTradeProcessModel.offerer.setTradeWalletPubKey(checkNotNull(message.sellerTradeWalletPubKey));
takerTradeProcessModel.offerer.setP2pEncryptPubKey(checkNotNull(message.takerP2PEncryptPublicKey)); takerTradeProcessModel.offerer.setP2pEncryptPubKey(checkNotNull(message.takerP2PEncryptPublicKey));
takerTradeProcessModel.offerer.setContractAsJson(nonEmptyStringOf(message.takerContractAsJson)); takerTradeProcessModel.offerer.setContractAsJson(nonEmptyStringOf(message.takerContractAsJson));
takerTradeProcessModel.offerer.setContractSignature(nonEmptyStringOf(message.takerContractSignature)); takerTradeProcessModel.offerer.setContractSignature(nonEmptyStringOf(message.takerContractSignature));

View file

@ -30,8 +30,8 @@ import static io.bitsquare.util.Validator.*;
public class TakerProcessRequestSellerDepositPaymentMessage extends TakerTradeTask { public class TakerProcessRequestSellerDepositPaymentMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerProcessRequestSellerDepositPaymentMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerProcessRequestSellerDepositPaymentMessage.class);
public TakerProcessRequestSellerDepositPaymentMessage(TaskRunner taskHandler, TakerTrade model) { public TakerProcessRequestSellerDepositPaymentMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override
@ -45,7 +45,7 @@ public class TakerProcessRequestSellerDepositPaymentMessage extends TakerTradeTa
checkArgument(message.buyerConnectedOutputsForAllInputs.size() > 0); checkArgument(message.buyerConnectedOutputsForAllInputs.size() > 0);
takerTradeProcessModel.offerer.setOutputs(checkNotNull(message.buyerOutputs)); takerTradeProcessModel.offerer.setOutputs(checkNotNull(message.buyerOutputs));
takerTradeProcessModel.offerer.setTradeWalletPubKey(checkNotNull(message.buyerTradeWalletPubKey)); takerTradeProcessModel.offerer.setTradeWalletPubKey(checkNotNull(message.buyerTradeWalletPubKey));
takerTradeProcessModel.offerer.setP2pSigPublicKey(checkNotNull(message.buyerP2PSigPublicKey)); takerTradeProcessModel.offerer.setP2pSigPubKey(checkNotNull(message.buyerP2PSigPublicKey));
takerTradeProcessModel.offerer.setP2pEncryptPubKey(checkNotNull(message.buyerP2PEncryptPublicKey)); takerTradeProcessModel.offerer.setP2pEncryptPubKey(checkNotNull(message.buyerP2PEncryptPublicKey));
takerTradeProcessModel.offerer.setFiatAccount(checkNotNull(message.buyerFiatAccount)); takerTradeProcessModel.offerer.setFiatAccount(checkNotNull(message.buyerFiatAccount));
takerTradeProcessModel.offerer.setAccountId(nonEmptyStringOf(message.buyerAccountId)); takerTradeProcessModel.offerer.setAccountId(nonEmptyStringOf(message.buyerAccountId));

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class TakerSendsDepositTxPublishedMessage extends TakerTradeTask { public class TakerSendsDepositTxPublishedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsDepositTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsDepositTxPublishedMessage.class);
public TakerSendsDepositTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerSendsDepositTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class TakerSendsFiatTransferStartedMessage extends TakerTradeTask { public class TakerSendsFiatTransferStartedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsFiatTransferStartedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsFiatTransferStartedMessage.class);
public TakerSendsFiatTransferStartedMessage(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerSendsFiatTransferStartedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
@ -39,8 +39,8 @@ public class TakerSendsFiatTransferStartedMessage extends TakerTradeTask {
try { try {
FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(takerTradeProcessModel.getId(), FiatTransferStartedMessage tradeMessage = new FiatTransferStartedMessage(takerTradeProcessModel.getId(),
takerTradeProcessModel.taker.getPayoutTxSignature(), takerTradeProcessModel.taker.getPayoutTxSignature(),
takerTradeProcessModel.offerer.getPayoutAmount(),
takerTradeProcessModel.taker.getPayoutAmount(), takerTradeProcessModel.taker.getPayoutAmount(),
takerTradeProcessModel.offerer.getPayoutAmount(),
takerTradeProcessModel.taker.getAddressEntry().getAddressString()); takerTradeProcessModel.taker.getAddressEntry().getAddressString());
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), tradeMessage, takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), tradeMessage,

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class TakerSendsPayoutTxPublishedMessage extends TakerTradeTask { public class TakerSendsPayoutTxPublishedMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsPayoutTxPublishedMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsPayoutTxPublishedMessage.class);
public TakerSendsPayoutTxPublishedMessage(TaskRunner taskHandler, TakerTrade model) { public TakerSendsPayoutTxPublishedMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override
@ -40,7 +40,7 @@ public class TakerSendsPayoutTxPublishedMessage extends TakerTradeTask {
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(takerTradeProcessModel.getId(), takerTradeProcessModel.getPayoutTx()); PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(takerTradeProcessModel.getId(), takerTradeProcessModel.getPayoutTx());
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(),
tradeMessage, tradeMessage,
takerTradeProcessModel.offerer.getP2pSigPublicKey(), takerTradeProcessModel.offerer.getP2pSigPubKey(),
takerTradeProcessModel.offerer.getP2pEncryptPubKey(), takerTradeProcessModel.offerer.getP2pEncryptPubKey(),
new SendMessageListener() { new SendMessageListener() {
@Override @Override

View file

@ -32,8 +32,8 @@ import org.slf4j.LoggerFactory;
public class TakerSendsRequestDepositTxInputsMessage extends TakerTradeTask { public class TakerSendsRequestDepositTxInputsMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestDepositTxInputsMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestDepositTxInputsMessage.class);
public TakerSendsRequestDepositTxInputsMessage(TaskRunner taskHandler, TakerTrade model) { public TakerSendsRequestDepositTxInputsMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
private int retryCounter = 0; private int retryCounter = 0;

View file

@ -22,7 +22,7 @@ import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.TakerAsBuyerTrade; import io.bitsquare.trade.TakerAsBuyerTrade;
import io.bitsquare.trade.TakerAsSellerTrade; import io.bitsquare.trade.TakerAsSellerTrade;
import io.bitsquare.trade.TakerTrade; import io.bitsquare.trade.TakerTrade;
import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositFromOffererMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -30,15 +30,16 @@ import org.slf4j.LoggerFactory;
public class TakerSendsRequestPayDepositMessage extends TakerTradeTask { public class TakerSendsRequestPayDepositMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestPayDepositMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestPayDepositMessage.class);
public TakerSendsRequestPayDepositMessage(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerSendsRequestPayDepositMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
RequestPayDepositMessage tradeMessage = new RequestPayDepositMessage( RequestPayDepositFromOffererMessage message = new RequestPayDepositFromOffererMessage(
takerTradeProcessModel.getId(), takerTradeProcessModel.getId(),
model.getTradeAmount(),
takerTradeProcessModel.taker.getConnectedOutputsForAllInputs(), takerTradeProcessModel.taker.getConnectedOutputsForAllInputs(),
takerTradeProcessModel.taker.getOutputs(), takerTradeProcessModel.taker.getOutputs(),
takerTradeProcessModel.taker.getTradeWalletPubKey(), takerTradeProcessModel.taker.getTradeWalletPubKey(),
@ -47,7 +48,7 @@ public class TakerSendsRequestPayDepositMessage extends TakerTradeTask {
takerTradeProcessModel.taker.getFiatAccount(), takerTradeProcessModel.taker.getFiatAccount(),
takerTradeProcessModel.taker.getAccountId()); takerTradeProcessModel.taker.getAccountId());
takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), tradeMessage, new SendMessageListener() { takerTradeProcessModel.getMessageService().sendMessage(takerTrade.getTradingPeer(), message, new SendMessageListener() {
@Override @Override
public void handleResult() { public void handleResult() {
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer"); log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");

View file

@ -30,8 +30,8 @@ import org.slf4j.LoggerFactory;
public class TakerSendsRequestPublishDepositTxMessage extends TakerTradeTask { public class TakerSendsRequestPublishDepositTxMessage extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestPublishDepositTxMessage.class); private static final Logger log = LoggerFactory.getLogger(TakerSendsRequestPublishDepositTxMessage.class);
public TakerSendsRequestPublishDepositTxMessage(TaskRunner taskHandler, TakerTrade model) { public TakerSendsRequestPublishDepositTxMessage(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -36,23 +36,23 @@ import org.slf4j.LoggerFactory;
public class TakerSignsAndPublishDepositTx extends TakerTradeTask { public class TakerSignsAndPublishDepositTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSignsAndPublishDepositTx.class); private static final Logger log = LoggerFactory.getLogger(TakerSignsAndPublishDepositTx.class);
public TakerSignsAndPublishDepositTx(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerSignsAndPublishDepositTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override
protected void doRun() { protected void doRun() {
try { try {
Coin inputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE); Coin inputAmount = takerTrade.getSecurityDeposit().add(FeePolicy.TX_FEE);
takerTradeProcessModel.getTradeWalletService().signAndPublishDepositTx( takerTradeProcessModel.getTradeWalletService().signAndPublishDepositTx(
takerTradeProcessModel.offerer.getPreparedDepositTx(), takerTradeProcessModel.offerer.getPreparedDepositTx(),
takerTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
takerTradeProcessModel.taker.getConnectedOutputsForAllInputs(), takerTradeProcessModel.taker.getConnectedOutputsForAllInputs(),
takerTradeProcessModel.offerer.getConnectedOutputsForAllInputs(),
takerTradeProcessModel.taker.getOutputs(), takerTradeProcessModel.taker.getOutputs(),
inputAmount, inputAmount,
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
takerTradeProcessModel.taker.getTradeWalletPubKey(), takerTradeProcessModel.taker.getTradeWalletPubKey(),
takerTradeProcessModel.offerer.getTradeWalletPubKey(),
takerTradeProcessModel.getArbitratorPubKey(), takerTradeProcessModel.getArbitratorPubKey(),
new FutureCallback<Transaction>() { new FutureCallback<Transaction>() {
@Override @Override

View file

@ -34,8 +34,8 @@ import org.slf4j.LoggerFactory;
public class TakerSignsAndPublishPayoutTx extends TakerTradeTask { public class TakerSignsAndPublishPayoutTx extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerSignsAndPublishPayoutTx.class); private static final Logger log = LoggerFactory.getLogger(TakerSignsAndPublishPayoutTx.class);
public TakerSignsAndPublishPayoutTx(TaskRunner taskHandler, TakerTrade model) { public TakerSignsAndPublishPayoutTx(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -30,10 +30,10 @@ class TakerTradeTask extends Task<TakerTrade> {
protected final TakerProcessModel takerTradeProcessModel; protected final TakerProcessModel takerTradeProcessModel;
protected final TakerTrade takerTrade; protected final TakerTrade takerTrade;
TakerTradeTask(TaskRunner taskHandler, TakerTrade model) { TakerTradeTask(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
takerTrade = model; this.takerTrade = takerTrade;
takerTradeProcessModel = takerTrade.getProcessModel(); takerTradeProcessModel = takerTrade.getProcessModel();
} }

View file

@ -28,8 +28,8 @@ import org.slf4j.LoggerFactory;
public class TakerVerifiesAndSignsContract extends TakerTradeTask { public class TakerVerifiesAndSignsContract extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(TakerVerifiesAndSignsContract.class); private static final Logger log = LoggerFactory.getLogger(TakerVerifiesAndSignsContract.class);
public TakerVerifiesAndSignsContract(TaskRunner taskHandler, TakerTrade takerTradeProcessModel) { public TakerVerifiesAndSignsContract(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, takerTradeProcessModel); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory;
public class VerifyOfferFeePayment extends TakerTradeTask { public class VerifyOfferFeePayment extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class); private static final Logger log = LoggerFactory.getLogger(VerifyOfferFeePayment.class);
public VerifyOfferFeePayment(TaskRunner taskHandler, TakerTrade model) { public VerifyOfferFeePayment(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override

View file

@ -26,8 +26,8 @@ import org.slf4j.LoggerFactory;
public class VerifyOffererAccount extends TakerTradeTask { public class VerifyOffererAccount extends TakerTradeTask {
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class); private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
public VerifyOffererAccount(TaskRunner taskHandler, TakerTrade model) { public VerifyOffererAccount(TaskRunner taskHandler, TakerTrade takerTrade) {
super(taskHandler, model); super(taskHandler, takerTrade);
} }
@Override @Override