mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-05-14 12:32:15 -04:00
changed trade protocol to use tasks, added scheduler framework
This commit is contained in:
parent
4f26d76746
commit
7e55b7325a
93 changed files with 3980 additions and 1273 deletions
17
pom.xml
17
pom.xml
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
@ -194,6 +194,19 @@
|
||||||
<artifactId>proguard</artifactId>
|
<artifactId>proguard</artifactId>
|
||||||
<version>4.4</version>
|
<version>4.4</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.typesafe.akka</groupId>
|
||||||
|
<artifactId>akka-actor_2.11</artifactId>
|
||||||
|
<version>2.3.3</version>
|
||||||
|
</dependency>
|
||||||
|
<!--
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.netflix.rxjava</groupId>
|
||||||
|
<artifactId>rxjava-core</artifactId>
|
||||||
|
<version>0.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
|
@ -17,7 +17,7 @@ public class BtcFormatter
|
||||||
public static BigInteger mBTC = new BigInteger("100000");
|
public static BigInteger mBTC = new BigInteger("100000");
|
||||||
|
|
||||||
|
|
||||||
public static String satoshiToString(BigInteger value)
|
public static String formatSatoshis(BigInteger value)
|
||||||
{
|
{
|
||||||
return Utils.bitcoinValueToFriendlyString(value);
|
return Utils.bitcoinValueToFriendlyString(value);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,14 @@ public class BtcFormatter
|
||||||
|
|
||||||
public static BigInteger stringValueToSatoshis(String value)
|
public static BigInteger stringValueToSatoshis(String value)
|
||||||
{
|
{
|
||||||
return Utils.toNanoCoins(String.valueOf(BitSquareConverter.stringToDouble2(value)));
|
try
|
||||||
|
{
|
||||||
|
return Utils.toNanoCoins(String.valueOf(BitSquareConverter.stringToDouble(value)));
|
||||||
|
} catch (ArithmeticException e)
|
||||||
|
{
|
||||||
|
log.warn("ArithmeticException " + e);
|
||||||
|
}
|
||||||
|
return BigInteger.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BigInteger doubleValueToSatoshis(double value)
|
public static BigInteger doubleValueToSatoshis(double value)
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class BtcValidator
|
||||||
|
|
||||||
public static boolean isMinSpendableAmount(BigInteger amount)
|
public static boolean isMinSpendableAmount(BigInteger amount)
|
||||||
{
|
{
|
||||||
return amount != null && amount.compareTo(FeePolicy.TX_FEE_depr.add(Transaction.MIN_NONDUST_OUTPUT)) > 0;
|
return amount != null && amount.compareTo(FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT)) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAddressValid(String addressString)
|
public boolean isAddressValid(String addressString)
|
||||||
|
|
|
@ -2,22 +2,16 @@ package io.bitsquare.btc;
|
||||||
|
|
||||||
import com.google.bitcoin.core.*;
|
import com.google.bitcoin.core.*;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.currency.Bitcoin;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class FeePolicy
|
public class FeePolicy
|
||||||
{
|
{
|
||||||
public static final BigInteger TX_FEE_depr = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
public static final BigInteger TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||||
public static final BigInteger ACCOUNT_REGISTRATION_FEE_depr = Utils.toNanoCoins("0.01");
|
public static final BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01");
|
||||||
public static final BigInteger CREATE_OFFER_FEE_depr = Utils.toNanoCoins("0.001");
|
public static final BigInteger CREATE_OFFER_FEE = Utils.toNanoCoins("0.001");
|
||||||
public static final BigInteger TAKE_OFFER_FEE_depr = CREATE_OFFER_FEE_depr;
|
public static final BigInteger TAKE_OFFER_FEE = CREATE_OFFER_FEE;
|
||||||
|
|
||||||
public static final Bitcoin TX_FEE = new Bitcoin(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE);
|
|
||||||
public static final Bitcoin CREATE_OFFER_FEE = new Bitcoin(Utils.toNanoCoins("0.001"));
|
|
||||||
public static final Bitcoin TAKE_OFFER_FEE = CREATE_OFFER_FEE;
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
|
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
|
||||||
private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
|
private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
|
||||||
private static final String createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
|
private static final String createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
|
||||||
|
|
|
@ -86,7 +86,7 @@ public class WalletFacade
|
||||||
|
|
||||||
public void initWallet()
|
public void initWallet()
|
||||||
{
|
{
|
||||||
// Tell bitcoinj to run event handlers on the JavaFX UI thread. This keeps things simple and means
|
// Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means
|
||||||
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
||||||
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
||||||
// a future version.
|
// a future version.
|
||||||
|
@ -94,7 +94,7 @@ public class WalletFacade
|
||||||
|
|
||||||
if (params == RegTestParams.get())
|
if (params == RegTestParams.get())
|
||||||
{
|
{
|
||||||
walletAppKit.connectToLocalHost(); // You should run a regtest mode bitcoind locally.
|
walletAppKit.connectToLocalHost(); // You should execute a regtest mode bitcoind locally.
|
||||||
}
|
}
|
||||||
else if (params == MainNetParams.get())
|
else if (params == MainNetParams.get())
|
||||||
{
|
{
|
||||||
|
@ -527,21 +527,21 @@ public class WalletFacade
|
||||||
|
|
||||||
public boolean isRegistrationFeeBalanceSufficient()
|
public boolean isRegistrationFeeBalanceSufficient()
|
||||||
{
|
{
|
||||||
return getRegistrationBalance().compareTo(FeePolicy.ACCOUNT_REGISTRATION_FEE_depr) >= 0;
|
return getRegistrationBalance().compareTo(FeePolicy.ACCOUNT_REGISTRATION_FEE) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnusedTradeAddressBalanceAboveCreationFee()
|
public boolean isUnusedTradeAddressBalanceAboveCreationFee()
|
||||||
{
|
{
|
||||||
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
||||||
BigInteger unUsedAddressInfoBalance = getBalanceForAddress(unUsedAddressEntry.getAddress());
|
BigInteger unUsedAddressInfoBalance = getBalanceForAddress(unUsedAddressEntry.getAddress());
|
||||||
return unUsedAddressInfoBalance.compareTo(FeePolicy.CREATE_OFFER_FEE_depr) > 0;
|
return unUsedAddressInfoBalance.compareTo(FeePolicy.CREATE_OFFER_FEE) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnusedTradeAddressBalanceAboveTakeOfferFee()
|
public boolean isUnusedTradeAddressBalanceAboveTakeOfferFee()
|
||||||
{
|
{
|
||||||
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
||||||
BigInteger unUsedAddressInfoBalance = getBalanceForAddress(unUsedAddressEntry.getAddress());
|
BigInteger unUsedAddressInfoBalance = getBalanceForAddress(unUsedAddressEntry.getAddress());
|
||||||
return unUsedAddressInfoBalance.compareTo(FeePolicy.TAKE_OFFER_FEE_depr) > 0;
|
return unUsedAddressInfoBalance.compareTo(FeePolicy.TAKE_OFFER_FEE) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -573,8 +573,8 @@ public class WalletFacade
|
||||||
byte[] data = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts);
|
byte[] data = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationAddressInfo().getKey(), stringifiedBankAccounts);
|
||||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
|
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, new ScriptBuilder().op(OP_RETURN).data(data).build());
|
||||||
|
|
||||||
BigInteger fee = FeePolicy.ACCOUNT_REGISTRATION_FEE_depr.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE_depr);
|
BigInteger fee = FeePolicy.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE);
|
||||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||||
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());
|
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());
|
||||||
|
|
||||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||||
|
@ -588,12 +588,11 @@ public class WalletFacade
|
||||||
printInputs("payRegistrationFee", tx);
|
printInputs("payRegistrationFee", tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
|
||||||
public String payCreateOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
public String payCreateOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||||
{
|
{
|
||||||
Transaction tx = new Transaction(params);
|
Transaction tx = new Transaction(params);
|
||||||
BigInteger fee = FeePolicy.CREATE_OFFER_FEE_depr.subtract(FeePolicy.TX_FEE_depr);
|
BigInteger fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||||
tx.addOutput(fee, feePolicy.getAddressForCreateOfferFee());
|
tx.addOutput(fee, feePolicy.getAddressForCreateOfferFee());
|
||||||
|
|
||||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||||
|
@ -603,18 +602,18 @@ public class WalletFacade
|
||||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||||
|
|
||||||
printInputs("payTakeOfferFee", tx);
|
printInputs("payCreateOfferFee", tx);
|
||||||
log.debug("tx=" + tx);
|
log.debug("tx=" + tx);
|
||||||
|
|
||||||
return tx.getHashAsString();
|
return tx.getHashAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
|
||||||
public String payTakeOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
public String payTakeOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||||
{
|
{
|
||||||
Transaction tx = new Transaction(params);
|
Transaction tx = new Transaction(params);
|
||||||
BigInteger fee = FeePolicy.TAKE_OFFER_FEE_depr.subtract(FeePolicy.TX_FEE_depr);
|
BigInteger fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||||
tx.addOutput(fee, feePolicy.getAddressForTakeOfferFee());
|
tx.addOutput(fee, feePolicy.getAddressForTakeOfferFee());
|
||||||
|
|
||||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||||
|
@ -643,7 +642,7 @@ public class WalletFacade
|
||||||
FutureCallback<Transaction> callback) throws AddressFormatException, InsufficientMoneyException, IllegalArgumentException
|
FutureCallback<Transaction> callback) throws AddressFormatException, InsufficientMoneyException, IllegalArgumentException
|
||||||
{
|
{
|
||||||
Transaction tx = new Transaction(params);
|
Transaction tx = new Transaction(params);
|
||||||
tx.addOutput(amount.subtract(FeePolicy.TX_FEE_depr), new Address(params, withdrawToAddress));
|
tx.addOutput(amount.subtract(FeePolicy.TX_FEE), new Address(params, withdrawToAddress));
|
||||||
|
|
||||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||||
// we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to wait for 1 confirmation)
|
// we allow spending of unconfirmed tx (double spend risk is low and usability would suffer if we need to wait for 1 confirmation)
|
||||||
|
@ -672,7 +671,7 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
log.debug("offererCreatesMSTxAndAddPayment");
|
log.debug("offererCreatesMSTxAndAddPayment");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
log.trace("offererInputAmount=" + BtcFormatter.satoshiToString(offererInputAmount));
|
log.trace("offererInputAmount=" + BtcFormatter.formatSatoshis(offererInputAmount));
|
||||||
log.trace("offererPubKey=" + offererPubKey);
|
log.trace("offererPubKey=" + offererPubKey);
|
||||||
log.trace("takerPubKey=" + takerPubKey);
|
log.trace("takerPubKey=" + takerPubKey);
|
||||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||||
|
@ -730,8 +729,8 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
log.debug("takerAddPaymentAndSignTx");
|
log.debug("takerAddPaymentAndSignTx");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
log.trace("takerInputAmount=" + BtcFormatter.satoshiToString(takerInputAmount));
|
log.trace("takerInputAmount=" + BtcFormatter.formatSatoshis(takerInputAmount));
|
||||||
log.trace("msOutputAmount=" + BtcFormatter.satoshiToString(msOutputAmount));
|
log.trace("msOutputAmount=" + BtcFormatter.formatSatoshis(msOutputAmount));
|
||||||
log.trace("offererPubKey=" + offererPubKey);
|
log.trace("offererPubKey=" + offererPubKey);
|
||||||
log.trace("takerPubKey=" + takerPubKey);
|
log.trace("takerPubKey=" + takerPubKey);
|
||||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||||
|
@ -786,7 +785,7 @@ public class WalletFacade
|
||||||
tx.addOutput(tempTx.getOutput(1));
|
tx.addOutput(tempTx.getOutput(1));
|
||||||
|
|
||||||
// We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output
|
// We add the btc tx fee to the msOutputAmount and apply the change to the multiSig output
|
||||||
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE_depr);
|
msOutputAmount = msOutputAmount.add(FeePolicy.TX_FEE);
|
||||||
tx.getOutput(0).setValue(msOutputAmount);
|
tx.getOutput(0).setValue(msOutputAmount);
|
||||||
|
|
||||||
// Now we sign our input
|
// Now we sign our input
|
||||||
|
@ -835,7 +834,7 @@ public class WalletFacade
|
||||||
// 3. step: deposit tx
|
// 3. step: deposit tx
|
||||||
// Offerer signs tx and publishes it
|
// Offerer signs tx and publishes it
|
||||||
|
|
||||||
public Transaction offererSignAndPublishTx(String offerersFirstTxAsHex,
|
public void offererSignAndPublishTx(String offerersFirstTxAsHex,
|
||||||
String takersSignedTxAsHex,
|
String takersSignedTxAsHex,
|
||||||
String takersSignedConnOutAsHex,
|
String takersSignedConnOutAsHex,
|
||||||
String takersSignedScriptSigAsHex,
|
String takersSignedScriptSigAsHex,
|
||||||
|
@ -881,7 +880,7 @@ public class WalletFacade
|
||||||
takersSignedTxInput.setParent(tx);
|
takersSignedTxInput.setParent(tx);
|
||||||
tx.addInput(takersSignedTxInput);
|
tx.addInput(takersSignedTxInput);
|
||||||
|
|
||||||
//TODO handle non change output cases
|
//TODO onResult non change output cases
|
||||||
// add outputs from takers tx, they are already correct
|
// add outputs from takers tx, they are already correct
|
||||||
tx.addOutput(takersSignedTx.getOutput(0));
|
tx.addOutput(takersSignedTx.getOutput(0));
|
||||||
if (takersSignedTx.getOutputs().size() > 1)
|
if (takersSignedTx.getOutputs().size() > 1)
|
||||||
|
@ -942,7 +941,6 @@ public class WalletFacade
|
||||||
Futures.addCallback(broadcastComplete, callback);
|
Futures.addCallback(broadcastComplete, callback);
|
||||||
printInputs("tx", tx);
|
printInputs("tx", tx);
|
||||||
log.debug("tx = " + tx);
|
log.debug("tx = " + tx);
|
||||||
return tx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 step deposit tx: Offerer send deposit tx to taker
|
// 4 step deposit tx: Offerer send deposit tx to taker
|
||||||
|
@ -981,8 +979,8 @@ public class WalletFacade
|
||||||
log.debug("offererCreatesAndSignsPayoutTx");
|
log.debug("offererCreatesAndSignsPayoutTx");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
log.trace("depositTxID=" + depositTxID);
|
log.trace("depositTxID=" + depositTxID);
|
||||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||||
log.trace("takerAddress=" + takerAddress);
|
log.trace("takerAddress=" + takerAddress);
|
||||||
|
|
||||||
// Offerer has published depositTx earlier, so he has it in his wallet
|
// Offerer has published depositTx earlier, so he has it in his wallet
|
||||||
|
@ -1007,9 +1005,7 @@ public class WalletFacade
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. step payout tx: Taker signs and publish tx
|
// 6. step payout tx: Taker signs and publish tx
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
public void takerSignsAndSendsTx(String depositTxAsHex,
|
||||||
|
|
||||||
public Transaction takerSignsAndSendsTx(String depositTxAsHex,
|
|
||||||
String offererSignatureR,
|
String offererSignatureR,
|
||||||
String offererSignatureS,
|
String offererSignatureS,
|
||||||
BigInteger offererPaybackAmount,
|
BigInteger offererPaybackAmount,
|
||||||
|
@ -1023,8 +1019,8 @@ public class WalletFacade
|
||||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||||
log.trace("offererSignatureR=" + offererSignatureR);
|
log.trace("offererSignatureR=" + offererSignatureR);
|
||||||
log.trace("offererSignatureS=" + offererSignatureS);
|
log.trace("offererSignatureS=" + offererSignatureS);
|
||||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||||
log.trace("offererAddress=" + offererAddress);
|
log.trace("offererAddress=" + offererAddress);
|
||||||
log.trace("callback=" + callback);
|
log.trace("callback=" + callback);
|
||||||
|
|
||||||
|
@ -1062,7 +1058,6 @@ public class WalletFacade
|
||||||
log.trace("Check if wallet is consistent: result=" + wallet.isConsistent());
|
log.trace("Check if wallet is consistent: result=" + wallet.isConsistent());
|
||||||
printInputs("takerSignsAndSendsTx", tx);
|
printInputs("takerSignsAndSendsTx", tx);
|
||||||
log.debug("tx = " + tx);
|
log.debug("tx = " + tx);
|
||||||
return tx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1103,8 +1098,8 @@ public class WalletFacade
|
||||||
log.trace("createPayoutTx");
|
log.trace("createPayoutTx");
|
||||||
log.trace("inputs: ");
|
log.trace("inputs: ");
|
||||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||||
log.trace("offererAddress=" + offererAddress);
|
log.trace("offererAddress=" + offererAddress);
|
||||||
log.trace("takerAddress=" + takerAddress);
|
log.trace("takerAddress=" + takerAddress);
|
||||||
|
|
||||||
|
@ -1122,7 +1117,7 @@ public class WalletFacade
|
||||||
{
|
{
|
||||||
for (TransactionInput input : tx.getInputs())
|
for (TransactionInput input : tx.getInputs())
|
||||||
if (input.getConnectedOutput() != null)
|
if (input.getConnectedOutput() != null)
|
||||||
log.trace(tracePrefix + ": " + BtcFormatter.satoshiToString(input.getConnectedOutput().getValue()));
|
log.trace(tracePrefix + " input value : " + BtcFormatter.formatSatoshis(input.getConnectedOutput().getValue()));
|
||||||
else
|
else
|
||||||
log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value.");
|
log.trace(tracePrefix + ": " + "Transaction already has inputs but we don't have the connected outputs, so we don't know the value.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
package io.bitsquare.currency;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.Random;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class Bitcoin extends BigInteger
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Bitcoin.class);
|
|
||||||
private static final long serialVersionUID = 6436341706716520132L;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public Bitcoin(BigInteger val)
|
|
||||||
{
|
|
||||||
super(val.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(byte[] val)
|
|
||||||
{
|
|
||||||
super(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(int signum, byte[] magnitude)
|
|
||||||
{
|
|
||||||
super(signum, magnitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(String val, int radix)
|
|
||||||
{
|
|
||||||
super(val, radix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(String val)
|
|
||||||
{
|
|
||||||
super(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(int numBits, Random rnd)
|
|
||||||
{
|
|
||||||
super(numBits, rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin(int bitLength, int certainty, Random rnd)
|
|
||||||
{
|
|
||||||
super(bitLength, certainty, rnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Public methods
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public boolean isZero()
|
|
||||||
{
|
|
||||||
|
|
||||||
return this.compareTo(BigInteger.ZERO) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMinValue()
|
|
||||||
{
|
|
||||||
|
|
||||||
return this.compareTo(Transaction.MIN_NONDUST_OUTPUT) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin addBitcoin(Bitcoin other)
|
|
||||||
{
|
|
||||||
return new Bitcoin(this.add(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin subtractBitcoin(Bitcoin other)
|
|
||||||
{
|
|
||||||
return new Bitcoin(this.subtract(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bitcoin multiplyBitcoin(Bitcoin other)
|
|
||||||
{
|
|
||||||
return new Bitcoin(this.multiply(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLarger(Bitcoin other)
|
|
||||||
{
|
|
||||||
|
|
||||||
return this.compareTo(other) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLess(Bitcoin other)
|
|
||||||
{
|
|
||||||
|
|
||||||
return this.compareTo(other) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEqual(Bitcoin other)
|
|
||||||
{
|
|
||||||
|
|
||||||
return this.compareTo(other) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFormattedValue()
|
|
||||||
{
|
|
||||||
return BtcFormatter.satoshiToString(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package io.bitsquare.currency;
|
|
||||||
|
|
||||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
|
||||||
import java.util.Currency;
|
|
||||||
import java.util.Locale;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class Fiat
|
|
||||||
{
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(Fiat.class);
|
|
||||||
private double value;
|
|
||||||
private Currency currency;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public Fiat(double value)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.currency = Currency.getInstance(Locale.getDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Fiat(double value, Currency currency)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
this.currency = currency;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Public methods
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
public String getFormattedValue()
|
|
||||||
{
|
|
||||||
return BitSquareFormatter.formatPrice(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrencyCode()
|
|
||||||
{
|
|
||||||
return currency.getCurrencyCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Currency getCurrency()
|
|
||||||
{
|
|
||||||
return currency;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,11 +8,11 @@ import io.bitsquare.btc.listeners.BalanceListener;
|
||||||
import io.bitsquare.di.GuiceFXMLLoader;
|
import io.bitsquare.di.GuiceFXMLLoader;
|
||||||
import io.bitsquare.gui.components.NetworkSyncPane;
|
import io.bitsquare.gui.components.NetworkSyncPane;
|
||||||
import io.bitsquare.gui.market.MarketController;
|
import io.bitsquare.gui.market.MarketController;
|
||||||
|
import io.bitsquare.gui.orders.OrdersController;
|
||||||
import io.bitsquare.gui.util.Icons;
|
import io.bitsquare.gui.util.Icons;
|
||||||
import io.bitsquare.gui.util.Transitions;
|
import io.bitsquare.gui.util.Transitions;
|
||||||
import io.bitsquare.locale.Localisation;
|
import io.bitsquare.locale.Localisation;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
import io.bitsquare.trade.Trading;
|
import io.bitsquare.trade.Trading;
|
||||||
|
@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
|
||||||
public class MainController implements Initializable, NavigationController
|
public class MainController implements Initializable, NavigationController
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(MainController.class);
|
private static final Logger log = LoggerFactory.getLogger(MainController.class);
|
||||||
private static MainController mainController;
|
private static MainController INSTANCE;
|
||||||
|
|
||||||
private final User user;
|
private final User user;
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
|
@ -85,7 +85,7 @@ public class MainController implements Initializable, NavigationController
|
||||||
this.trading = trading;
|
this.trading = trading;
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
|
||||||
MainController.mainController = this;
|
MainController.INSTANCE = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -93,9 +93,9 @@ public class MainController implements Initializable, NavigationController
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
public static MainController INSTANCE()
|
public static MainController GET_INSTANCE()
|
||||||
{
|
{
|
||||||
return mainController;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ public class MainController implements Initializable, NavigationController
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
messageFacade.init();
|
messageFacade.init();
|
||||||
messageFacade.addTakeOfferRequestListener(this::showTakeOfferRequest);
|
messageFacade.addTakeOfferRequestListener(this::onTakeOfferRequested);
|
||||||
|
|
||||||
walletFacade.addDownloadListener(new WalletFacade.DownloadListener()
|
walletFacade.addDownloadListener(new WalletFacade.DownloadListener()
|
||||||
{
|
{
|
||||||
|
@ -209,13 +209,15 @@ public class MainController implements Initializable, NavigationController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void showTakeOfferRequest(TradeMessage tradeMessage, PeerAddress sender)
|
private void onTakeOfferRequested(String offerId, PeerAddress sender)
|
||||||
{
|
{
|
||||||
trading.createOffererPaymentProtocol(tradeMessage, sender);
|
|
||||||
final Button alertButton = new Button("", Icons.getIconImageView(Icons.MSG_ALERT));
|
final Button alertButton = new Button("", Icons.getIconImageView(Icons.MSG_ALERT));
|
||||||
alertButton.setId("nav-alert-button");
|
alertButton.setId("nav-alert-button");
|
||||||
alertButton.relocate(36, 19);
|
alertButton.relocate(36, 19);
|
||||||
alertButton.setOnAction((e) -> ordersButton.fire());
|
alertButton.setOnAction((e) -> {
|
||||||
|
OrdersController.GET_INSTANCE().setSelectedTabIndex(1);
|
||||||
|
ordersButton.fire();
|
||||||
|
});
|
||||||
Tooltip.install(alertButton, new Tooltip("Someone accepted your offer"));
|
Tooltip.install(alertButton, new Tooltip("Someone accepted your offer"));
|
||||||
ordersButtonButtonHolder.getChildren().add(alertButton);
|
ordersButtonButtonHolder.getChildren().add(alertButton);
|
||||||
}
|
}
|
||||||
|
@ -289,13 +291,13 @@ public class MainController implements Initializable, NavigationController
|
||||||
balanceTextField.setEditable(false);
|
balanceTextField.setEditable(false);
|
||||||
balanceTextField.setPrefWidth(90);
|
balanceTextField.setPrefWidth(90);
|
||||||
balanceTextField.setId("nav-balance-label");
|
balanceTextField.setId("nav-balance-label");
|
||||||
balanceTextField.setText(BtcFormatter.satoshiToString(walletFacade.getWalletBalance()));
|
balanceTextField.setText(BtcFormatter.formatSatoshis(walletFacade.getWalletBalance()));
|
||||||
walletFacade.addBalanceListener(new BalanceListener()
|
walletFacade.addBalanceListener(new BalanceListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onBalanceChanged(BigInteger balance)
|
public void onBalanceChanged(BigInteger balance)
|
||||||
{
|
{
|
||||||
balanceTextField.setText(BtcFormatter.satoshiToString(balance));
|
balanceTextField.setText(BtcFormatter.formatSatoshis(balance));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
@ -181,7 +180,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onPrevious(ActionEvent actionEvent)
|
public void onPrevious()
|
||||||
{
|
{
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
{
|
{
|
||||||
|
@ -193,7 +192,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onNext(ActionEvent actionEvent)
|
public void onNext()
|
||||||
{
|
{
|
||||||
if (index < allArbitrators.size() - 1)
|
if (index < allArbitrators.size() - 1)
|
||||||
{
|
{
|
||||||
|
@ -205,14 +204,14 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onSelect(ActionEvent actionEvent)
|
public void onSelect()
|
||||||
{
|
{
|
||||||
settings.addAcceptedArbitrator(currentArbitrator);
|
settings.addAcceptedArbitrator(currentArbitrator);
|
||||||
storage.write(settings.getClass().getName(), settings);
|
storage.write(settings.getClass().getName(), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onClose(ActionEvent actionEvent)
|
public void onClose()
|
||||||
{
|
{
|
||||||
Stage stage = (Stage) rootContainer.getScene().getWindow();
|
Stage stage = (Stage) rootContainer.getScene().getWindow();
|
||||||
stage.close();
|
stage.close();
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
@ -232,7 +231,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onSelectIDType(ActionEvent actionEvent)
|
public void onSelectIDType()
|
||||||
{
|
{
|
||||||
idType = idTypeComboBox.getSelectionModel().getSelectedItem();
|
idType = idTypeComboBox.getSelectionModel().getSelectedItem();
|
||||||
if (idType != null)
|
if (idType != null)
|
||||||
|
@ -259,7 +258,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onAddLanguage(ActionEvent actionEvent)
|
public void onAddLanguage()
|
||||||
{
|
{
|
||||||
Locale item = languageComboBox.getSelectionModel().getSelectedItem();
|
Locale item = languageComboBox.getSelectionModel().getSelectedItem();
|
||||||
if (!languageList.contains(item) && item != null)
|
if (!languageList.contains(item) && item != null)
|
||||||
|
@ -271,14 +270,14 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onClearLanguages(ActionEvent actionEvent)
|
public void onClearLanguages()
|
||||||
{
|
{
|
||||||
languageList.clear();
|
languageList.clear();
|
||||||
languagesTextField.setText("");
|
languagesTextField.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onAddMethod(ActionEvent actionEvent)
|
public void onAddMethod()
|
||||||
{
|
{
|
||||||
Arbitrator.METHOD item = methodsComboBox.getSelectionModel().getSelectedItem();
|
Arbitrator.METHOD item = methodsComboBox.getSelectionModel().getSelectedItem();
|
||||||
if (!methodList.contains(item) && item != null)
|
if (!methodList.contains(item) && item != null)
|
||||||
|
@ -290,7 +289,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onClearMethods(ActionEvent actionEvent)
|
public void onClearMethods()
|
||||||
{
|
{
|
||||||
methodList.clear();
|
methodList.clear();
|
||||||
methodsTextField.setText("");
|
methodsTextField.setText("");
|
||||||
|
@ -298,7 +297,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onAddIDVerification(ActionEvent actionEvent)
|
public void onAddIDVerification()
|
||||||
{
|
{
|
||||||
Arbitrator.ID_VERIFICATION idVerification = idVerificationsComboBox.getSelectionModel().getSelectedItem();
|
Arbitrator.ID_VERIFICATION idVerification = idVerificationsComboBox.getSelectionModel().getSelectedItem();
|
||||||
if (idVerification != null)
|
if (idVerification != null)
|
||||||
|
@ -314,14 +313,14 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onClearIDVerifications(ActionEvent actionEvent)
|
public void onClearIDVerifications()
|
||||||
{
|
{
|
||||||
idVerificationList.clear();
|
idVerificationList.clear();
|
||||||
idVerificationsTextField.setText("");
|
idVerificationsTextField.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onSaveProfile(ActionEvent actionEvent)
|
public void onSaveProfile()
|
||||||
{
|
{
|
||||||
arbitrator = getEditedArbitrator();
|
arbitrator = getEditedArbitrator();
|
||||||
if (arbitrator != null)
|
if (arbitrator != null)
|
||||||
|
@ -349,7 +348,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void onPaymentDone(ActionEvent actionEvent)
|
public void onPaymentDone()
|
||||||
{
|
{
|
||||||
//To change body of created methods use File | Settings | File Templates.
|
//To change body of created methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,12 @@ import javafx.scene.Node;
|
||||||
import javafx.scene.control.SingleSelectionModel;
|
import javafx.scene.control.SingleSelectionModel;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class LazyLoadingTabPane extends TabPane
|
public class LazyLoadingTabPane extends TabPane
|
||||||
{
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(LazyLoadingTabPane.class);
|
||||||
private final Map<Integer, Node> views = new HashMap<>();
|
private final Map<Integer, Node> views = new HashMap<>();
|
||||||
private final Map<Integer, ChildController> controllers = new HashMap<>();
|
private final Map<Integer, ChildController> controllers = new HashMap<>();
|
||||||
private SingleSelectionModel<Tab> selectionModel;
|
private SingleSelectionModel<Tab> selectionModel;
|
||||||
|
@ -24,6 +27,7 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
private String[] tabContentFXMLUrls;
|
private String[] tabContentFXMLUrls;
|
||||||
private Storage storage;
|
private Storage storage;
|
||||||
private ChildController childController;
|
private ChildController childController;
|
||||||
|
private int selectedTabIndex = -1;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -50,9 +54,17 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
selectionModel = getSelectionModel();
|
selectionModel = getSelectionModel();
|
||||||
selectionModel.selectedItemProperty().addListener((observableValue, oldTab, newTab) -> onTabSelectedIndexChanged());
|
selectionModel.selectedItemProperty().addListener((observableValue, oldTab, newTab) -> onTabSelectedIndexChanged());
|
||||||
|
|
||||||
|
if (selectedTabIndex == -1)
|
||||||
|
{
|
||||||
Object indexObject = storage.read(storageId);
|
Object indexObject = storage.read(storageId);
|
||||||
|
log.trace("saved index" + indexObject);
|
||||||
if (indexObject != null)
|
if (indexObject != null)
|
||||||
selectionModel.select((int) indexObject);
|
selectionModel.select((int) indexObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectionModel.select(selectedTabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
onTabSelectedIndexChanged();
|
onTabSelectedIndexChanged();
|
||||||
}
|
}
|
||||||
|
@ -81,6 +93,7 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
private void onTabSelectedIndexChanged()
|
private void onTabSelectedIndexChanged()
|
||||||
{
|
{
|
||||||
int index = selectionModel.getSelectedIndex();
|
int index = selectionModel.getSelectedIndex();
|
||||||
|
log.trace("onTabSelectedIndexChanged index" + index);
|
||||||
if (index < tabContentFXMLUrls.length && index >= 0)
|
if (index < tabContentFXMLUrls.length && index >= 0)
|
||||||
{
|
{
|
||||||
if (childController != null)
|
if (childController != null)
|
||||||
|
@ -121,4 +134,8 @@ public class LazyLoadingTabPane extends TabPane
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSelectedTabIndex(int selectedTabIndex)
|
||||||
|
{
|
||||||
|
this.selectedTabIndex = selectedTabIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
package io.bitsquare.gui.components;
|
||||||
|
|
||||||
|
import javafx.beans.binding.BooleanBinding;
|
||||||
|
import javafx.beans.property.*;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.effect.BlurType;
|
||||||
|
import javafx.scene.effect.DropShadow;
|
||||||
|
import javafx.scene.effect.Effect;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TextField with regex-based real-time input validation.
|
||||||
|
* JavaFX 2 and FXML compatible. </p>
|
||||||
|
* <p>
|
||||||
|
* FXML code example:<div>
|
||||||
|
* {@code <ValidatedTextField fx:id="validatedTextField" minLength="1" maxLength="1" mask="^[0-9]*$" />}
|
||||||
|
* </div>
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class ValidatedTextField extends TextField
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ValidatedTextField.class);
|
||||||
|
|
||||||
|
private final BooleanProperty invalid = new SimpleBooleanProperty(false);
|
||||||
|
private final StringProperty mask;
|
||||||
|
private final IntegerProperty minLength;
|
||||||
|
private final IntegerProperty maxLength;
|
||||||
|
|
||||||
|
private Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);
|
||||||
|
|
||||||
|
public ValidatedTextField()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.mask = new SimpleStringProperty("^[0-9.,]*$");
|
||||||
|
this.minLength = new SimpleIntegerProperty(1);
|
||||||
|
this.maxLength = new SimpleIntegerProperty(12);
|
||||||
|
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable)
|
||||||
|
{
|
||||||
|
this(mask, minLength, maxLength, nullable, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable, String string)
|
||||||
|
{
|
||||||
|
super(string);
|
||||||
|
this.mask = new SimpleStringProperty(mask);
|
||||||
|
this.minLength = new SimpleIntegerProperty(minLength);
|
||||||
|
this.maxLength = new SimpleIntegerProperty(maxLength);
|
||||||
|
|
||||||
|
bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyBooleanProperty invalidProperty()
|
||||||
|
{
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyStringProperty maskProperty()
|
||||||
|
{
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyIntegerProperty minLengthProperty()
|
||||||
|
{
|
||||||
|
return minLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyIntegerProperty maxLengthProperty()
|
||||||
|
{
|
||||||
|
return maxLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInvalid()
|
||||||
|
{
|
||||||
|
return invalid.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMask()
|
||||||
|
{
|
||||||
|
return mask.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMask(String mask)
|
||||||
|
{
|
||||||
|
this.mask.set(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinLength()
|
||||||
|
{
|
||||||
|
return minLength.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinLength(int minLength)
|
||||||
|
{
|
||||||
|
this.minLength.set(minLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxLength()
|
||||||
|
{
|
||||||
|
return maxLength.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxLength(int maxLength)
|
||||||
|
{
|
||||||
|
this.maxLength.set(maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Effect getInvalidEffect()
|
||||||
|
{
|
||||||
|
return this.invalidEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvalidEffect(Effect effect)
|
||||||
|
{
|
||||||
|
this.invalidEffect = effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bind()
|
||||||
|
{
|
||||||
|
this.invalid.bind(maskCheck().or(minLengthCheck()));
|
||||||
|
|
||||||
|
this.textProperty().addListener(new ChangeListener<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends String> ov, String t, String t1)
|
||||||
|
{
|
||||||
|
if (textProperty().get().length() > maxLength.get())
|
||||||
|
{
|
||||||
|
setText(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.invalid.addListener(new ChangeListener<Boolean>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1)
|
||||||
|
{
|
||||||
|
if (t ^ t1)
|
||||||
|
{
|
||||||
|
if (t1)
|
||||||
|
{
|
||||||
|
// setStyle("-fx-font-weight: bold; -fx-text-fill: red;");
|
||||||
|
setEffect(invalidEffect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;");
|
||||||
|
setEffect(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private BooleanBinding maskCheck()
|
||||||
|
{
|
||||||
|
return new BooleanBinding()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
super.bind(textProperty(), mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean computeValue()
|
||||||
|
{
|
||||||
|
return !textProperty().get().matches(mask.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private BooleanBinding minLengthCheck()
|
||||||
|
{
|
||||||
|
return new BooleanBinding()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
super.bind(textProperty(), minLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean computeValue()
|
||||||
|
{
|
||||||
|
return textProperty().get().length() < minLength.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private BooleanBinding maxLengthCheck()
|
||||||
|
{
|
||||||
|
return new BooleanBinding()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
super.bind(textProperty(), maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean computeValue()
|
||||||
|
{
|
||||||
|
return textProperty().get().length() > maxLength.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ public class TransactionsListItem
|
||||||
Address address = null;
|
Address address = null;
|
||||||
if (valueSentToMe.compareTo(BigInteger.ZERO) == 0)
|
if (valueSentToMe.compareTo(BigInteger.ZERO) == 0)
|
||||||
{
|
{
|
||||||
amount.set("-" + BtcFormatter.satoshiToString(valueSentFromMe));
|
amount.set("-" + BtcFormatter.formatSatoshis(valueSentFromMe));
|
||||||
|
|
||||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||||
{
|
{
|
||||||
|
@ -62,7 +62,7 @@ public class TransactionsListItem
|
||||||
}
|
}
|
||||||
else if (valueSentFromMe.compareTo(BigInteger.ZERO) == 0)
|
else if (valueSentFromMe.compareTo(BigInteger.ZERO) == 0)
|
||||||
{
|
{
|
||||||
amount.set(BtcFormatter.satoshiToString(valueSentToMe));
|
amount.set(BtcFormatter.formatSatoshis(valueSentToMe));
|
||||||
type.set("Received with");
|
type.set("Received with");
|
||||||
|
|
||||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||||
|
@ -83,7 +83,7 @@ public class TransactionsListItem
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
amount.set(BtcFormatter.satoshiToString(valueSentToMe.subtract(valueSentFromMe)));
|
amount.set(BtcFormatter.formatSatoshis(valueSentToMe.subtract(valueSentFromMe)));
|
||||||
|
|
||||||
boolean outgoing = false;
|
boolean outgoing = false;
|
||||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||||
|
|
|
@ -83,7 +83,7 @@ public class WithdrawalController implements Initializable, ChildController, Hib
|
||||||
|
|
||||||
if (BigInteger.ZERO.compareTo(newValue.getBalance()) <= 0)
|
if (BigInteger.ZERO.compareTo(newValue.getBalance()) <= 0)
|
||||||
{
|
{
|
||||||
amountTextField.setText(BtcFormatter.satoshiToString(newValue.getBalance()));
|
amountTextField.setText(BtcFormatter.formatSatoshis(newValue.getBalance()));
|
||||||
withdrawFromTextField.setText(newValue.getAddressEntry().getAddressString());
|
withdrawFromTextField.setText(newValue.getAddressEntry().getAddressString());
|
||||||
changeAddressTextField.setText(newValue.getAddressEntry().getAddressString());
|
changeAddressTextField.setText(newValue.getAddressEntry().getAddressString());
|
||||||
}
|
}
|
||||||
|
@ -174,8 +174,8 @@ public class WithdrawalController implements Initializable, ChildController, Hib
|
||||||
"Amount: " + amountTextField.getText() + " BTC\n" +
|
"Amount: " + amountTextField.getText() + " BTC\n" +
|
||||||
"Sending address: " + withdrawFromTextField.getText() + "\n" +
|
"Sending address: " + withdrawFromTextField.getText() + "\n" +
|
||||||
"Receiving address: " + withdrawToTextField.getText() + "\n" +
|
"Receiving address: " + withdrawToTextField.getText() + "\n" +
|
||||||
"Transaction fee: " + BtcFormatter.satoshiToString(FeePolicy.TX_FEE_depr) + "\n" +
|
"Transaction fee: " + BtcFormatter.formatSatoshis(FeePolicy.TX_FEE) + "\n" +
|
||||||
"You receive in total: " + BtcFormatter.satoshiToString(amount.subtract(FeePolicy.TX_FEE_depr)) + " BTC\n\n" +
|
"You receive in total: " + BtcFormatter.formatSatoshis(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
|
||||||
"Are you sure you withdraw that amount?");
|
"Are you sure you withdraw that amount?");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class WithdrawalListItem
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
if (balance != null)
|
if (balance != null)
|
||||||
{
|
{
|
||||||
balanceLabel.setText(BtcFormatter.satoshiToString(balance));
|
balanceLabel.setText(BtcFormatter.formatSatoshis(balance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ public class MarketController implements Initializable, NavigationController, Ch
|
||||||
public void initialize(URL url, ResourceBundle rb)
|
public void initialize(URL url, ResourceBundle rb)
|
||||||
{
|
{
|
||||||
navigateToView(NavigationItem.ORDER_BOOK);
|
navigateToView(NavigationItem.ORDER_BOOK);
|
||||||
|
|
||||||
navigateToView(NavigationItem.TAKE_OFFER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
}
|
}
|
||||||
acceptedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(settings.getAcceptedCountries()));
|
acceptedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(settings.getAcceptedCountries()));
|
||||||
acceptedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(settings.getAcceptedLanguageLocales()));
|
acceptedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(settings.getAcceptedLanguageLocales()));
|
||||||
feeLabel.setText(BtcFormatter.satoshiToString(FeePolicy.CREATE_OFFER_FEE_depr));
|
feeLabel.setText(BtcFormatter.formatSatoshis(FeePolicy.CREATE_OFFER_FEE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int collateral = (int) (BitSquareConverter.stringToDouble2(collateralTextField.getText()));
|
int collateral = (int) (BitSquareConverter.stringToDouble(collateralTextField.getText()));
|
||||||
Arbitrator arbitrator = settings.getRandomArbitrator(collateral, getAmountAsBI());
|
Arbitrator arbitrator = settings.getRandomArbitrator(collateral, getAmountAsBI());
|
||||||
if (arbitrator == null)
|
if (arbitrator == null)
|
||||||
{
|
{
|
||||||
|
@ -189,7 +189,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
{
|
{
|
||||||
offer = new Offer(user.getMessagePubKeyAsHex(),
|
offer = new Offer(user.getMessagePubKeyAsHex(),
|
||||||
direction,
|
direction,
|
||||||
BitSquareConverter.stringToDouble2(priceTextField.getText()),
|
BitSquareConverter.stringToDouble(priceTextField.getText()),
|
||||||
BtcFormatter.stringValueToSatoshis(amountTextField.getText()),
|
BtcFormatter.stringValueToSatoshis(amountTextField.getText()),
|
||||||
BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()),
|
BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()),
|
||||||
user.getCurrentBankAccount().getBankAccountType(),
|
user.getCurrentBankAccount().getBankAccountType(),
|
||||||
|
@ -202,7 +202,9 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
settings.getAcceptedLanguageLocales());
|
settings.getAcceptedLanguageLocales());
|
||||||
|
|
||||||
|
|
||||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
try
|
||||||
|
{
|
||||||
|
walletFacade.payCreateOfferFee(offer.getId(), new FutureCallback<Transaction>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
||||||
|
@ -231,10 +233,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t);
|
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t);
|
||||||
placeOfferButton.setDisable(false);
|
placeOfferButton.setDisable(false);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
try
|
|
||||||
{
|
|
||||||
walletFacade.payCreateOfferFee(offer.getId(), callback);
|
|
||||||
placeOfferButton.setDisable(true);
|
placeOfferButton.setDisable(true);
|
||||||
} catch (InsufficientMoneyException e1)
|
} catch (InsufficientMoneyException e1)
|
||||||
{
|
{
|
||||||
|
@ -279,8 +278,8 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
|
|
||||||
private double getVolume()
|
private double getVolume()
|
||||||
{
|
{
|
||||||
double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
double amountAsDouble = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
|
double priceAsDouble = BitSquareConverter.stringToDouble(priceTextField.getText());
|
||||||
return amountAsDouble * priceAsDouble;
|
return amountAsDouble * priceAsDouble;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,10 +292,10 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||||
@SuppressWarnings("UnusedAssignment")
|
@SuppressWarnings("UnusedAssignment")
|
||||||
private boolean inputValid()
|
private boolean inputValid()
|
||||||
{
|
{
|
||||||
double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
|
double priceAsDouble = BitSquareConverter.stringToDouble(priceTextField.getText());
|
||||||
double minAmountAsDouble = BitSquareConverter.stringToDouble2(minAmountTextField.getText());
|
double minAmountAsDouble = BitSquareConverter.stringToDouble(minAmountTextField.getText());
|
||||||
double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
double amountAsDouble = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
double collateralAsDouble = BitSquareConverter.stringToDouble2(collateralTextField.getText());
|
double collateralAsDouble = BitSquareConverter.stringToDouble(collateralTextField.getText());
|
||||||
|
|
||||||
return priceAsDouble > 0 &&
|
return priceAsDouble > 0 &&
|
||||||
amountAsDouble > 0 &&
|
amountAsDouble > 0 &&
|
||||||
|
|
|
@ -13,7 +13,7 @@ import io.bitsquare.gui.MainController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
import io.bitsquare.gui.NavigationItem;
|
import io.bitsquare.gui.NavigationItem;
|
||||||
import io.bitsquare.gui.market.createOffer.CreateOfferController;
|
import io.bitsquare.gui.market.createOffer.CreateOfferController;
|
||||||
import io.bitsquare.gui.market.trade.TakerTradeController;
|
import io.bitsquare.gui.market.trade.TakerOfferController;
|
||||||
import io.bitsquare.gui.popups.Popups;
|
import io.bitsquare.gui.popups.Popups;
|
||||||
import io.bitsquare.gui.util.BitSquareConverter;
|
import io.bitsquare.gui.util.BitSquareConverter;
|
||||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||||
|
@ -115,7 +115,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
orderBook.init();
|
orderBook.init();
|
||||||
|
|
||||||
// setup table
|
// init table
|
||||||
setCountryColumnCellFactory();
|
setCountryColumnCellFactory();
|
||||||
setBankAccountTypeColumnCellFactory();
|
setBankAccountTypeColumnCellFactory();
|
||||||
setDirectionColumnCellFactory();
|
setDirectionColumnCellFactory();
|
||||||
|
@ -223,16 +223,16 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
Action response = Popups.openErrorPopup("Registration fee not confirmed yet", "The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation.");
|
Action response = Popups.openErrorPopup("Registration fee not confirmed yet", "The registration fee transaction has not been confirmed yet in the blockchain. Please wait until it has at least 1 confirmation.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action response = Popups.openErrorPopup("Missing registration fee", "You have not funded the full registration fee of " + BtcFormatter.satoshiToString(FeePolicy.ACCOUNT_REGISTRATION_FEE_depr) + " BTC.");
|
Action response = Popups.openErrorPopup("Missing registration fee", "You have not funded the full registration fee of " + BtcFormatter.formatSatoshis(FeePolicy.ACCOUNT_REGISTRATION_FEE) + " BTC.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,11 +255,11 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
|
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Not registered yet", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
|
||||||
if (registrationMissingAction == settingsCommandLink)
|
if (registrationMissingAction == settingsCommandLink)
|
||||||
{
|
{
|
||||||
MainController.INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
||||||
}
|
}
|
||||||
else if (registrationMissingAction == depositFeeCommandLink)
|
else if (registrationMissingAction == depositFeeCommandLink)
|
||||||
{
|
{
|
||||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
}
|
}
|
||||||
else if (registrationMissingAction == sendRegistrationCommandLink)
|
else if (registrationMissingAction == sendRegistrationCommandLink)
|
||||||
{
|
{
|
||||||
|
@ -315,7 +315,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
Action response = Popups.openErrorPopup("No funds for a trade", "You have to add some funds before you create a new offer.");
|
Action response = Popups.openErrorPopup("No funds for a trade", "You have to add some funds before you create a new offer.");
|
||||||
if (response == Dialog.Actions.OK)
|
if (response == Dialog.Actions.OK)
|
||||||
{
|
{
|
||||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
if (isRegistered())
|
if (isRegistered())
|
||||||
{
|
{
|
||||||
TakerTradeController takerTradeController = (TakerTradeController) navigationController.navigateToView(NavigationItem.TAKE_OFFER);
|
TakerOfferController takerOfferController = (TakerOfferController) navigationController.navigateToView(NavigationItem.TAKE_OFFER);
|
||||||
|
|
||||||
BigInteger requestedAmount;
|
BigInteger requestedAmount;
|
||||||
if (!"".equals(amount.getText()))
|
if (!"".equals(amount.getText()))
|
||||||
|
@ -337,8 +337,8 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
else
|
else
|
||||||
requestedAmount = offer.getAmount();
|
requestedAmount = offer.getAmount();
|
||||||
|
|
||||||
if (takerTradeController != null)
|
if (takerOfferController != null)
|
||||||
takerTradeController.initWithData(offer, requestedAmount);
|
takerOfferController.initWithData(offer, requestedAmount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -541,7 +541,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
} catch (ParseException e)
|
} catch (ParseException e)
|
||||||
{
|
{
|
||||||
amount.setText(oldValue);
|
amount.setText(oldValue);
|
||||||
d = BitSquareConverter.stringToDouble2(oldValue);
|
d = BitSquareConverter.stringToDouble(oldValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import io.bitsquare.gui.components.ValidatedTextField?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
@ -8,7 +9,7 @@
|
||||||
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
|
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
|
||||||
<panes>
|
<panes>
|
||||||
|
|
||||||
<TitledPane fx:id="profileTitledPane" text="Offer details">
|
<TitledPane fx:id="takeOfferTitledPane" text="Offer details">
|
||||||
<ScrollPane fitToWidth="true">
|
<ScrollPane fitToWidth="true">
|
||||||
<GridPane hgap="5.0" vgap="5.0">
|
<GridPane hgap="5.0" vgap="5.0">
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -18,43 +19,41 @@
|
||||||
<Label text="Take offer:" id="headline-label"/>
|
<Label text="Take offer:" id="headline-label"/>
|
||||||
|
|
||||||
<Label text="Amount (BTC):" GridPane.rowIndex="1"/>
|
<Label text="Amount (BTC):" GridPane.rowIndex="1"/>
|
||||||
<TextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
|
<ValidatedTextField fx:id="amountTextField" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/>
|
<Label text="Price (EUR/BTC):" GridPane.rowIndex="2"/>
|
||||||
<TextField fx:id="priceTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
<TextField fx:id="priceTextField" editable="false" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Volume (EUR):" GridPane.rowIndex="3"/>
|
<Label text="Volume (EUR):" GridPane.rowIndex="3"/>
|
||||||
<TextField fx:id="volumeTextField" GridPane.rowIndex="3" GridPane.columnIndex="1"/>
|
<TextField fx:id="volumeTextField" editable="false" GridPane.rowIndex="3" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Collateral (BTC):" GridPane.rowIndex="4"/>
|
<Label text="Collateral (BTC):" GridPane.rowIndex="4"/>
|
||||||
<TextField fx:id="collateralTextField" GridPane.rowIndex="4" GridPane.columnIndex="1"/>
|
<TextField fx:id="collateralTextField" editable="false" GridPane.rowIndex="4" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Fee (BTC):" GridPane.rowIndex="5"/>
|
<Label text="Fee (BTC):" GridPane.rowIndex="5"/>
|
||||||
<TextField fx:id="feeTextField" GridPane.rowIndex="5" GridPane.columnIndex="1"/>
|
<TextField fx:id="feeTextField" editable="false" GridPane.rowIndex="5" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Total (BTC):" GridPane.rowIndex="6"/>
|
<Label text="Total (BTC):" GridPane.rowIndex="6"/>
|
||||||
<TextField fx:id="totalTextField" GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
<TextField fx:id="totalTextField" editable="false" GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
|
||||||
<Button text="Take offer and pay" onAction="#onTakeOffer" defaultButton="true" GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
|
||||||
|
|
||||||
|
<Button fx:id="takeOfferButton" text="Take offer and pay" onAction="#onTakeOffer" defaultButton="true" GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Offer details:" id="headline-label" GridPane.rowIndex="8"/>
|
<Label text="Offer details:" id="headline-label" GridPane.rowIndex="8"/>
|
||||||
|
|
||||||
<Label text="Bank account type:" GridPane.rowIndex="9"/>
|
<Label text="Bank account type:" GridPane.rowIndex="9"/>
|
||||||
<TextField fx:id="bankAccountTypeTextField" GridPane.rowIndex="9" GridPane.columnIndex="1"/>
|
<TextField fx:id="bankAccountTypeTextField" editable="false" GridPane.rowIndex="9" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Country:" GridPane.rowIndex="10"/>
|
<Label text="Country:" GridPane.rowIndex="10"/>
|
||||||
<TextField fx:id="countryTextField" GridPane.rowIndex="10" GridPane.columnIndex="1"/>
|
<TextField fx:id="countryTextField" editable="false" GridPane.rowIndex="10" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Arbitrators:" GridPane.rowIndex="11"/>
|
<Label text="Arbitrators:" GridPane.rowIndex="11"/>
|
||||||
<TextField fx:id="arbitratorsTextField" GridPane.rowIndex="11" GridPane.columnIndex="1"/>
|
<TextField fx:id="arbitratorsTextField" editable="false" GridPane.rowIndex="11" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Supported languages:" GridPane.rowIndex="12"/>
|
<Label text="Supported languages:" GridPane.rowIndex="12"/>
|
||||||
<TextField fx:id="supportedLanguagesTextField" GridPane.rowIndex="12" GridPane.columnIndex="1"/>
|
<TextField fx:id="supportedLanguagesTextField" editable="false" GridPane.rowIndex="12" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
<Label text="Supported countries:" GridPane.rowIndex="13"/>
|
<Label text="Supported countries:" GridPane.rowIndex="13"/>
|
||||||
<TextField fx:id="supportedCountriesTextField" GridPane.rowIndex="13" GridPane.columnIndex="1"/>
|
<TextField fx:id="supportedCountriesTextField" editable="false" GridPane.rowIndex="13" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
|
@ -63,30 +62,110 @@
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
|
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
|
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</ScrollPane>
|
</ScrollPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
|
|
||||||
<TitledPane fx:id="payCollateralTitledPane" text="Wait for bank transfer">
|
<TitledPane fx:id="waitBankTxTitledPane" text="Wait for bank transfer">
|
||||||
|
<GridPane hgap="5.0" vgap="5.0">
|
||||||
|
<padding>
|
||||||
|
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||||
|
</padding>
|
||||||
|
|
||||||
|
<Label fx:id="headLineLabel" text="Deposit transaction published" id="headline-label"/>
|
||||||
|
|
||||||
|
<Label text="Status information:" GridPane.rowIndex="1" GridPane.valignment="TOP"/>
|
||||||
|
<Label fx:id="infoLabel" GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.valignment="TOP"/>
|
||||||
|
|
||||||
|
<Label text="Deposit transaction ID:" GridPane.rowIndex="2"/>
|
||||||
|
<TextField fx:id="depositTxIdTextField" editable="false" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<Button fx:id="receivedFiatButton" text="I have received the money at my bank account" onAction="#onReceivedFiat" defaultButton="true" disable="true" GridPane.rowIndex="3"
|
||||||
|
GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="RIGHT" hgrow="NEVER" minWidth="10.0"/>
|
||||||
|
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
</rowConstraints>
|
||||||
|
|
||||||
|
</GridPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
|
|
||||||
<TitledPane fx:id="payCollateralTitledPane" text="Summary">
|
<TitledPane fx:id="summaryTitledPane" text="Summary">
|
||||||
|
<GridPane hgap="5.0" vgap="5.0">
|
||||||
|
<padding>
|
||||||
|
<Insets left="10" right="10" top="10" bottom="10"/>
|
||||||
|
</padding>
|
||||||
|
|
||||||
|
<Label text="Trade completed" id="headline-label"/>
|
||||||
|
<Label text="Summary:" GridPane.rowIndex="1"/>
|
||||||
|
|
||||||
|
<Label text="You have sold (BTC):" GridPane.rowIndex="2"/>
|
||||||
|
<ValidatedTextField fx:id="summaryPaidTextField" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<Label text="You have received (EUR):" GridPane.rowIndex="3"/>
|
||||||
|
<TextField fx:id="summaryReceivedTextField" editable="false" GridPane.rowIndex="3" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
|
||||||
|
<Label text="Details:" GridPane.rowIndex="4"/>
|
||||||
|
|
||||||
|
<Label text="Total fees (take offer fee + tx fee):" GridPane.rowIndex="5"/>
|
||||||
|
<TextField fx:id="summaryFeesTextField" editable="false" GridPane.rowIndex="5" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<Label text="Refunded collateral (BTC):" GridPane.rowIndex="6"/>
|
||||||
|
<TextField fx:id="summaryCollateralTextField" editable="false" GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<Label text="Deposit transaction ID:" GridPane.rowIndex="7"/>
|
||||||
|
<TextField fx:id="summaryDepositTxIdTextField" editable="false" GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<Label text="Payout transaction ID:" GridPane.rowIndex="8"/>
|
||||||
|
<TextField fx:id="summaryPayoutTxIdTextField" editable="false" GridPane.rowIndex="8" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
|
||||||
|
<Button text="Close" onAction="#onClose" defaultButton="true" GridPane.rowIndex="9" GridPane.columnIndex="1"/>
|
||||||
|
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
|
||||||
|
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="NEVER"/>
|
||||||
|
</rowConstraints>
|
||||||
|
|
||||||
|
</GridPane>
|
||||||
</TitledPane>
|
</TitledPane>
|
||||||
|
|
||||||
</panes>
|
</panes>
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
package io.bitsquare.gui.market.trade;
|
package io.bitsquare.gui.market.trade;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.btc.AddressEntry;
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.btc.FeePolicy;
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.currency.Bitcoin;
|
|
||||||
import io.bitsquare.currency.Fiat;
|
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
|
import io.bitsquare.gui.NavigationItem;
|
||||||
|
import io.bitsquare.gui.components.ValidatedTextField;
|
||||||
|
import io.bitsquare.gui.popups.Popups;
|
||||||
import io.bitsquare.gui.util.BitSquareConverter;
|
import io.bitsquare.gui.util.BitSquareConverter;
|
||||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||||
import io.bitsquare.locale.CountryUtil;
|
import io.bitsquare.gui.util.BitSquareValidator;
|
||||||
import io.bitsquare.locale.LanguageUtil;
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.trade.Direction;
|
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.Trading;
|
import io.bitsquare.trade.Trading;
|
||||||
import io.bitsquare.user.Arbitrator;
|
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Currency;
|
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Accordion;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.control.TitledPane;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -38,18 +36,29 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
private final Trading trading;
|
private final Trading trading;
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
private final MessageFacade messageFacade;
|
private final MessageFacade messageFacade;
|
||||||
|
|
||||||
private NavigationController navigationController;
|
private NavigationController navigationController;
|
||||||
private Offer offer;
|
private Offer offer;
|
||||||
private Bitcoin requestedAmount;
|
private BigInteger requestedAmount;
|
||||||
|
private String tradeId;
|
||||||
|
private String depositTxId;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private AnchorPane rootContainer;
|
||||||
@FXML
|
@FXML
|
||||||
private Accordion accordion;
|
private Accordion accordion;
|
||||||
@FXML
|
@FXML
|
||||||
private TitledPane profileTitledPane;
|
private TitledPane takeOfferTitledPane, waitBankTxTitledPane, summaryTitledPane;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField amountTextField, priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField,
|
private ValidatedTextField amountTextField;
|
||||||
arbitratorsTextField, supportedLanguagesTextField, supportedCountriesTextField;
|
@FXML
|
||||||
|
private TextField priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField,
|
||||||
|
arbitratorsTextField, supportedLanguagesTextField, supportedCountriesTextField, depositTxIdTextField, summaryPaidTextField, summaryReceivedTextField, summaryFeesTextField,
|
||||||
|
summaryCollateralTextField, summaryDepositTxIdTextField, summaryPayoutTxIdTextField;
|
||||||
|
@FXML
|
||||||
|
private Label infoLabel, headLineLabel;
|
||||||
|
@FXML
|
||||||
|
private Button takeOfferButton, receivedFiatButton;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
|
@ -61,23 +70,6 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
this.trading = trading;
|
this.trading = trading;
|
||||||
this.walletFacade = walletFacade;
|
this.walletFacade = walletFacade;
|
||||||
this.messageFacade = messageFacade;
|
this.messageFacade = messageFacade;
|
||||||
|
|
||||||
|
|
||||||
Offer offer = new Offer("m",
|
|
||||||
Direction.BUY,
|
|
||||||
111,
|
|
||||||
new BigInteger("100000000"),
|
|
||||||
new BigInteger("10000000"),
|
|
||||||
BankAccountType.OK_PAY,
|
|
||||||
Currency.getInstance("EUR"),
|
|
||||||
CountryUtil.getDefaultCountry(),
|
|
||||||
"baid",
|
|
||||||
new Arbitrator(),
|
|
||||||
10,
|
|
||||||
CountryUtil.getAllCountriesFor(CountryUtil.getAllRegions().get(0)),
|
|
||||||
LanguageUtil.getAllLanguageLocales());
|
|
||||||
|
|
||||||
initWithData(offer, new Bitcoin("50000000"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,10 +77,13 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
// Public methods
|
// Public methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void initWithData(Offer offer, Bitcoin requestedAmount)
|
public void initWithData(Offer offer, BigInteger requestedAmount)
|
||||||
{
|
{
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
this.requestedAmount = requestedAmount.isZero() ? new Bitcoin(offer.getAmount()) : requestedAmount;
|
this.requestedAmount = requestedAmount.compareTo(BigInteger.ZERO) == 0 ? offer.getAmount() : requestedAmount;
|
||||||
|
|
||||||
|
if (amountTextField != null)
|
||||||
|
applyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -98,17 +93,18 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb)
|
public void initialize(URL url, ResourceBundle rb)
|
||||||
{
|
{
|
||||||
accordion.setExpandedPane(profileTitledPane);
|
accordion.setExpandedPane(takeOfferTitledPane);
|
||||||
|
}
|
||||||
|
|
||||||
if (offer != null && requestedAmount != null)
|
public void applyData()
|
||||||
{
|
{
|
||||||
amountTextField.setText(requestedAmount.getFormattedValue());
|
amountTextField.setText(BtcFormatter.formatSatoshis(requestedAmount));
|
||||||
amountTextField.setPromptText(new Bitcoin(offer.getMinAmount()).getFormattedValue() + " - " + new Bitcoin(offer.getAmount()).getFormattedValue());
|
amountTextField.setPromptText(BtcFormatter.formatSatoshis(offer.getMinAmount()) + " - " + BtcFormatter.formatSatoshis(offer.getAmount()));
|
||||||
priceTextField.setText(new Fiat(offer.getPrice()).getFormattedValue());
|
priceTextField.setText(BitSquareFormatter.formatPrice(offer.getPrice()));
|
||||||
applyVolume();
|
applyVolume();
|
||||||
applyCollateral();
|
applyCollateral();
|
||||||
applyTotal();
|
applyTotal();
|
||||||
feeTextField.setText(getFee().getFormattedValue());
|
feeTextField.setText(BtcFormatter.formatSatoshis(getFee()));
|
||||||
totalTextField.setText(getFormattedTotal());
|
totalTextField.setText(getFormattedTotal());
|
||||||
|
|
||||||
bankAccountTypeTextField.setText(offer.getBankAccountType().toString());
|
bankAccountTypeTextField.setText(offer.getBankAccountType().toString());
|
||||||
|
@ -127,7 +123,6 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -145,19 +140,103 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// GUI handlers
|
// GUI handlers
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@FXML
|
||||||
public void onTakeOffer()
|
public void onTakeOffer()
|
||||||
{
|
{
|
||||||
|
AddressEntry addressEntry = walletFacade.getAddressInfoByTradeID(offer.getId());
|
||||||
|
BigInteger amount = BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||||
|
// TODO more validation (fee payment, blacklist,...)
|
||||||
|
if (amountTextField.isInvalid())
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Invalid input", "The requested amount you entered is not a valid amount.");
|
||||||
|
}
|
||||||
|
else if (BitSquareValidator.tradeAmountOutOfRange(amount, offer))
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Invalid input", "The requested amount you entered is outside of the range of the offered amount.");
|
||||||
|
}
|
||||||
|
else if (addressEntry == null || getTotal().compareTo(walletFacade.getBalanceForAddress(addressEntry.getAddress())) > 0)
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Insufficient money", "You don't have enough funds for that trade.");
|
||||||
|
}
|
||||||
|
else if (trading.isOfferAlreadyInTrades(offer))
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Offer previously accepted", "You have that offer already taken. Open the offer section to find that trade.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
takeOfferButton.setDisable(true);
|
||||||
|
amountTextField.setEditable(false);
|
||||||
|
trading.takeOffer(amount, offer, new TakerAsSellerProtocolListener()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDepositTxPublished(String depositTxId)
|
||||||
|
{
|
||||||
|
setDepositTxId(depositTxId);
|
||||||
|
accordion.setExpandedPane(waitBankTxTitledPane);
|
||||||
|
infoLabel.setText("Deposit transaction published by offerer.\n" +
|
||||||
|
"As soon as the offerer starts the \n" +
|
||||||
|
"Bank transfer, you will get informed.");
|
||||||
|
depositTxIdTextField.setText(depositTxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBankTransferInited(String tradeId)
|
||||||
|
{
|
||||||
|
setTradeId(tradeId);
|
||||||
|
headLineLabel.setText("Bank transfer inited");
|
||||||
|
infoLabel.setText("Check your bank account and continue \n" +
|
||||||
|
"when you have received the money.");
|
||||||
|
receivedFiatButton.setDisable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTradeCompleted(Trade trade, String payoutTxId)
|
||||||
|
{
|
||||||
|
accordion.setExpandedPane(summaryTitledPane);
|
||||||
|
summaryPaidTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount()));
|
||||||
|
summaryReceivedTextField.setText(BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount())));
|
||||||
|
summaryFeesTextField.setText(BtcFormatter.formatSatoshis(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||||
|
summaryCollateralTextField.setText(BtcFormatter.formatSatoshis(trade.getCollateralAmount()));
|
||||||
|
summaryDepositTxIdTextField.setText(depositTxId);
|
||||||
|
summaryPayoutTxIdTextField.setText(payoutTxId);
|
||||||
|
}
|
||||||
|
}, (task) -> {
|
||||||
|
//log.trace(task.toString());
|
||||||
|
}, throwable -> {
|
||||||
|
log.error(throwable.toString());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void onReceivedFiat()
|
||||||
|
{
|
||||||
|
trading.releaseBTC(tradeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
TabPane tabPane = ((TabPane) (rootContainer.getParent().getParent()));
|
||||||
|
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
|
||||||
|
|
||||||
|
navigationController.navigateToView(NavigationItem.ORDER_BOOK);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Private methods
|
// Private methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
private void applyCollateral()
|
private void applyCollateral()
|
||||||
{
|
{
|
||||||
collateralTextField.setText(getFormattedCollateral());
|
collateralTextField.setText(getFormattedCollateral());
|
||||||
|
@ -181,18 +260,23 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
|
|
||||||
private String getFormattedTotal()
|
private String getFormattedTotal()
|
||||||
{
|
{
|
||||||
return BitSquareFormatter.formatVolume(getTotal());
|
return BitSquareFormatter.formatVolume(getTotal().doubleValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFormattedCollateral()
|
private String getFormattedCollateral()
|
||||||
{
|
{
|
||||||
return BtcFormatter.satoshiToString(getCollateralInSatoshis());
|
return BtcFormatter.formatSatoshis(getCollateralInSatoshis());
|
||||||
}
|
}
|
||||||
|
|
||||||
// values
|
// values
|
||||||
private double getAmountAsDouble()
|
private double getAmountAsDouble()
|
||||||
{
|
{
|
||||||
return BitSquareConverter.stringToDouble2(amountTextField.getText());
|
return BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigInteger getAmountInSatoshis()
|
||||||
|
{
|
||||||
|
return BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getVolume()
|
private double getVolume()
|
||||||
|
@ -200,22 +284,32 @@ public class TakerOfferController implements Initializable, ChildController
|
||||||
return offer.getPrice() * getAmountAsDouble();
|
return offer.getPrice() * getAmountAsDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitcoin getFee()
|
private BigInteger getFee()
|
||||||
{
|
{
|
||||||
return FeePolicy.TAKE_OFFER_FEE.addBitcoin(FeePolicy.TX_FEE);
|
return FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getTotal()
|
private BigInteger getTotal()
|
||||||
{
|
{
|
||||||
return getFee().doubleValue() + getVolume();
|
return getFee().add(getAmountInSatoshis()).add(getCollateralInSatoshis());
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigInteger getCollateralInSatoshis()
|
private BigInteger getCollateralInSatoshis()
|
||||||
{
|
{
|
||||||
double amount = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
double amount = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
||||||
return BtcFormatter.doubleValueToSatoshis(resultDouble);
|
return BtcFormatter.doubleValueToSatoshis(resultDouble);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setTradeId(String tradeId)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepositTxId(String depositTxId)
|
||||||
|
{
|
||||||
|
this.depositTxId = depositTxId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,10 @@ import io.bitsquare.gui.util.BitSquareConverter;
|
||||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||||
import io.bitsquare.gui.util.FormBuilder;
|
import io.bitsquare.gui.util.FormBuilder;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
import io.bitsquare.trade.Trading;
|
import io.bitsquare.trade.Trading;
|
||||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
|
|
||||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocolListener;
|
|
||||||
import io.bitsquare.util.Utilities;
|
import io.bitsquare.util.Utilities;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -149,21 +146,21 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
row = -1;
|
row = -1;
|
||||||
|
|
||||||
FormBuilder.addHeaderLabel(gridPane, "Take offer:", ++row);
|
FormBuilder.addHeaderLabel(gridPane, "Take offer:", ++row);
|
||||||
amountTextField = FormBuilder.addTextField(gridPane, "Amount (BTC):", BtcFormatter.satoshiToString(requestedAmount), ++row, true, true);
|
amountTextField = FormBuilder.addTextField(gridPane, "Amount (BTC):", BtcFormatter.formatSatoshis(requestedAmount), ++row, true, true);
|
||||||
amountTextField.textProperty().addListener(e -> {
|
amountTextField.textProperty().addListener(e -> {
|
||||||
applyVolume();
|
applyVolume();
|
||||||
applyCollateral();
|
applyCollateral();
|
||||||
totalToPayLabel.setText(getTotalToPayAsString());
|
totalToPayLabel.setText(getTotalToPayAsString());
|
||||||
|
|
||||||
});
|
});
|
||||||
Label amountRangeLabel = new Label("(" + BtcFormatter.satoshiToString(offer.getMinAmount()) + " - " + BtcFormatter.satoshiToString(offer.getAmount()) + ")");
|
Label amountRangeLabel = new Label("(" + BtcFormatter.formatSatoshis(offer.getMinAmount()) + " - " + BtcFormatter.formatSatoshis(offer.getAmount()) + ")");
|
||||||
gridPane.add(amountRangeLabel, 2, row);
|
gridPane.add(amountRangeLabel, 2, row);
|
||||||
|
|
||||||
FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", BitSquareFormatter.formatPrice(offer.getPrice()), ++row);
|
FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", BitSquareFormatter.formatPrice(offer.getPrice()), ++row);
|
||||||
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
||||||
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
|
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
|
||||||
applyCollateral();
|
applyCollateral();
|
||||||
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", BtcFormatter.satoshiToString(FeePolicy.TAKE_OFFER_FEE_depr.add(FeePolicy.TX_FEE_depr)), ++row);
|
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", BtcFormatter.formatSatoshis(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)), ++row);
|
||||||
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPayAsString(), ++row);
|
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPayAsString(), ++row);
|
||||||
|
|
||||||
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
|
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
|
||||||
|
@ -228,18 +225,18 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trading.isOfferTradable(offer))
|
//if (trading.isOfferAlreadyInTrades(offer))
|
||||||
{
|
// {
|
||||||
trade = trading.createTrade(offer);
|
trade = trading.createTrade(offer);
|
||||||
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||||
|
|
||||||
/* if (!blockChainFacade.verifyAccountRegistration(offer.getAccountID()))
|
/* if (!blockChainFacade.verifyAccountRegistration(offer.getAccountId()))
|
||||||
{
|
{
|
||||||
Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements.");
|
Popups.openErrorPopup("Offerers account ID not valid", "Offerers registration tx is not found in blockchain or does not match the requirements.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountID()))
|
if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountId()))
|
||||||
{
|
{
|
||||||
Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted.");
|
Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted.");
|
||||||
return;
|
return;
|
||||||
|
@ -269,7 +266,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
||||||
gridPane.add(progressIndicatorHolder, 1, row);
|
gridPane.add(progressIndicatorHolder, 1, row);
|
||||||
|
|
||||||
TakerPaymentProtocol takerPaymentProtocol = trading.addTakerPaymentProtocol(trade, new TakerPaymentProtocolListener()
|
/*TakerPaymentProtocol takerPaymentProtocol = trading.addTakerPaymentProtocol(trade, new TakerPaymentProtocolListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onProgress(double progress)
|
public void onProgress(double progress)
|
||||||
|
@ -297,6 +294,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
statusTextField.setText("Offer fee payed. Send offerer payment transaction ID for confirmation.");
|
statusTextField.setText("Offer fee payed. Send offerer payment transaction ID for confirmation.");
|
||||||
break;
|
break;
|
||||||
} */
|
} */
|
||||||
|
/*
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -306,13 +304,13 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDepositTxPublished(String depositTxID)
|
public void onDepositTxPublishedMessage(String depositTxID)
|
||||||
{
|
{
|
||||||
buildDepositPublishedScreen(depositTxID);
|
buildDepositPublishedScreen(depositTxID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBankTransferInited(TradeMessage tradeMessage)
|
public void onBankTransferInitedMessage(TradeMessage tradeMessage)
|
||||||
{
|
{
|
||||||
buildBankTransferInitedScreen(tradeMessage);
|
buildBankTransferInitedScreen(tradeMessage);
|
||||||
}
|
}
|
||||||
|
@ -324,9 +322,9 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
takerPaymentProtocol.takeOffer();
|
takerPaymentProtocol.takeOffer(); */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
@SuppressWarnings("EmptyMethod")
|
||||||
private void updateTx(Trade trade)
|
private void updateTx(Trade trade)
|
||||||
|
@ -347,7 +345,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
// confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
|
// confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildBankTransferInitedScreen(TradeMessage tradeMessage)
|
private void buildBankTransferInitedScreen()
|
||||||
{
|
{
|
||||||
processStepBar.next();
|
processStepBar.next();
|
||||||
|
|
||||||
|
@ -355,13 +353,13 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
infoLabel.setText("Check your bank account and continue \nwhen you have received the money.");
|
infoLabel.setText("Check your bank account and continue \nwhen you have received the money.");
|
||||||
gridPane.add(nextButton, 1, ++row);
|
gridPane.add(nextButton, 1, ++row);
|
||||||
nextButton.setText("I have received the money at my bank");
|
nextButton.setText("I have received the money at my bank");
|
||||||
nextButton.setOnAction(e -> releaseBTC(tradeMessage));
|
nextButton.setOnAction(e -> releaseBTC());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void releaseBTC(TradeMessage tradeMessage)
|
private void releaseBTC()
|
||||||
{
|
{
|
||||||
processStepBar.next();
|
processStepBar.next();
|
||||||
trading.releaseBTC(trade.getId(), tradeMessage);
|
trading.releaseBTC(trade.getId());
|
||||||
|
|
||||||
nextButton.setText("Close");
|
nextButton.setText("Close");
|
||||||
nextButton.setOnAction(e -> close());
|
nextButton.setOnAction(e -> close());
|
||||||
|
@ -372,19 +370,19 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
|
|
||||||
String fiatReceived = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
String fiatReceived = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
||||||
|
|
||||||
FormBuilder.addTextField(gridPane, "You have sold (BTC):", BtcFormatter.satoshiToString(trade.getTradeAmount()), ++row);
|
FormBuilder.addTextField(gridPane, "You have sold (BTC):", BtcFormatter.formatSatoshis(trade.getTradeAmount()), ++row);
|
||||||
if (takerIsSelling())
|
if (takerIsSelling())
|
||||||
{
|
{
|
||||||
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):\"", fiatReceived, ++row);
|
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):\"", fiatReceived, ++row);
|
||||||
FormBuilder.addTextField(gridPane, "Total fees (take offer fee + tx fee):", BtcFormatter.satoshiToString(FeePolicy.TAKE_OFFER_FEE_depr.add(FeePolicy.TX_FEE_depr)), ++row);
|
FormBuilder.addTextField(gridPane, "Total fees (take offer fee + tx fee):", BtcFormatter.formatSatoshis(FeePolicy.TAKE_OFFER_FEE.add(FeePolicy.TX_FEE)), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "Refunded collateral:", BtcFormatter.satoshiToString(trade.getCollateralAmount()), ++row);
|
FormBuilder.addTextField(gridPane, "Refunded collateral:", BtcFormatter.formatSatoshis(trade.getCollateralAmount()), ++row);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.satoshiToString(getCollateralInSatoshis()), ++row);
|
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis()), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.satoshiToString(offer.getAmount()), ++row);
|
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount()), ++row);
|
||||||
}
|
}
|
||||||
|
|
||||||
gridPane.add(nextButton, 1, ++row);
|
gridPane.add(nextButton, 1, ++row);
|
||||||
|
@ -440,18 +438,18 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
|
|
||||||
private double getVolume()
|
private double getVolume()
|
||||||
{
|
{
|
||||||
return offer.getPrice() * BitSquareConverter.stringToDouble2(amountTextField.getText());
|
return offer.getPrice() * BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTotalToPayAsString()
|
private String getTotalToPayAsString()
|
||||||
{
|
{
|
||||||
if (takerIsSelling())
|
if (takerIsSelling())
|
||||||
{
|
{
|
||||||
return BtcFormatter.satoshiToString(getTotalToPay());
|
return BtcFormatter.formatSatoshis(getTotalToPay());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BtcFormatter.satoshiToString(getTotalToPay()) + "\n" +
|
return BtcFormatter.formatSatoshis(getTotalToPay()) + "\n" +
|
||||||
BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency());
|
BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,22 +458,22 @@ public class TakerTradeController implements Initializable, ChildController
|
||||||
{
|
{
|
||||||
if (takerIsSelling())
|
if (takerIsSelling())
|
||||||
{
|
{
|
||||||
return getAmountInSatoshis().add(FeePolicy.TAKE_OFFER_FEE_depr).add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE_depr).add(getCollateralInSatoshis());
|
return getAmountInSatoshis().add(FeePolicy.TAKE_OFFER_FEE).add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE).add(getCollateralInSatoshis());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return FeePolicy.TAKE_OFFER_FEE_depr.add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE_depr).add(getCollateralInSatoshis());
|
return FeePolicy.TAKE_OFFER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(FeePolicy.TX_FEE).add(getCollateralInSatoshis());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyCollateral()
|
private void applyCollateral()
|
||||||
{
|
{
|
||||||
collateralTextField.setText(BtcFormatter.satoshiToString(getCollateralInSatoshis()));
|
collateralTextField.setText(BtcFormatter.formatSatoshis(getCollateralInSatoshis()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigInteger getCollateralInSatoshis()
|
private BigInteger getCollateralInSatoshis()
|
||||||
{
|
{
|
||||||
double amount = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
double amount = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||||
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
||||||
return BtcFormatter.doubleValueToSatoshis(resultDouble);
|
return BtcFormatter.doubleValueToSatoshis(resultDouble);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,38 @@ import org.slf4j.LoggerFactory;
|
||||||
public class OrdersController implements Initializable, ChildController, NavigationController
|
public class OrdersController implements Initializable, ChildController, NavigationController
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(OrdersController.class);
|
private static final Logger log = LoggerFactory.getLogger(OrdersController.class);
|
||||||
|
private static int SELECTED_TAB_INDEX = -1;
|
||||||
|
private static OrdersController INSTANCE;
|
||||||
private final Storage storage;
|
private final Storage storage;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private LazyLoadingTabPane tabPane;
|
private LazyLoadingTabPane tabPane;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Constructor
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private OrdersController(Storage storage)
|
private OrdersController(Storage storage)
|
||||||
{
|
{
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
INSTANCE = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public static OrdersController GET_INSTANCE()
|
||||||
|
{
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void setSelectedTabIndex(int index)
|
||||||
|
{
|
||||||
|
log.trace("setSelectedTabIndex " + index);
|
||||||
|
tabPane.setSelectedTabIndex(index);
|
||||||
|
storage.write(this.getClass().getName() + ".selectedTabIndex", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +58,7 @@ public class OrdersController implements Initializable, ChildController, Navigat
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb)
|
public void initialize(URL url, ResourceBundle rb)
|
||||||
{
|
{
|
||||||
|
log.trace("initialize ");
|
||||||
tabPane.initialize(this, storage, NavigationItem.OFFER.getFxmlUrl(), NavigationItem.PENDING_TRADE.getFxmlUrl(), NavigationItem.CLOSED_TRADE.getFxmlUrl());
|
tabPane.initialize(this, storage, NavigationItem.OFFER.getFxmlUrl(), NavigationItem.PENDING_TRADE.getFxmlUrl(), NavigationItem.CLOSED_TRADE.getFxmlUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +78,7 @@ public class OrdersController implements Initializable, ChildController, Navigat
|
||||||
tabPane.cleanup();
|
tabPane.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Interface implementation: NavigationController
|
// Interface implementation: NavigationController
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -68,7 +68,6 @@ public class OfferController implements Initializable, ChildController, Hibernat
|
||||||
@Override
|
@Override
|
||||||
public void setNavigationController(NavigationController navigationController)
|
public void setNavigationController(NavigationController navigationController)
|
||||||
{
|
{
|
||||||
log.debug("setNavigationController" + this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -35,7 +35,6 @@ import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.event.ActionEvent;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
@ -165,21 +164,16 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||||
|
|
||||||
initCopyIcons();
|
initCopyIcons();
|
||||||
|
|
||||||
if (tradeItems.size() > 0)
|
// select
|
||||||
{
|
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getCurrentPendingTrade().getId())).findFirst();
|
||||||
openTradesTable.getSelectionModel().select(0);
|
if (currentTradeItemOptional.isPresent())
|
||||||
}
|
openTradesTable.getSelectionModel().select(currentTradeItemOptional.get());
|
||||||
|
|
||||||
tradeItems.addListener(new ListChangeListener<PendingTradesListItem>()
|
tradeItems.addListener((ListChangeListener<PendingTradesListItem>) change -> {
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onChanged(Change<? extends PendingTradesListItem> change)
|
|
||||||
{
|
|
||||||
if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0)
|
if (openTradesTable.getSelectionModel().getSelectedItem() == null && tradeItems.size() > 0)
|
||||||
{
|
{
|
||||||
openTradesTable.getSelectionModel().select(0);
|
openTradesTable.getSelectionModel().select(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,13 +181,13 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||||
// GUI handlers
|
// GUI handlers
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void bankTransferInited(ActionEvent actionEvent)
|
public void bankTransferInited()
|
||||||
{
|
{
|
||||||
trading.onBankTransferInited(currentTrade.getId());
|
trading.onUIEventBankTransferInited(currentTrade.getId());
|
||||||
bankTransferInitedButton.setDisable(true);
|
bankTransferInitedButton.setDisable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close(ActionEvent actionEvent)
|
public void close()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,10 +322,10 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||||
|
|
||||||
String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
|
||||||
|
|
||||||
bankAccountTypeTextField.setText(BtcFormatter.satoshiToString(trade.getTradeAmount()));
|
bankAccountTypeTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount()));
|
||||||
holderNameTextField.setText(fiatPayed);
|
holderNameTextField.setText(fiatPayed);
|
||||||
primaryBankAccountIDTextField.setText(BtcFormatter.satoshiToString(FeePolicy.CREATE_OFFER_FEE_depr.add(FeePolicy.TX_FEE_depr)));
|
primaryBankAccountIDTextField.setText(BtcFormatter.formatSatoshis(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||||
secondaryBankAccountIDTextField.setText(BtcFormatter.satoshiToString(trade.getCollateralAmount()));
|
secondaryBankAccountIDTextField.setText(BtcFormatter.formatSatoshis(trade.getCollateralAmount()));
|
||||||
|
|
||||||
holderNameCopyIcon.setVisible(false);
|
holderNameCopyIcon.setVisible(false);
|
||||||
primaryBankAccountIDCopyIcon.setVisible(false);
|
primaryBankAccountIDCopyIcon.setVisible(false);
|
||||||
|
|
|
@ -14,22 +14,12 @@ public class BitSquareConverter
|
||||||
public static double stringToDouble(String input)
|
public static double stringToDouble(String input)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
|
||||||
return stringToDouble2(input);
|
|
||||||
} catch (NumberFormatException | NullPointerException e)
|
|
||||||
{
|
|
||||||
return Double.NEGATIVE_INFINITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param input String to be converted to a double. Both decimal points "." and "," are supported. Thousands separator is not supported.
|
|
||||||
* @return Returns a double value. Any invalid value throws an exception.
|
|
||||||
*/
|
|
||||||
public static double stringToDouble2(String input)
|
|
||||||
{
|
{
|
||||||
input = input.replace(",", ".");
|
input = input.replace(",", ".");
|
||||||
return Double.parseDouble(input);
|
return Double.parseDouble(input);
|
||||||
|
} catch (NumberFormatException | NullPointerException e)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package io.bitsquare.gui.util;
|
package io.bitsquare.gui.util;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.bank.BankAccountType;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import java.math.BigInteger;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.effect.BlurType;
|
import javafx.scene.effect.BlurType;
|
||||||
import javafx.scene.effect.DropShadow;
|
import javafx.scene.effect.DropShadow;
|
||||||
|
@ -13,6 +15,16 @@ public class BitSquareValidator
|
||||||
private static final Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);
|
private static final Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);
|
||||||
private static final String invalidStyle = "-fx-border-color: red";
|
private static final String invalidStyle = "-fx-border-color: red";
|
||||||
|
|
||||||
|
public static boolean tradeAmountOutOfRange(BigInteger tradeAmount, Offer offer)
|
||||||
|
{
|
||||||
|
return tradeAmount.compareTo(offer.getAmount()) > 0 || tradeAmount.compareTo(offer.getMinAmount()) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean greaterThanZero(BigInteger value)
|
||||||
|
{
|
||||||
|
return value.compareTo(BigInteger.ZERO) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static void textFieldsNotEmptyWithReset(TextField... textFields) throws ValidationException
|
public static void textFieldsNotEmptyWithReset(TextField... textFields) throws ValidationException
|
||||||
{
|
{
|
||||||
resetTextFields(textFields);
|
resetTextFields(textFields);
|
||||||
|
|
|
@ -187,7 +187,7 @@ public class ConfidenceDisplay
|
||||||
}
|
}
|
||||||
|
|
||||||
if (balanceTextField != null)
|
if (balanceTextField != null)
|
||||||
balanceTextField.setText(BtcFormatter.satoshiToString(balance));
|
balanceTextField.setText(BtcFormatter.formatSatoshis(balance));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConfidence(Transaction tx)
|
private void updateConfidence(Transaction tx)
|
||||||
|
|
|
@ -4,8 +4,14 @@ import com.google.inject.Inject;
|
||||||
import io.bitsquare.BitSquare;
|
import io.bitsquare.BitSquare;
|
||||||
import io.bitsquare.msg.listeners.*;
|
import io.bitsquare.msg.listeners.*;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
|
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
|
import io.bitsquare.trade.payment.offerer.messages.*;
|
||||||
|
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||||
|
import io.bitsquare.trade.payment.taker.listeners.GetPeerAddressListener;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.RequestTakeOfferMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||||
import io.bitsquare.user.Arbitrator;
|
import io.bitsquare.user.Arbitrator;
|
||||||
import io.bitsquare.util.DSAKeyUtil;
|
import io.bitsquare.util.DSAKeyUtil;
|
||||||
import io.bitsquare.util.FileUtil;
|
import io.bitsquare.util.FileUtil;
|
||||||
|
@ -46,9 +52,10 @@ public class MessageFacade
|
||||||
private final List<OrderBookListener> orderBookListeners = new ArrayList<>();
|
private final List<OrderBookListener> orderBookListeners = new ArrayList<>();
|
||||||
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
||||||
private final List<ArbitratorListener> arbitratorListeners = new ArrayList<>();
|
private final List<ArbitratorListener> arbitratorListeners = new ArrayList<>();
|
||||||
// //TODO change to map (key: offerID) instead of list (offererPaymentProtocols, takerPaymentProtocols)
|
|
||||||
private final List<TakerPaymentProtocol> takerPaymentProtocols = new ArrayList<>();
|
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||||
private final List<OffererPaymentProtocol> offererPaymentProtocols = new ArrayList<>();
|
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocols = new HashMap<>();
|
||||||
|
|
||||||
private final List<PingPeerListener> pingPeerListeners = new ArrayList<>();
|
private final List<PingPeerListener> pingPeerListeners = new ArrayList<>();
|
||||||
private final BooleanProperty isDirty = new SimpleBooleanProperty(false);
|
private final BooleanProperty isDirty = new SimpleBooleanProperty(false);
|
||||||
private Peer myPeer;
|
private Peer myPeer;
|
||||||
|
@ -66,7 +73,7 @@ public class MessageFacade
|
||||||
{
|
{
|
||||||
/* try
|
/* try
|
||||||
{
|
{
|
||||||
masterPeer = BootstrapMasterPeer.INSTANCE(MASTER_PEER_PORT);
|
masterPeer = BootstrapMasterPeer.GET_INSTANCE(MASTER_PEER_PORT);
|
||||||
} catch (Exception e)
|
} catch (Exception e)
|
||||||
{
|
{
|
||||||
if (masterPeer != null)
|
if (masterPeer != null)
|
||||||
|
@ -97,7 +104,7 @@ public class MessageFacade
|
||||||
} catch (IOException e)
|
} catch (IOException e)
|
||||||
{
|
{
|
||||||
shutDown();
|
shutDown();
|
||||||
log.error("Error at setup myPeerInstance" + e.getMessage());
|
log.error("Error at init myPeerInstance" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +330,7 @@ public class MessageFacade
|
||||||
|
|
||||||
private void onGetDirtyFlag(long timeStamp)
|
private void onGetDirtyFlag(long timeStamp)
|
||||||
{
|
{
|
||||||
// TODO don't get updates at first run....
|
// TODO don't get updates at first execute....
|
||||||
if (lastTimeStamp != timeStamp)
|
if (lastTimeStamp != timeStamp)
|
||||||
{
|
{
|
||||||
isDirty.setValue(!isDirty.get());
|
isDirty.setValue(!isDirty.get());
|
||||||
|
@ -423,7 +430,8 @@ public class MessageFacade
|
||||||
// Find peer address
|
// Find peer address
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void getPeerAddress(final String pubKeyAsHex, AddressLookupListener listener)
|
|
||||||
|
public void getPeerAddress(String pubKeyAsHex, GetPeerAddressListener listener)
|
||||||
{
|
{
|
||||||
final Number160 location = Number160.createHash(pubKeyAsHex);
|
final Number160 location = Number160.createHash(pubKeyAsHex);
|
||||||
final FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
final FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
||||||
|
@ -435,32 +443,44 @@ public class MessageFacade
|
||||||
if (baseFuture.isSuccess() && getPeerAddressFuture.getData() != null)
|
if (baseFuture.isSuccess() && getPeerAddressFuture.getData() != null)
|
||||||
{
|
{
|
||||||
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
||||||
Platform.runLater(() -> onAddressFound(peerAddress, listener));
|
Platform.runLater(() -> listener.onResult(peerAddress));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Platform.runLater(() -> onGetPeerAddressFailed(listener));
|
Platform.runLater(() -> listener.onFailed());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAddressFound(final PeerAddress peerAddress, AddressLookupListener listener)
|
|
||||||
{
|
|
||||||
listener.onResult(peerAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onGetPeerAddressFailed(AddressLookupListener listener)
|
|
||||||
{
|
|
||||||
listener.onFailed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Trade process
|
// Trade process
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void sendTradeMessage(final PeerAddress peerAddress, final TradeMessage tradeMessage, TradeMessageListener listener)
|
public void sendTradingMessage(final PeerAddress peerAddress, TradeMessage tradeMessage, TradeMessageListener listener)
|
||||||
|
{
|
||||||
|
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
||||||
|
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||||
|
sendFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||||
|
{
|
||||||
|
if (sendFuture.isSuccess())
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> listener.onResult());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Platform.runLater(() -> listener.onFailed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendTradeMessage(PeerAddress peerAddress, TradeMessage tradeMessage, TradeMessageListener listener)
|
||||||
{
|
{
|
||||||
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
||||||
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||||
|
@ -499,51 +519,47 @@ public class MessageFacade
|
||||||
|
|
||||||
private void processTradingMessage(TradeMessage tradeMessage, PeerAddress sender)
|
private void processTradingMessage(TradeMessage tradeMessage, PeerAddress sender)
|
||||||
{
|
{
|
||||||
//TODO change to map (key: offerID) instead of list (offererPaymentProtocols, takerPaymentProtocols)
|
// log.trace("processTradingMessage TradeId " + tradeMessage.getTradeId());
|
||||||
log.info("processTradingMessage " + tradeMessage.getType());
|
log.trace("processTradingMessage instance " + tradeMessage.getClass().getSimpleName());
|
||||||
switch (tradeMessage.getType())
|
log.trace("processTradingMessage instance " + tradeMessage.getClass().getName());
|
||||||
{
|
log.trace("processTradingMessage instance " + tradeMessage.getClass().getCanonicalName());
|
||||||
case REQUEST_TAKE_OFFER:
|
log.trace("processTradingMessage instance " + tradeMessage.getClass().getTypeName());
|
||||||
// That is used to initiate the OffererPaymentProtocol and to show incoming requests in the view
|
|
||||||
for (TakeOfferRequestListener takeOfferRequestListener : takeOfferRequestListeners)
|
|
||||||
takeOfferRequestListener.onTakeOfferRequested(tradeMessage, sender);
|
|
||||||
break;
|
|
||||||
case ACCEPT_TAKE_OFFER_REQUEST:
|
|
||||||
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
|
|
||||||
takeOfferTradeListener.onTakeOfferRequestAccepted();
|
|
||||||
break;
|
|
||||||
case REJECT_TAKE_OFFER_REQUEST:
|
|
||||||
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
|
|
||||||
takeOfferTradeListener.onTakeOfferRequestRejected();
|
|
||||||
break;
|
|
||||||
case TAKE_OFFER_FEE_PAYED:
|
|
||||||
for (OffererPaymentProtocol offererPaymentProtocol : offererPaymentProtocols)
|
|
||||||
offererPaymentProtocol.onTakeOfferFeePayed(tradeMessage);
|
|
||||||
break;
|
|
||||||
case REQUEST_TAKER_DEPOSIT_PAYMENT:
|
|
||||||
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
|
|
||||||
takeOfferTradeListener.onTakerDepositPaymentRequested(tradeMessage);
|
|
||||||
break;
|
|
||||||
case REQUEST_OFFERER_DEPOSIT_PUBLICATION:
|
|
||||||
for (OffererPaymentProtocol offererPaymentProtocol : offererPaymentProtocols)
|
|
||||||
offererPaymentProtocol.onDepositTxReadyForPublication(tradeMessage);
|
|
||||||
break;
|
|
||||||
case DEPOSIT_TX_PUBLISHED:
|
|
||||||
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
|
|
||||||
takeOfferTradeListener.onDepositTxPublished(tradeMessage);
|
|
||||||
break;
|
|
||||||
case BANK_TX_INITED:
|
|
||||||
for (TakerPaymentProtocol takeOfferTradeListener : takerPaymentProtocols)
|
|
||||||
takeOfferTradeListener.onBankTransferInited(tradeMessage);
|
|
||||||
break;
|
|
||||||
case PAYOUT_TX_PUBLISHED:
|
|
||||||
for (OffererPaymentProtocol offererPaymentProtocol : offererPaymentProtocols)
|
|
||||||
offererPaymentProtocol.onPayoutTxPublished(tradeMessage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if (tradeMessage instanceof RequestTakeOfferMessage)
|
||||||
log.info("default");
|
{
|
||||||
break;
|
takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeMessage.getTradeId(), sender));
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof AcceptTakeOfferRequestMessage)
|
||||||
|
{
|
||||||
|
takerPaymentProtocols.get(tradeMessage.getTradeId()).onAcceptTakeOfferRequestMessage();
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof RejectTakeOfferRequestMessage)
|
||||||
|
{
|
||||||
|
takerPaymentProtocols.get(tradeMessage.getTradeId()).onRejectTakeOfferRequestMessage();
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof TakeOfferFeePayedMessage)
|
||||||
|
{
|
||||||
|
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof RequestTakerDepositPaymentMessage)
|
||||||
|
{
|
||||||
|
takerPaymentProtocols.get(tradeMessage.getTradeId()).onRequestTakerDepositPaymentMessage((RequestTakerDepositPaymentMessage) tradeMessage);
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage)
|
||||||
|
{
|
||||||
|
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof DepositTxPublishedMessage)
|
||||||
|
{
|
||||||
|
takerPaymentProtocols.get(tradeMessage.getTradeId()).onDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof BankTransferInitedMessage)
|
||||||
|
{
|
||||||
|
takerPaymentProtocols.get(tradeMessage.getTradeId()).onBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
|
||||||
|
}
|
||||||
|
else if (tradeMessage instanceof PayoutTxPublishedMessage)
|
||||||
|
{
|
||||||
|
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onPayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,12 +632,12 @@ public class MessageFacade
|
||||||
// Misc
|
// Misc
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
public PublicKey getPubKey()
|
public PublicKey getPubKey()
|
||||||
{
|
{
|
||||||
return keyPair.getPublic();
|
return keyPair.getPublic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Event Listeners
|
// Event Listeners
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -646,24 +662,24 @@ public class MessageFacade
|
||||||
takeOfferRequestListeners.remove(listener);
|
takeOfferRequestListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTakerPaymentProtocol(TakerPaymentProtocol listener)
|
public void addTakerPaymentProtocol(TakerAsSellerProtocol protocol)
|
||||||
{
|
{
|
||||||
takerPaymentProtocols.add(listener);
|
takerPaymentProtocols.put(protocol.getId(), protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeTakerPaymentProtocol(TakerPaymentProtocol listener)
|
public void removeTakerPaymentProtocol(TakerAsSellerProtocol protocol)
|
||||||
{
|
{
|
||||||
takerPaymentProtocols.remove(listener);
|
takerPaymentProtocols.remove(protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOffererPaymentProtocol(OffererPaymentProtocol listener)
|
public void addOffererPaymentProtocol(OffererAsBuyerProtocol protocol)
|
||||||
{
|
{
|
||||||
offererPaymentProtocols.add(listener);
|
offererAsBuyerProtocols.put(protocol.getId(), protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeOffererPaymentProtocol(OffererPaymentProtocol listener)
|
public void removeOffererPaymentProtocol(OffererAsBuyerProtocol protocol)
|
||||||
{
|
{
|
||||||
offererPaymentProtocols.remove(listener);
|
offererAsBuyerProtocols.remove(protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPingPeerListener(PingPeerListener listener)
|
public void addPingPeerListener(PingPeerListener listener)
|
||||||
|
@ -781,5 +797,4 @@ public class MessageFacade
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,277 +1,6 @@
|
||||||
package io.bitsquare.msg;
|
package io.bitsquare.msg;
|
||||||
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
public interface TradeMessage
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
//TODO refactor
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
|
||||||
public class TradeMessage implements Serializable
|
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 7916445031849763995L;
|
public String getTradeId();
|
||||||
|
|
||||||
|
|
||||||
private final String uid;
|
|
||||||
private final TradeMessageType type;
|
|
||||||
private final String offerUID;
|
|
||||||
private String takerMessagePubKey;
|
|
||||||
private String signedTakerDepositTxAsHex;
|
|
||||||
private String txScriptSigAsHex;
|
|
||||||
private String txConnOutAsHex;
|
|
||||||
private String contractAsJson;
|
|
||||||
private String takerContractSignature;
|
|
||||||
private String takerPayoutAddress;
|
|
||||||
private String depositTxID;
|
|
||||||
private String depositTxAsHex;
|
|
||||||
private String offererSignatureR;
|
|
||||||
private String offererSignatureS;
|
|
||||||
private BigInteger offererPaybackAmount;
|
|
||||||
private BigInteger takerPaybackAmount;
|
|
||||||
private String offererPayoutAddress;
|
|
||||||
private BigInteger tradeAmount;
|
|
||||||
private String takeOfferFeeTxID;
|
|
||||||
private String takerMultiSigPubKey;
|
|
||||||
private BankAccount bankAccount;
|
|
||||||
private String accountID;
|
|
||||||
private String offererPubKey;
|
|
||||||
private String preparedOffererDepositTxAsHex;
|
|
||||||
private long offererTxOutIndex;
|
|
||||||
private long takerTxOutIndex;
|
|
||||||
private String payoutTxAsHex;
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID, BigInteger tradeAmount, String takeOfferFeeTxID, String takerMultiSigPubKey)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
this.tradeAmount = tradeAmount;
|
|
||||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
|
||||||
this.takerMultiSigPubKey = takerMultiSigPubKey;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID, BankAccount bankAccount, String accountID, String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
this.bankAccount = bankAccount;
|
|
||||||
this.accountID = accountID;
|
|
||||||
this.offererPubKey = offererPubKey;
|
|
||||||
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
|
||||||
this.offererTxOutIndex = offererTxOutIndex;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID,
|
|
||||||
BankAccount bankAccount,
|
|
||||||
String accountID,
|
|
||||||
String takerMessagePubKey,
|
|
||||||
String signedTakerDepositTxAsHex,
|
|
||||||
String txScriptSigAsHex,
|
|
||||||
String txConnOutAsHex,
|
|
||||||
String contractAsJson,
|
|
||||||
String takerContractSignature,
|
|
||||||
String takerPayoutAddress,
|
|
||||||
long takerTxOutIndex,
|
|
||||||
long offererTxOutIndex)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
this.bankAccount = bankAccount;
|
|
||||||
this.accountID = accountID;
|
|
||||||
this.takerMessagePubKey = takerMessagePubKey;
|
|
||||||
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
|
|
||||||
this.txScriptSigAsHex = txScriptSigAsHex;
|
|
||||||
this.txConnOutAsHex = txConnOutAsHex;
|
|
||||||
this.contractAsJson = contractAsJson;
|
|
||||||
this.takerContractSignature = takerContractSignature;
|
|
||||||
this.takerPayoutAddress = takerPayoutAddress;
|
|
||||||
this.takerTxOutIndex = takerTxOutIndex;
|
|
||||||
this.offererTxOutIndex = offererTxOutIndex;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID, String depositTxAsHex)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
this.depositTxAsHex = depositTxAsHex;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.10
|
|
||||||
|
|
||||||
public TradeMessage(TradeMessageType type, String offerUID,
|
|
||||||
String depositTxAsHex,
|
|
||||||
String offererSignatureR,
|
|
||||||
String offererSignatureS,
|
|
||||||
BigInteger offererPaybackAmount,
|
|
||||||
BigInteger takerPaybackAmount,
|
|
||||||
String offererPayoutAddress)
|
|
||||||
{
|
|
||||||
this.offerUID = offerUID;
|
|
||||||
this.type = type;
|
|
||||||
this.depositTxAsHex = depositTxAsHex;
|
|
||||||
this.offererSignatureR = offererSignatureR;
|
|
||||||
this.offererSignatureS = offererSignatureS;
|
|
||||||
this.offererPaybackAmount = offererPaybackAmount;
|
|
||||||
this.takerPaybackAmount = takerPaybackAmount;
|
|
||||||
this.offererPayoutAddress = offererPayoutAddress;
|
|
||||||
|
|
||||||
uid = UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getUid()
|
|
||||||
{
|
|
||||||
return uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TradeMessageType getType()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakeOfferFeeTxID()
|
|
||||||
{
|
|
||||||
return takeOfferFeeTxID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOfferUID()
|
|
||||||
{
|
|
||||||
return offerUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BankAccount getBankAccount()
|
|
||||||
{
|
|
||||||
return bankAccount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccountID()
|
|
||||||
{
|
|
||||||
return accountID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakerMultiSigPubKey()
|
|
||||||
{
|
|
||||||
return takerMultiSigPubKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPreparedOffererDepositTxAsHex()
|
|
||||||
{
|
|
||||||
return preparedOffererDepositTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigInteger getTradeAmount()
|
|
||||||
{
|
|
||||||
return tradeAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakerMessagePubKey()
|
|
||||||
{
|
|
||||||
return takerMessagePubKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignedTakerDepositTxAsHex()
|
|
||||||
{
|
|
||||||
return signedTakerDepositTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getContractAsJson()
|
|
||||||
{
|
|
||||||
return contractAsJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakerContractSignature()
|
|
||||||
{
|
|
||||||
return takerContractSignature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTxScriptSigAsHex()
|
|
||||||
{
|
|
||||||
return txScriptSigAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTxConnOutAsHex()
|
|
||||||
{
|
|
||||||
return txConnOutAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDepositTxID()
|
|
||||||
{
|
|
||||||
return depositTxID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOffererPubKey()
|
|
||||||
{
|
|
||||||
return offererPubKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakerPayoutAddress()
|
|
||||||
{
|
|
||||||
return takerPayoutAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOffererPayoutAddress()
|
|
||||||
{
|
|
||||||
return offererPayoutAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOffererSignatureR()
|
|
||||||
{
|
|
||||||
return offererSignatureR;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOffererSignatureS()
|
|
||||||
{
|
|
||||||
return offererSignatureS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigInteger getOffererPaybackAmount()
|
|
||||||
{
|
|
||||||
return offererPaybackAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigInteger getTakerPaybackAmount()
|
|
||||||
{
|
|
||||||
return takerPaybackAmount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDepositTxAsHex()
|
|
||||||
{
|
|
||||||
return depositTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPayoutTxAsHex()
|
|
||||||
{
|
|
||||||
return payoutTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayoutTxAsHex(String payoutTxAsHex)
|
|
||||||
{
|
|
||||||
this.payoutTxAsHex = payoutTxAsHex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getOffererTxOutIndex()
|
|
||||||
{
|
|
||||||
return offererTxOutIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTakerTxOutIndex()
|
|
||||||
{
|
|
||||||
return takerTxOutIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package io.bitsquare.msg;
|
|
||||||
|
|
||||||
public enum TradeMessageType
|
|
||||||
{
|
|
||||||
REQUEST_TAKE_OFFER,
|
|
||||||
ACCEPT_TAKE_OFFER_REQUEST,
|
|
||||||
REJECT_TAKE_OFFER_REQUEST,
|
|
||||||
TAKE_OFFER_FEE_PAYED,
|
|
||||||
REQUEST_TAKER_DEPOSIT_PAYMENT,
|
|
||||||
REQUEST_OFFERER_DEPOSIT_PUBLICATION,
|
|
||||||
DEPOSIT_TX_PUBLISHED,
|
|
||||||
BANK_TX_INITED,
|
|
||||||
PAYOUT_TX_PUBLISHED
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +1,8 @@
|
||||||
package io.bitsquare.msg.listeners;
|
package io.bitsquare.msg.listeners;
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
|
||||||
public interface TakeOfferRequestListener
|
public interface TakeOfferRequestListener
|
||||||
{
|
{
|
||||||
void onTakeOfferRequested(TradeMessage tradeMessage, PeerAddress sender);
|
void onTakeOfferRequested(String offerId, PeerAddress sender);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ public class Storage
|
||||||
|
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private Map<String, Serializable> rootMap = new HashMap<>();
|
private Map<String, Serializable> rootMap = new HashMap<>();
|
||||||
private boolean dirty;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -120,7 +119,6 @@ public class Storage
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock.lock();
|
lock.lock();
|
||||||
dirty = true;
|
|
||||||
rootMap.put(key, value);
|
rootMap.put(key, value);
|
||||||
saveObjectToFile((Serializable) rootMap);
|
saveObjectToFile((Serializable) rootMap);
|
||||||
} finally
|
} finally
|
||||||
|
@ -141,20 +139,23 @@ public class Storage
|
||||||
return read(classInstance.getClass().getName() + "." + propertyKey);
|
return read(classInstance.getClass().getName() + "." + propertyKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read from local rootMap, just if not found read from disc
|
||||||
public Serializable read(String key)
|
public Serializable read(String key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock.lock();
|
lock.lock();
|
||||||
if (dirty)
|
if (rootMap.containsKey(key))
|
||||||
|
{
|
||||||
|
// log.trace("Read object with key = " + key + " / value = " + rootMap.get(key));
|
||||||
|
return rootMap.get(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
final Map<String, Serializable> map = readRootMap();
|
final Map<String, Serializable> map = readRootMap();
|
||||||
if (map != null)
|
if (map != null)
|
||||||
{
|
{
|
||||||
rootMap = map;
|
rootMap = map;
|
||||||
dirty = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (rootMap.containsKey(key))
|
if (rootMap.containsKey(key))
|
||||||
{
|
{
|
||||||
|
@ -163,9 +164,10 @@ public class Storage
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log.warn("Object with key = " + key + " not found.");
|
log.info("Object with key = " + key + " not found.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally
|
} finally
|
||||||
{
|
{
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -205,7 +207,7 @@ public class Storage
|
||||||
} catch (FileNotFoundException e)
|
} catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
|
|
||||||
log.trace("File not found is ok for the first run.");
|
log.trace("File not found is ok for the first execute.");
|
||||||
return null;
|
return null;
|
||||||
} catch (ClassNotFoundException | IOException e2)
|
} catch (ClassNotFoundException | IOException e2)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class Trade implements Serializable
|
||||||
private Transaction depositTransaction;
|
private Transaction depositTransaction;
|
||||||
private Transaction payoutTransaction;
|
private Transaction payoutTransaction;
|
||||||
|
|
||||||
private State state = State.NONE;
|
private State state = State.OPEN;
|
||||||
|
|
||||||
public Trade(Offer offer)
|
public Trade(Offer offer)
|
||||||
{
|
{
|
||||||
|
@ -39,21 +39,6 @@ public class Trade implements Serializable
|
||||||
// Setters
|
// Setters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return offer.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Offer getOffer()
|
|
||||||
{
|
|
||||||
return offer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTakeOfferFeeTxID()
|
|
||||||
{
|
|
||||||
return takeOfferFeeTxID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTakeOfferFeeTxID(String takeOfferFeeTxID)
|
public void setTakeOfferFeeTxID(String takeOfferFeeTxID)
|
||||||
{
|
{
|
||||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||||
|
@ -80,16 +65,31 @@ public class Trade implements Serializable
|
||||||
contractChangedProperty.set(!contractChangedProperty.get());
|
contractChangedProperty.set(!contractChangedProperty.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return offer.getId();
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
public Offer getOffer()
|
||||||
// Getters
|
{
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
return offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakeOfferFeeTxId()
|
||||||
|
{
|
||||||
|
return takeOfferFeeTxID;
|
||||||
|
}
|
||||||
|
|
||||||
public String getContractAsJson()
|
public String getContractAsJson()
|
||||||
{
|
{
|
||||||
return contractAsJson;
|
return contractAsJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void setContractAsJson(String contractAsJson)
|
public void setContractAsJson(String contractAsJson)
|
||||||
{
|
{
|
||||||
this.contractAsJson = contractAsJson;
|
this.contractAsJson = contractAsJson;
|
||||||
|
@ -122,7 +122,6 @@ public class Trade implements Serializable
|
||||||
payoutTxChangedProperty.set(!payoutTxChangedProperty.get());
|
payoutTxChangedProperty.set(!payoutTxChangedProperty.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public State getState()
|
public State getState()
|
||||||
{
|
{
|
||||||
return state;
|
return state;
|
||||||
|
@ -134,7 +133,6 @@ public class Trade implements Serializable
|
||||||
stateChangedProperty.set(state.toString());
|
stateChangedProperty.set(state.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SimpleBooleanProperty getDepositTxChangedProperty()
|
public SimpleBooleanProperty getDepositTxChangedProperty()
|
||||||
{
|
{
|
||||||
return depositTxChangedProperty;
|
return depositTxChangedProperty;
|
||||||
|
@ -186,7 +184,7 @@ public class Trade implements Serializable
|
||||||
|
|
||||||
public static enum State
|
public static enum State
|
||||||
{
|
{
|
||||||
NONE,
|
OPEN,
|
||||||
ACCEPTED,
|
ACCEPTED,
|
||||||
COMPLETED
|
COMPLETED
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,18 @@ import com.google.inject.Inject;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.gui.popups.Popups;
|
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
|
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocolListener;
|
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocolListener;
|
||||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
|
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocolListener;
|
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
@ -32,8 +34,8 @@ import org.slf4j.LoggerFactory;
|
||||||
public class Trading
|
public class Trading
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
||||||
private final Map<String, TakerPaymentProtocol> takerPaymentProtocols = new HashMap<>();
|
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||||
private final Map<String, OffererPaymentProtocol> offererPaymentProtocols = new HashMap<>();
|
private final Map<String, OffererAsBuyerProtocol> offererPaymentProtocols = new HashMap<>();
|
||||||
private final String storageKey;
|
private final String storageKey;
|
||||||
private final User user;
|
private final User user;
|
||||||
|
|
||||||
|
@ -44,9 +46,10 @@ public class Trading
|
||||||
private final CryptoFacade cryptoFacade;
|
private final CryptoFacade cryptoFacade;
|
||||||
private final StringProperty newTradeProperty = new SimpleStringProperty();
|
private final StringProperty newTradeProperty = new SimpleStringProperty();
|
||||||
|
|
||||||
private Map<String, Offer> myOffers = new HashMap<>();
|
private Map<String, Offer> offers = new HashMap<>();
|
||||||
|
|
||||||
private Map<String, Trade> trades = new HashMap<>();
|
private Map<String, Trade> trades = new HashMap<>();
|
||||||
|
private Trade currentPendingTrade;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -73,15 +76,15 @@ public class Trading
|
||||||
|
|
||||||
Object offersObject = storage.read(storageKey + ".offers");
|
Object offersObject = storage.read(storageKey + ".offers");
|
||||||
if (offersObject instanceof HashMap)
|
if (offersObject instanceof HashMap)
|
||||||
myOffers = (Map<String, Offer>) offersObject;
|
offers = (Map<String, Offer>) offersObject;
|
||||||
|
|
||||||
Object tradesObject = storage.read(storageKey + ".trades");
|
Object tradesObject = storage.read(storageKey + ".trades");
|
||||||
if (tradesObject instanceof HashMap)
|
if (tradesObject instanceof HashMap)
|
||||||
trades = (Map<String, Trade>) tradesObject;
|
trades = (Map<String, Trade>) tradesObject;
|
||||||
|
|
||||||
|
messageFacade.addTakeOfferRequestListener((offerId, sender) -> createOffererAsBuyerProtocol(offerId, sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Public Methods
|
// Public Methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -92,15 +95,15 @@ public class Trading
|
||||||
|
|
||||||
private void saveOffers()
|
private void saveOffers()
|
||||||
{
|
{
|
||||||
storage.write(storageKey + ".offers", myOffers);
|
storage.write(storageKey + ".offers", offers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOffer(Offer offer) throws IOException
|
public void addOffer(Offer offer) throws IOException
|
||||||
{
|
{
|
||||||
if (myOffers.containsKey(offer.getId()))
|
if (offers.containsKey(offer.getId()))
|
||||||
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getId());
|
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getId());
|
||||||
|
|
||||||
myOffers.put(offer.getId(), offer);
|
offers.put(offer.getId(), offer);
|
||||||
saveOffers();
|
saveOffers();
|
||||||
|
|
||||||
messageFacade.addOffer(offer);
|
messageFacade.addOffer(offer);
|
||||||
|
@ -108,17 +111,12 @@ public class Trading
|
||||||
|
|
||||||
public void removeOffer(Offer offer) throws IOException
|
public void removeOffer(Offer offer) throws IOException
|
||||||
{
|
{
|
||||||
myOffers.remove(offer.getId());
|
offers.remove(offer.getId());
|
||||||
saveOffers();
|
saveOffers();
|
||||||
|
|
||||||
messageFacade.removeOffer(offer);
|
messageFacade.removeOffer(offer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOfferTradable(Offer offer)
|
|
||||||
{
|
|
||||||
return !trades.containsKey(offer.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Trade createTrade(Offer offer)
|
public Trade createTrade(Offer offer)
|
||||||
{
|
{
|
||||||
|
@ -144,85 +142,88 @@ public class Trading
|
||||||
return this.newTradeProperty;
|
return this.newTradeProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener, WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
public TakerPaymentProtocol addTakerPaymentProtocol(Trade trade, TakerPaymentProtocolListener listener)
|
|
||||||
{
|
|
||||||
TakerPaymentProtocol takerPaymentProtocol = new TakerPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
|
||||||
takerPaymentProtocols.put(trade.getId(), takerPaymentProtocol);
|
|
||||||
return takerPaymentProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
OffererPaymentProtocol addOffererPaymentProtocol(Trade trade, OffererPaymentProtocolListener listener)
|
|
||||||
{
|
|
||||||
OffererPaymentProtocol offererPaymentProtocol = new OffererPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
|
||||||
offererPaymentProtocols.put(trade.getId(), offererPaymentProtocol);
|
|
||||||
return offererPaymentProtocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createOffererPaymentProtocol(TradeMessage tradeMessage, PeerAddress sender)
|
|
||||||
{
|
|
||||||
Offer offer = myOffers.get(tradeMessage.getOfferUID());
|
|
||||||
if (isOfferTradable(offer))
|
|
||||||
{
|
{
|
||||||
Trade trade = createTrade(offer);
|
Trade trade = createTrade(offer);
|
||||||
OffererPaymentProtocol offererPaymentProtocol = addOffererPaymentProtocol(trade, new OffererPaymentProtocolListener()
|
trade.setTradeAmount(amount);
|
||||||
{
|
|
||||||
@Override
|
TakerAsSellerProtocol takerPaymentProtocol = new TakerAsSellerProtocol(trade, listener, resultHandler, faultHandler, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||||
public void onProgress(double progress)
|
takerPaymentProtocols.put(trade.getId(), takerPaymentProtocol);
|
||||||
{
|
|
||||||
//log.debug("onProgress " + progress);
|
return trade;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(String failureMessage)
|
|
||||||
{
|
|
||||||
log.warn(failureMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public void createOffererAsBuyerProtocol(String offerId, PeerAddress sender)
|
||||||
|
{
|
||||||
|
log.trace("createOffererAsBuyerProtocol offerId = " + offerId);
|
||||||
|
Offer offer = offers.get(offerId);
|
||||||
|
if (offer != null && offers.containsKey(offer.getId()))
|
||||||
|
{
|
||||||
|
offers.remove(offer);
|
||||||
|
|
||||||
|
currentPendingTrade = createTrade(offer);
|
||||||
|
OffererAsBuyerProtocolListener listener = new OffererAsBuyerProtocolListener()
|
||||||
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onDepositTxPublished(String depositTxID)
|
public void onDepositTxPublished(String depositTxID)
|
||||||
{
|
{
|
||||||
log.debug("trading onDepositTxPublished " + depositTxID);
|
log.trace("trading onDepositTxPublishedMessage " + depositTxID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDepositTxConfirmedUpdate(TransactionConfidence confidence)
|
public void onDepositTxConfirmedUpdate(TransactionConfidence confidence)
|
||||||
{
|
{
|
||||||
log.debug("trading onDepositTxConfirmedUpdate");
|
log.trace("trading onDepositTxConfirmedUpdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPayoutTxPublished(String payoutTxAsHex)
|
public void onPayoutTxPublished(String payoutTxAsHex)
|
||||||
{
|
{
|
||||||
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
|
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
|
||||||
trade.setPayoutTransaction(payoutTx);
|
currentPendingTrade.setPayoutTransaction(payoutTx);
|
||||||
trade.setState(Trade.State.COMPLETED);
|
currentPendingTrade.setState(Trade.State.COMPLETED);
|
||||||
log.debug("trading onPayoutTxPublished");
|
log.debug("trading onPayoutTxPublishedMessage");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDepositTxConfirmedInBlockchain()
|
public void onDepositTxConfirmedInBlockchain()
|
||||||
{
|
{
|
||||||
log.debug("trading onDepositTxConfirmedInBlockchain");
|
log.trace("trading onDepositTxConfirmedInBlockchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
};
|
||||||
|
|
||||||
// the handler was not called there because the object was not created when the event occurred (and therefor no listener)
|
WorkerResultHandler resultHandler = new WorkerResultHandler()
|
||||||
// will probably created earlier, so let it for the moment like that....
|
{
|
||||||
offererPaymentProtocol.onTakeOfferRequested(sender);
|
@Override
|
||||||
|
public void onResult(Worker worker)
|
||||||
|
{
|
||||||
|
//log.trace("onResult " + worker.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WorkerFaultHandler faultHandler = new WorkerFaultHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onFault(Throwable throwable)
|
||||||
|
{
|
||||||
|
log.error("onFault " + throwable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OffererAsBuyerProtocol offererAsBuyerProtocol = new OffererAsBuyerProtocol(currentPendingTrade, sender, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user, resultHandler, faultHandler, listener);
|
||||||
|
offererPaymentProtocols.put(currentPendingTrade.getId(), offererAsBuyerProtocol);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Popups.openWarningPopup("Offer already taken", "You have that offer already taken. Find that trade under Orders/Open or Pending.");
|
log.warn("Incoming offer take request does not match with any saved offer. We ignore that request.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void onBankTransferInited(String tradeUID)
|
public void onUIEventBankTransferInited(String tradeUID)
|
||||||
{
|
{
|
||||||
offererPaymentProtocols.get(tradeUID).bankTransferInited();
|
offererPaymentProtocols.get(tradeUID).onUIEventBankTransferInited();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -232,9 +233,9 @@ public class Trading
|
||||||
|
|
||||||
|
|
||||||
// 6
|
// 6
|
||||||
public void releaseBTC(String tradeUID, TradeMessage tradeMessage)
|
public void releaseBTC(String tradeUID)
|
||||||
{
|
{
|
||||||
takerPaymentProtocols.get(tradeUID).releaseBTC(tradeMessage);
|
takerPaymentProtocols.get(tradeUID).onUIEventFiatReceived();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -250,11 +251,22 @@ public class Trading
|
||||||
|
|
||||||
public Map<String, Offer> getOffers()
|
public Map<String, Offer> getOffers()
|
||||||
{
|
{
|
||||||
return myOffers;
|
return offers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Offer getOffer(String offerId)
|
public Offer getOffer(String offerId)
|
||||||
{
|
{
|
||||||
return myOffers.get(offerId);
|
return offers.get(offerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isOfferAlreadyInTrades(Offer offer)
|
||||||
|
{
|
||||||
|
return trades.containsKey(offer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trade getCurrentPendingTrade()
|
||||||
|
{
|
||||||
|
return currentPendingTrade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/main/java/io/bitsquare/trade/payment/PaymentModel.java
Normal file
26
src/main/java/io/bitsquare/trade/payment/PaymentModel.java
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package io.bitsquare.trade.payment;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.MessageFacade;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
|
||||||
|
public class PaymentModel extends PropertyProviderModel
|
||||||
|
{
|
||||||
|
public final MessageFacade messageFacade;
|
||||||
|
public final Offer offer;
|
||||||
|
public PeerAddress peerAddress;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public PaymentModel(MessageFacade messageFacade, Trade trade)
|
||||||
|
{
|
||||||
|
this.messageFacade = messageFacade;
|
||||||
|
this.offer = trade.getOffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,88 +1,320 @@
|
||||||
package io.bitsquare.trade.payment.offerer;
|
package io.bitsquare.trade.payment.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.*;
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import io.bitsquare.msg.TradeMessageType;
|
|
||||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
|
||||||
import io.bitsquare.trade.Contract;
|
|
||||||
import io.bitsquare.trade.Offer;
|
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.payment.offerer.tasks.*;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import io.bitsquare.util.Utilities;
|
import io.nucleo.scheduler.SequenceScheduler;
|
||||||
import java.math.BigInteger;
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
import javafx.util.Pair;
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
//TODO refactor to process based pattern
|
//TODO refactor to process based pattern
|
||||||
public class OffererPaymentProtocol
|
public class OffererAsBuyerProtocol
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(OffererPaymentProtocol.class);
|
private static final Logger log = LoggerFactory.getLogger(OffererAsBuyerProtocol.class);
|
||||||
|
public final PeerAddress peerAddress;
|
||||||
|
// provided data
|
||||||
|
private final String id;
|
||||||
private final Trade trade;
|
private final Trade trade;
|
||||||
private final Offer offer;
|
private final OffererAsBuyerProtocolListener listener;
|
||||||
private final OffererPaymentProtocolListener offererPaymentProtocolListener;
|
private final WorkerResultHandler resultHandler;
|
||||||
|
private final WorkerFaultHandler faultHandler;
|
||||||
private final MessageFacade messageFacade;
|
private final MessageFacade messageFacade;
|
||||||
|
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
|
|
||||||
private final BlockChainFacade blockChainFacade;
|
private final BlockChainFacade blockChainFacade;
|
||||||
|
|
||||||
private final CryptoFacade cryptoFacade;
|
private final CryptoFacade cryptoFacade;
|
||||||
|
|
||||||
private final User user;
|
private final User user;
|
||||||
private PeerAddress peerAddress;
|
// private
|
||||||
private boolean isTakeOfferRequested;
|
private final SequenceScheduler scheduler_1;
|
||||||
private int currentStep = 0;
|
// data written/read by tasks
|
||||||
private String preparedOffererDepositTxAsHex;
|
private String preparedOffererDepositTxAsHex;
|
||||||
private Transaction depositTransaction;
|
private long offererTxOutIndex;
|
||||||
|
private String offererPubKey;
|
||||||
|
// data written by messages, read by tasks
|
||||||
|
private String takeOfferFeeTxId;
|
||||||
|
private String takerMultiSigPubKey;
|
||||||
private String takerPayoutAddress;
|
private String takerPayoutAddress;
|
||||||
|
private String peersAccountId;
|
||||||
|
private BankAccount peersBankAccount;
|
||||||
|
private String takerMessagePubKey;
|
||||||
|
private String peersContractAsJson;
|
||||||
|
private String signedTakerDepositTxAsHex;
|
||||||
|
private String txConnOutAsHex;
|
||||||
|
private String txScriptSigAsHex;
|
||||||
|
private long takerTxOutIndex;
|
||||||
|
private SequenceScheduler scheduler_2;
|
||||||
|
private SequenceScheduler scheduler_3;
|
||||||
|
private SequenceScheduler scheduler_4;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public OffererPaymentProtocol(Trade trade,
|
public OffererAsBuyerProtocol(Trade trade,
|
||||||
OffererPaymentProtocolListener offererPaymentProtocolListener,
|
PeerAddress peerAddress,
|
||||||
MessageFacade messageFacade,
|
MessageFacade messageFacade,
|
||||||
WalletFacade walletFacade,
|
WalletFacade walletFacade,
|
||||||
BlockChainFacade blockChainFacade,
|
BlockChainFacade blockChainFacade,
|
||||||
CryptoFacade cryptoFacade,
|
CryptoFacade cryptoFacade,
|
||||||
User user)
|
User user,
|
||||||
|
WorkerResultHandler resultHandler,
|
||||||
|
WorkerFaultHandler faultHandler,
|
||||||
|
OffererAsBuyerProtocolListener listener)
|
||||||
{
|
{
|
||||||
checkNotNull(trade);
|
|
||||||
checkNotNull(messageFacade);
|
|
||||||
checkNotNull(walletFacade);
|
|
||||||
checkNotNull(blockChainFacade);
|
|
||||||
checkNotNull(cryptoFacade);
|
|
||||||
checkNotNull(user);
|
|
||||||
|
|
||||||
this.trade = trade;
|
this.trade = trade;
|
||||||
this.offererPaymentProtocolListener = offererPaymentProtocolListener;
|
this.peerAddress = peerAddress;
|
||||||
|
this.listener = listener;
|
||||||
|
this.resultHandler = resultHandler;
|
||||||
|
this.faultHandler = faultHandler;
|
||||||
this.messageFacade = messageFacade;
|
this.messageFacade = messageFacade;
|
||||||
this.walletFacade = walletFacade;
|
this.walletFacade = walletFacade;
|
||||||
this.blockChainFacade = blockChainFacade;
|
this.blockChainFacade = blockChainFacade;
|
||||||
this.cryptoFacade = cryptoFacade;
|
this.cryptoFacade = cryptoFacade;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
||||||
offer = trade.getOffer();
|
id = trade.getId();
|
||||||
|
|
||||||
messageFacade.addOffererPaymentProtocol(this);
|
messageFacade.addOffererPaymentProtocol(this);
|
||||||
|
|
||||||
log.debug("0 Constr");
|
log.debug("OffererAsBuyerProtocol created");
|
||||||
|
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new HandleTakeOfferRequest(resultHandler, faultHandler));
|
||||||
|
scheduler_1 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_1.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onTakeOfferFeePayedMessage(TakeOfferFeePayedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onTakeOfferFeePayedMessage");
|
||||||
|
getTrade().setTakeOfferFeeTxID(message.getTakeOfferFeeTxID());
|
||||||
|
getTrade().setTradeAmount(message.getTradeAmount());
|
||||||
|
|
||||||
|
takeOfferFeeTxId = message.getTakeOfferFeeTxID();
|
||||||
|
takerMultiSigPubKey = message.getTakerMultiSigPubKey();
|
||||||
|
|
||||||
|
if (scheduler_1.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new VerifyTakeOfferFeePayment(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new CreateDepositTx(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new RequestTakerDepositPayment(getResultHandler(), getFaultHandler()));
|
||||||
|
scheduler_2 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_2.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_1 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onRequestOffererPublishDepositTxMessage");
|
||||||
|
takerPayoutAddress = message.getTakerPayoutAddress();
|
||||||
|
peersAccountId = message.getAccountId();
|
||||||
|
peersBankAccount = message.getBankAccount();
|
||||||
|
takerMessagePubKey = message.getTakerMessagePubKey();
|
||||||
|
peersContractAsJson = message.getContractAsJson();
|
||||||
|
signedTakerDepositTxAsHex = message.getSignedTakerDepositTxAsHex();
|
||||||
|
txConnOutAsHex = message.getTxConnOutAsHex();
|
||||||
|
txScriptSigAsHex = message.getTxScriptSigAsHex();
|
||||||
|
takerTxOutIndex = message.getTakerTxOutIndex();
|
||||||
|
|
||||||
|
if (scheduler_2.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new VerifyTakerAccount(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new VerifyAndSignContract(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new SignAndPublishDepositTx(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new SendDepositTxIdToTaker(getResultHandler(), getFaultHandler()));
|
||||||
|
tasks.add(new SetupListenerForBlockChainConfirmation(getResultHandler(), getFaultHandler()));
|
||||||
|
scheduler_3 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_3.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_2 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triggered from UI event: Button click "Bank transfer inited"
|
||||||
|
public void onUIEventBankTransferInited()
|
||||||
|
{
|
||||||
|
log.debug("onUIEventBankTransferInited");
|
||||||
|
|
||||||
|
if (scheduler_3.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new SendSignedPayoutTx(getResultHandler(), getFaultHandler()));
|
||||||
|
scheduler_4 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_4.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_3 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage)
|
||||||
|
{
|
||||||
|
log.debug("onPayoutTxPublishedMessage");
|
||||||
|
listener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters, Setters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakeOfferFeeTxId()
|
||||||
|
{
|
||||||
|
return takeOfferFeeTxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerMultiSigPubKey()
|
||||||
|
{
|
||||||
|
return takerMultiSigPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerPayoutAddress()
|
||||||
|
{
|
||||||
|
return takerPayoutAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPeersAccountId()
|
||||||
|
{
|
||||||
|
return peersAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BankAccount getPeersBankAccount()
|
||||||
|
{
|
||||||
|
return peersBankAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerMessagePubKey()
|
||||||
|
{
|
||||||
|
return takerMessagePubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPeersContractAsJson()
|
||||||
|
{
|
||||||
|
return peersContractAsJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignedTakerDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return signedTakerDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTxConnOutAsHex()
|
||||||
|
{
|
||||||
|
return txConnOutAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTxScriptSigAsHex()
|
||||||
|
{
|
||||||
|
return txScriptSigAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTakerTxOutIndex()
|
||||||
|
{
|
||||||
|
return takerTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPreparedOffererDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return preparedOffererDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreparedOffererDepositTxAsHex(String preparedOffererDepositTxAsHex)
|
||||||
|
{
|
||||||
|
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOffererTxOutIndex()
|
||||||
|
{
|
||||||
|
return offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffererTxOutIndex(long offererTxOutIndex)
|
||||||
|
{
|
||||||
|
this.offererTxOutIndex = offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererPubKey()
|
||||||
|
{
|
||||||
|
return offererPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffererPubKey(String offererPubKey)
|
||||||
|
{
|
||||||
|
this.offererPubKey = offererPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trade getTrade()
|
||||||
|
{
|
||||||
|
return trade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffererAsBuyerProtocolListener getListener()
|
||||||
|
{
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkerResultHandler getResultHandler()
|
||||||
|
{
|
||||||
|
return resultHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkerFaultHandler getFaultHandler()
|
||||||
|
{
|
||||||
|
return faultHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFacade getMessageFacade()
|
||||||
|
{
|
||||||
|
return messageFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletFacade getWalletFacade()
|
||||||
|
{
|
||||||
|
return walletFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockChainFacade getBlockChainFacade()
|
||||||
|
{
|
||||||
|
return blockChainFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CryptoFacade getCryptoFacade()
|
||||||
|
{
|
||||||
|
return cryptoFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser()
|
||||||
|
{
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +330,7 @@ public class OffererPaymentProtocol
|
||||||
// We got a take offer request and check if the offer is not already reserved for another user.
|
// We got a take offer request and check if the offer is not already reserved for another user.
|
||||||
// If the offer is free we send an accept message.
|
// If the offer is free we send an accept message.
|
||||||
|
|
||||||
public void onTakeOfferRequested(PeerAddress sender)
|
/* public void onTakeOfferRequested(PeerAddress sender)
|
||||||
{
|
{
|
||||||
log.debug("1.3 onTakeOfferRequested");
|
log.debug("1.3 onTakeOfferRequested");
|
||||||
|
|
||||||
|
@ -108,7 +340,7 @@ public class OffererPaymentProtocol
|
||||||
if (isTakeOfferRequested)
|
if (isTakeOfferRequested)
|
||||||
{
|
{
|
||||||
log.debug("1.3 offer already requested REJECT_TAKE_OFFER_REQUEST");
|
log.debug("1.3 offer already requested REJECT_TAKE_OFFER_REQUEST");
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REJECT_TAKE_OFFER_REQUEST, trade.getId());
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REJECT_TAKE_OFFER_REQUEST, trade.getId());
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
TradeMessageListener listener = new TradeMessageListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -140,7 +372,7 @@ public class OffererPaymentProtocol
|
||||||
log.debug("1.3 onTakeOfferRequested ACCEPT_TAKE_OFFER_REQUEST onResult");
|
log.debug("1.3 onTakeOfferRequested ACCEPT_TAKE_OFFER_REQUEST onResult");
|
||||||
// The accept message has arrived at the peer
|
// The accept message has arrived at the peer
|
||||||
// We set requested flag and remove the offer from the orderbook
|
// We set requested flag and remove the offer from the orderbook
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
|
|
||||||
isTakeOfferRequested = true;
|
isTakeOfferRequested = true;
|
||||||
log.debug("1.3 messageFacade.removeOffer");
|
log.debug("1.3 messageFacade.removeOffer");
|
||||||
|
@ -153,18 +385,18 @@ public class OffererPaymentProtocol
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.warn("1.3 onTakeOfferRequested ACCEPT_TAKE_OFFER_REQUEST onFailed");
|
log.warn("1.3 onTakeOfferRequested ACCEPT_TAKE_OFFER_REQUEST onFailed");
|
||||||
offererPaymentProtocolListener.onFailure("onTakeOfferRequested onSendTradingMessageFailed");
|
// offererPaymentProtocolListener.onFailure("onTakeOfferRequested onSendTradingMessageFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
|
|
||||||
// 1.3a Send accept take offer message
|
// 1.3a Send accept take offer message
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.ACCEPT_TAKE_OFFER_REQUEST, trade.getId());
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.ACCEPT_TAKE_OFFER_REQUEST, trade.getId());
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// 1.4, 2.1 - 2.2 Takers task, we wait until the next incoming message
|
// 1.4, 2.1 - 2.2 Takers task, we wait until the next incoming message
|
||||||
|
@ -175,37 +407,36 @@ public class OffererPaymentProtocol
|
||||||
// Step 2.3
|
// Step 2.3
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onTakeOfferFeePayed(TradeMessage requestTradeMessage)
|
/* public void onTakeOfferFeePayedMessage(SendProofOfTakerOfferFeePaymentMessage requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.3 onTakeOfferFeePayed");
|
log.debug("2.3 onTakeOfferFeePayedMessage");
|
||||||
trade.setTakeOfferFeeTxID(requestTradeMessage.getTakeOfferFeeTxID());
|
trade.setTakeOfferFeeTxID(requestTradeMessage.getTakeOfferFeeTxId());
|
||||||
trade.setTradeAmount(requestTradeMessage.getTradeAmount());
|
trade.setTradeAmount(requestTradeMessage.getTradeAmount());
|
||||||
verifyTakeOfferFeePayment(requestTradeMessage);
|
verifyTakeOfferFeePayment(requestTradeMessage);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.4
|
// Step 2.4
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void verifyTakeOfferFeePayment(TradeMessage requestTradeMessage)
|
/* private void verifyTakeOfferFeePayment(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.4 verifyTakeOfferFeePayment");
|
log.debug("2.4 verifyTakeOfferFeePayment");
|
||||||
//TODO just dummy now, will be async
|
//TODO just dummy now, will be async
|
||||||
int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(requestTradeMessage.getTakeOfferFeeTxID());
|
int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(requestTradeMessage.getTakeOfferFeeTxId());
|
||||||
if (numOfPeersSeenTx > 2)
|
if (numOfPeersSeenTx > 2)
|
||||||
{
|
{
|
||||||
createDepositTx(requestTradeMessage);
|
createDepositTx(requestTradeMessage);
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.5
|
// Step 2.5
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
/* private void createDepositTx(TradeMessageOld requestTradeMessage)
|
||||||
private void createDepositTx(TradeMessage requestTradeMessage)
|
|
||||||
{
|
{
|
||||||
checkNotNull(requestTradeMessage);
|
checkNotNull(requestTradeMessage);
|
||||||
|
|
||||||
|
@ -222,7 +453,7 @@ public class OffererPaymentProtocol
|
||||||
checkNotNull(arbitratorPubKey);
|
checkNotNull(arbitratorPubKey);
|
||||||
|
|
||||||
log.debug("2.5 offererCreatesMSTxAndAddPayment");
|
log.debug("2.5 offererCreatesMSTxAndAddPayment");
|
||||||
log.debug("offererInputAmount " + BtcFormatter.satoshiToString(offererInputAmount));
|
log.debug("offererInputAmount " + BtcFormatter.formatSatoshis(offererInputAmount));
|
||||||
log.debug("offerer pubkey " + offererPubKey);
|
log.debug("offerer pubkey " + offererPubKey);
|
||||||
log.debug("taker pubkey " + takerPubKey);
|
log.debug("taker pubkey " + takerPubKey);
|
||||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||||
|
@ -242,13 +473,13 @@ public class OffererPaymentProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.6
|
// Step 2.6
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void sendDepositTxAndDataForContract(String preparedOffererDepositTxAsHex, String offererPubKey, long offererTxOutIndex)
|
/*private void sendDepositTxAndDataForContract(String preparedOffererDepositTxAsHex, String offererPubKey, long offererTxOutIndex)
|
||||||
{
|
{
|
||||||
log.debug("2.6 sendDepositTxAndDataForContract");
|
log.debug("2.6 sendDepositTxAndDataForContract");
|
||||||
// Send all the requested data
|
// Send all the requested data
|
||||||
|
@ -260,7 +491,7 @@ public class OffererPaymentProtocol
|
||||||
{
|
{
|
||||||
log.debug("2.6 sendDepositTxAndDataForContract onResult");
|
log.debug("2.6 sendDepositTxAndDataForContract onResult");
|
||||||
// Message arrived at taker
|
// Message arrived at taker
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
|
|
||||||
// We wait until we get the signed tx back
|
// We wait until we get the signed tx back
|
||||||
}
|
}
|
||||||
|
@ -269,19 +500,19 @@ public class OffererPaymentProtocol
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.debug("2.6 sendDepositTxAndDataForContract onFailed");
|
log.debug("2.6 sendDepositTxAndDataForContract onFailed");
|
||||||
offererPaymentProtocolListener.onFailure("sendDepositTxAndDataForContract onSendTradingMessageFailed");
|
// offererPaymentProtocolListener.onFailure("sendDepositTxAndDataForContract onSendTradingMessageFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
|
|
||||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountUID());
|
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountUID());
|
||||||
String accountID = user.getAccountID();
|
String accountID = user.getAccountId();
|
||||||
|
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKER_DEPOSIT_PAYMENT, trade.getId(), bankAccount, accountID, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REQUEST_TAKER_DEPOSIT_PAYMENT, trade.getId(), bankAccount, accountID, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
||||||
log.debug("2.6 sendTradingMessage");
|
log.debug("2.6 sendTradingMessage");
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
} */
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// 2.7 - 2.11 Takers task, we wait until the next incoming message
|
// 2.7 - 2.11 Takers task, we wait until the next incoming message
|
||||||
|
@ -292,28 +523,28 @@ public class OffererPaymentProtocol
|
||||||
// Step 3.1 Incoming msg from taker
|
// Step 3.1 Incoming msg from taker
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onDepositTxReadyForPublication(TradeMessage requestTradeMessage)
|
/* public void onRequestOffererPublishDepositTxMessage(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.1 onDepositTxReadyForPublication");
|
log.debug("3.1 onRequestOffererPublishDepositTxMessage");
|
||||||
takerPayoutAddress = requestTradeMessage.getTakerPayoutAddress();
|
takerPayoutAddress = requestTradeMessage.getTakerPayoutAddress();
|
||||||
verifyTaker(requestTradeMessage);
|
verifyTaker(requestTradeMessage);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.2 Verify offerers account registration and against the blacklist
|
// Step 3.2 Verify offerers account registration and against the blacklist
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void verifyTaker(TradeMessage requestTradeMessage)
|
/* private void verifyTaker(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.2 verifyTaker");
|
log.debug("3.2 verifyTaker");
|
||||||
log.debug("3.2.1 verifyAccountRegistration");
|
log.debug("3.2.1 verifyAccountRegistration");
|
||||||
if (blockChainFacade.verifyAccountRegistration())
|
if (blockChainFacade.verifyAccountRegistration())
|
||||||
{
|
{
|
||||||
log.debug("3.2.2 isAccountBlackListed");
|
log.debug("3.2.2 isAccountBlackListed");
|
||||||
if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountID(), requestTradeMessage.getBankAccount()))
|
if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountId(), requestTradeMessage.getBankAccount()))
|
||||||
{
|
{
|
||||||
offererPaymentProtocolListener.onFailure("Taker is blacklisted.");
|
// offererPaymentProtocolListener.onFailure("Taker is blacklisted.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -322,20 +553,19 @@ public class OffererPaymentProtocol
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offererPaymentProtocolListener.onFailure("Takers account registration is invalid.");
|
// offererPaymentProtocolListener.onFailure("Takers account registration is invalid.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.3 Verify and sign the contract
|
// Step 3.3 Verify and sign the contract
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
/* private void verifyAndSignContract(TradeMessageOld requestTradeMessage)
|
||||||
private void verifyAndSignContract(TradeMessage requestTradeMessage)
|
|
||||||
{
|
{
|
||||||
Contract contract = new Contract(offer,
|
Contract contract = new Contract(offer,
|
||||||
trade.getTradeAmount(),
|
trade.getTradeAmount(),
|
||||||
trade.getTakeOfferFeeTxID(),
|
trade.getTakeOfferFeeTxId(),
|
||||||
user.getAccountID(),
|
user.getAccountID(),
|
||||||
requestTradeMessage.getAccountID(),
|
requestTradeMessage.getAccountID(),
|
||||||
user.getCurrentBankAccount(),
|
user.getCurrentBankAccount(),
|
||||||
|
@ -364,13 +594,13 @@ public class OffererPaymentProtocol
|
||||||
{
|
{
|
||||||
log.error("3.3 verifyContract failed");
|
log.error("3.3 verifyContract failed");
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.4 Sign and publish the deposit tx
|
// Step 3.4 Sign and publish the deposit tx
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void signAndPublishDepositTx(TradeMessage requestTradeMessage)
|
/* private void signAndPublishDepositTx(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.4 signAndPublishDepositTx");
|
log.debug("3.4 signAndPublishDepositTx");
|
||||||
|
|
||||||
|
@ -410,13 +640,13 @@ public class OffererPaymentProtocol
|
||||||
e.getStackTrace();// Could not understand form of connected output script: RETURN
|
e.getStackTrace();// Could not understand form of connected output script: RETURN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.5 Send tx id of published deposit tx to taker
|
// Step 3.5 Send tx id of published deposit tx to taker
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void sendDepositTxIdToTaker(Transaction transaction)
|
/*private void sendDepositTxIdToTaker(Transaction transaction)
|
||||||
{
|
{
|
||||||
log.debug("3.5 sendDepositTxIdToTaker");
|
log.debug("3.5 sendDepositTxIdToTaker");
|
||||||
|
|
||||||
|
@ -426,24 +656,24 @@ public class OffererPaymentProtocol
|
||||||
public void onResult()
|
public void onResult()
|
||||||
{
|
{
|
||||||
log.debug("3.5 sendDepositTxIdToTaker DEPOSIT_TX_PUBLISHED onResult");
|
log.debug("3.5 sendDepositTxIdToTaker DEPOSIT_TX_PUBLISHED onResult");
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.warn("3.5 sendDepositTxIdToTaker DEPOSIT_TX_PUBLISHED onFailed");
|
log.warn("3.5 sendDepositTxIdToTaker DEPOSIT_TX_PUBLISHED onFailed");
|
||||||
offererPaymentProtocolListener.onFailure("sendDepositTxAndDataForContract onSendTradingMessageFailed");
|
// offererPaymentProtocolListener.onFailure("sendDepositTxAndDataForContract onSendTradingMessageFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.DEPOSIT_TX_PUBLISHED, trade.getId(), Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.DEPOSIT_TX_PUBLISHED, trade.getId(), Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||||
log.debug("3.5 sendTradingMessage");
|
log.debug("3.5 sendTradingMessage");
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
|
|
||||||
// wait for at least 1 confirmation, then pay Fiat
|
// wait for at least 1 confirmation, then pay Fiat
|
||||||
offererPaymentProtocolListener.onDepositTxPublished(tradeMessage.getDepositTxID());
|
offererPaymentProtocolListener.onDepositTxPublishedMessage(tradeMessage.getDepositTxID());
|
||||||
setupListenerForBlockChainConfirmation(transaction);
|
setupListenerForBlockChainConfirmation(transaction);
|
||||||
}
|
} */
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// 3.6 Taker got informed, but no action from his side required.
|
// 3.6 Taker got informed, but no action from his side required.
|
||||||
|
@ -451,10 +681,10 @@ public class OffererPaymentProtocol
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.7 We setup a listener for block chain confirmation
|
// Step 3.7 We init a listener for block chain confirmation
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void setupListenerForBlockChainConfirmation(Transaction transaction)
|
/* private void setupListenerForBlockChainConfirmation(Transaction transaction)
|
||||||
{
|
{
|
||||||
log.debug("3.7 setupListenerForBlockChainConfirmation");
|
log.debug("3.7 setupListenerForBlockChainConfirmation");
|
||||||
|
|
||||||
|
@ -477,6 +707,7 @@ public class OffererPaymentProtocol
|
||||||
onDepositTxConfirmedInBlockchain();
|
onDepositTxConfirmedInBlockchain();
|
||||||
transaction.getConfidenceForAddress().removeEventListener(this);
|
transaction.getConfidenceForAddress().removeEventListener(this);
|
||||||
} */
|
} */
|
||||||
|
/*
|
||||||
|
|
||||||
}
|
}
|
||||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||||
|
@ -487,27 +718,27 @@ public class OffererPaymentProtocol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
} */
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.8 We check if the block chain confirmation is >= 1
|
// Step 3.8 We check if the block chain confirmation is >= 1
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void updateConfirmation(TransactionConfidence confidence)
|
/* private void updateConfirmation(TransactionConfidence confidence)
|
||||||
{
|
{
|
||||||
log.debug("3.8 updateConfirmation " + confidence);
|
log.debug("3.8 updateConfirmation " + confidence);
|
||||||
offererPaymentProtocolListener.onDepositTxConfirmedUpdate(confidence);
|
offererPaymentProtocolListener.onDepositTxConfirmedUpdate(confidence);
|
||||||
}
|
} */
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.9 Blockchain confirmation received, so tell user he should start bank transfer
|
// Step 3.9 Blockchain confirmation received, so tell user he should start bank transfer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void onDepositTxConfirmedInBlockchain()
|
/* private void onDepositTxConfirmedInBlockchain()
|
||||||
{
|
{
|
||||||
log.debug("3.9 readyForBankTransfer");
|
log.debug("3.9 readyForBankTransfer");
|
||||||
offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||||
}
|
} */
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// Offerer need to start bank tx, after he done it he call the next step
|
// Offerer need to start bank tx, after he done it he call the next step
|
||||||
|
@ -518,25 +749,25 @@ public class OffererPaymentProtocol
|
||||||
// Step 3.10 User clicked the "bank transfer inited" button, so we tell the peer that we started the bank tx
|
// Step 3.10 User clicked the "bank transfer inited" button, so we tell the peer that we started the bank tx
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@SuppressWarnings("ConstantConditions")
|
/*
|
||||||
public void bankTransferInited()
|
public void onBankTransferInitedMessage()
|
||||||
{
|
{
|
||||||
log.debug("3.10 bankTransferInited");
|
log.debug("3.10 onBankTransferInitedMessage");
|
||||||
|
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
TradeMessageListener listener = new TradeMessageListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void onResult()
|
public void onResult()
|
||||||
{
|
{
|
||||||
log.debug("3.10 bankTransferInited BANK_TX_INITED onResult");
|
log.debug("3.10 onBankTransferInitedMessage BANK_TX_INITED onResult");
|
||||||
offererPaymentProtocolListener.onProgress(getProgress());
|
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.warn("3.10 bankTransferInited BANK_TX_INITED onFailed");
|
log.warn("3.10 onBankTransferInitedMessage BANK_TX_INITED onFailed");
|
||||||
offererPaymentProtocolListener.onFailure("bankTransferInited BANK_TX_INITED");
|
// offererPaymentProtocolListener.onFailure("onBankTransferInitedMessage BANK_TX_INITED");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -560,7 +791,7 @@ public class OffererPaymentProtocol
|
||||||
String offererSignatureS = offererSignature.s.toString();
|
String offererSignatureS = offererSignature.s.toString();
|
||||||
String depositTxAsHex = result.getValue();
|
String depositTxAsHex = result.getValue();
|
||||||
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
|
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.BANK_TX_INITED, trade.getId(),
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.BANK_TX_INITED, trade.getId(),
|
||||||
depositTxAsHex,
|
depositTxAsHex,
|
||||||
offererSignatureR,
|
offererSignatureR,
|
||||||
offererSignatureS,
|
offererSignatureS,
|
||||||
|
@ -583,7 +814,7 @@ public class OffererPaymentProtocol
|
||||||
log.error("3.10 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
log.error("3.10 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// We wait until taker has received the money on his bank account, that might take a while.
|
// We wait until taker has received the money on his bank account, that might take a while.
|
||||||
|
@ -594,25 +825,23 @@ public class OffererPaymentProtocol
|
||||||
// Step 3.14 We received the payout tx. Trade is completed
|
// Step 3.14 We received the payout tx. Trade is completed
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onPayoutTxPublished(TradeMessage tradeMessage)
|
/* public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.14 onPayoutTxPublished");
|
log.debug("onPayoutTxPublishedMessage");
|
||||||
log.debug("3.14 TRADE COMPLETE!!!!!!!!!!!");
|
offererPaymentProtocolListener.onPayoutTxPublishedMessage(tradeMessage.getPayoutTxAsHex());
|
||||||
|
} */
|
||||||
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Util
|
// Util
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private double getProgress()
|
/* private double getProgress()
|
||||||
{
|
{
|
||||||
currentStep++;
|
currentStep++;
|
||||||
int numberOfSteps = 10;
|
int numberOfSteps = 10;
|
||||||
return (double) currentStep / (double) numberOfSteps;
|
return (double) currentStep / (double) numberOfSteps;
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,19 +2,12 @@ package io.bitsquare.trade.payment.offerer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.TransactionConfidence;
|
import com.google.bitcoin.core.TransactionConfidence;
|
||||||
|
|
||||||
@SuppressWarnings("EmptyMethod")
|
public interface OffererAsBuyerProtocolListener
|
||||||
public interface OffererPaymentProtocolListener
|
|
||||||
{
|
{
|
||||||
@SuppressWarnings("UnusedParameters")
|
|
||||||
void onProgress(double progress);
|
|
||||||
|
|
||||||
void onFailure(String failureMessage);
|
|
||||||
|
|
||||||
void onDepositTxPublished(String depositTxID);
|
void onDepositTxPublished(String depositTxID);
|
||||||
|
|
||||||
void onDepositTxConfirmedInBlockchain();
|
void onDepositTxConfirmedInBlockchain();
|
||||||
|
|
||||||
@SuppressWarnings("UnusedParameters")
|
|
||||||
void onDepositTxConfirmedUpdate(TransactionConfidence confidence);
|
void onDepositTxConfirmedUpdate(TransactionConfidence confidence);
|
||||||
|
|
||||||
void onPayoutTxPublished(String payoutTxID);
|
void onPayoutTxPublished(String payoutTxID);
|
|
@ -0,0 +1,22 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class AcceptTakeOfferRequestMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 6177387534087739018L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
public AcceptTakeOfferRequestMessage(String tradeId)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class BankTransferInitedMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -3479634129543632523L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
private String depositTxAsHex;
|
||||||
|
private String offererSignatureR;
|
||||||
|
private String offererSignatureS;
|
||||||
|
private BigInteger offererPaybackAmount;
|
||||||
|
private BigInteger takerPaybackAmount;
|
||||||
|
private String offererPayoutAddress;
|
||||||
|
|
||||||
|
public BankTransferInitedMessage(String tradeId, String depositTxAsHex,
|
||||||
|
String offererSignatureR,
|
||||||
|
String offererSignatureS,
|
||||||
|
BigInteger offererPaybackAmount,
|
||||||
|
BigInteger takerPaybackAmount,
|
||||||
|
String offererPayoutAddress)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.depositTxAsHex = depositTxAsHex;
|
||||||
|
this.offererSignatureR = offererSignatureR;
|
||||||
|
this.offererSignatureS = offererSignatureS;
|
||||||
|
this.offererPaybackAmount = offererPaybackAmount;
|
||||||
|
this.takerPaybackAmount = takerPaybackAmount;
|
||||||
|
this.offererPayoutAddress = offererPayoutAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return depositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererPayoutAddress()
|
||||||
|
{
|
||||||
|
return offererPayoutAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererSignatureS()
|
||||||
|
{
|
||||||
|
return offererSignatureS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getOffererPaybackAmount()
|
||||||
|
{
|
||||||
|
return offererPaybackAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getTakerPaybackAmount()
|
||||||
|
{
|
||||||
|
return takerPaybackAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererSignatureR()
|
||||||
|
{
|
||||||
|
return offererSignatureR;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class DepositTxPublishedMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1532231540167406581L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
private String depositTxAsHex;
|
||||||
|
|
||||||
|
public DepositTxPublishedMessage(String tradeId, String depositTxAsHex)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.depositTxAsHex = depositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return depositTxAsHex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class RejectTakeOfferRequestMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -8088557759642128139L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
public RejectTakeOfferRequestMessage(String tradeId)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class RequestTakerDepositPaymentMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -3988720410493712913L;
|
||||||
|
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
private BankAccount bankAccount;
|
||||||
|
private String accountID;
|
||||||
|
private String offererPubKey;
|
||||||
|
private String preparedOffererDepositTxAsHex;
|
||||||
|
private long offererTxOutIndex;
|
||||||
|
|
||||||
|
public RequestTakerDepositPaymentMessage(String tradeId, BankAccount bankAccount, String accountID, String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.bankAccount = bankAccount;
|
||||||
|
this.accountID = accountID;
|
||||||
|
this.offererPubKey = offererPubKey;
|
||||||
|
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||||
|
this.offererTxOutIndex = offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BankAccount getBankAccount()
|
||||||
|
{
|
||||||
|
return bankAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccountID()
|
||||||
|
{
|
||||||
|
return accountID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererPubKey()
|
||||||
|
{
|
||||||
|
return offererPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPreparedOffererDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return preparedOffererDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOffererTxOutIndex()
|
||||||
|
{
|
||||||
|
return offererTxOutIndex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||||
|
import io.nucleo.scheduler.tasks.AbstractTask;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class AbstractOffererAsBuyerTask extends AbstractTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AbstractOffererAsBuyerTask.class);
|
||||||
|
|
||||||
|
protected OffererAsBuyerProtocol sharedModel;
|
||||||
|
|
||||||
|
public AbstractOffererAsBuyerTask(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
addResultHandlers(resultHandler);
|
||||||
|
addFaultHandlers(faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setModel(Object model)
|
||||||
|
{
|
||||||
|
sharedModel = (OffererAsBuyerProtocol) model;
|
||||||
|
super.setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class CreateDepositTx extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CreateDepositTx.class);
|
||||||
|
|
||||||
|
public CreateDepositTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sharedModel.setOffererPubKey(sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getPubKeyAsHexString());
|
||||||
|
Transaction tx = sharedModel.getWalletFacade().offererCreatesMSTxAndAddPayment(sharedModel.getTrade().getCollateralAmount(),
|
||||||
|
sharedModel.getOffererPubKey(),
|
||||||
|
sharedModel.getTakerMultiSigPubKey(),
|
||||||
|
sharedModel.getTrade().getOffer().getArbitrator().getPubKeyAsHex(),
|
||||||
|
sharedModel.getTrade().getId());
|
||||||
|
|
||||||
|
sharedModel.setPreparedOffererDepositTxAsHex(Utils.bytesToHexString(tx.bitcoinSerialize()));
|
||||||
|
sharedModel.setOffererTxOutIndex(tx.getInput(0).getOutpoint().getIndex());
|
||||||
|
complete();
|
||||||
|
} catch (InsufficientMoneyException e)
|
||||||
|
{
|
||||||
|
log.error("Create deposit tx failed due InsufficientMoneyException " + e);
|
||||||
|
failed(new Exception("Create deposit tx failed due InsufficientMoneyException " + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.AcceptTakeOfferRequestMessage;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.RejectTakeOfferRequestMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class HandleTakeOfferRequest extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
|
||||||
|
|
||||||
|
public HandleTakeOfferRequest(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
if (sharedModel.getTrade().getState() == Trade.State.OPEN)
|
||||||
|
{
|
||||||
|
AcceptTakeOfferRequestMessage msg = new AcceptTakeOfferRequestMessage(sharedModel.getTrade().getId());
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, msg, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("AcceptTakeOfferRequestMessage successfully arrived at peer");
|
||||||
|
sharedModel.getTrade().setState(Trade.State.ACCEPTED);
|
||||||
|
sharedModel.getMessageFacade().removeOffer(sharedModel.getTrade().getOffer());
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("AcceptTakeOfferRequestMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("AcceptTakeOfferRequestMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RejectTakeOfferRequestMessage msg = new RejectTakeOfferRequestMessage(sharedModel.getTrade().getId());
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, msg, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RejectTakeOfferRequestMessage successfully arrived at peer");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("RejectTakeOfferRequestMessage failed to arrive at peer");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
log.error("Offer not marked as open.");
|
||||||
|
failed(new Exception("Offer not marked as open."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.RequestTakerDepositPaymentMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class RequestTakerDepositPayment extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RequestTakerDepositPayment.class);
|
||||||
|
|
||||||
|
public RequestTakerDepositPayment(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(sharedModel.getTrade().getId(),
|
||||||
|
sharedModel.getUser().getBankAccount(sharedModel.getTrade().getOffer().getBankAccountUID()),
|
||||||
|
sharedModel.getUser().getAccountID(),
|
||||||
|
sharedModel.getOffererPubKey(),
|
||||||
|
sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||||
|
sharedModel.getOffererTxOutIndex());
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("RequestTakerDepositPaymentMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("RequestTakerDepositPaymentMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.DepositTxPublishedMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendDepositTxIdToTaker extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
|
||||||
|
|
||||||
|
public SendDepositTxIdToTaker(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(sharedModel.getTrade().getId(), Utils.bytesToHexString(sharedModel.getTrade().getDepositTransaction().bitcoinSerialize()));
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("DepositTxPublishedMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("DepositTxPublishedMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("DepositTxPublishedMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.ECKey;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.BankTransferInitedMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import javafx.util.Pair;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendSignedPayoutTx extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendSignedPayoutTx.class);
|
||||||
|
|
||||||
|
public SendSignedPayoutTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Transaction depositTransaction = sharedModel.getTrade().getDepositTransaction();
|
||||||
|
BigInteger collateral = sharedModel.getTrade().getCollateralAmount();
|
||||||
|
BigInteger offererPaybackAmount = sharedModel.getTrade().getTradeAmount().add(collateral);
|
||||||
|
BigInteger takerPaybackAmount = collateral;
|
||||||
|
|
||||||
|
log.trace("offererPaybackAmount " + offererPaybackAmount);
|
||||||
|
log.trace("takerPaybackAmount " + takerPaybackAmount);
|
||||||
|
log.trace("depositTransaction.getHashAsString() " + depositTransaction.getHashAsString());
|
||||||
|
log.trace("takerPayoutAddress " + sharedModel.getTakerPayoutAddress());
|
||||||
|
|
||||||
|
Pair<ECKey.ECDSASignature, String> result = sharedModel.getWalletFacade().offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(),
|
||||||
|
offererPaybackAmount,
|
||||||
|
takerPaybackAmount,
|
||||||
|
sharedModel.getTakerPayoutAddress(),
|
||||||
|
sharedModel.getTrade().getId());
|
||||||
|
|
||||||
|
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||||
|
String offererSignatureR = offererSignature.r.toString();
|
||||||
|
String offererSignatureS = offererSignature.s.toString();
|
||||||
|
String depositTxAsHex = result.getValue();
|
||||||
|
String offererPayoutAddress = sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getAddressString();
|
||||||
|
|
||||||
|
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(sharedModel.getTrade().getId(),
|
||||||
|
depositTxAsHex,
|
||||||
|
offererSignatureR,
|
||||||
|
offererSignatureS,
|
||||||
|
offererPaybackAmount,
|
||||||
|
takerPaybackAmount,
|
||||||
|
offererPayoutAddress);
|
||||||
|
|
||||||
|
log.trace("depositTxAsHex " + depositTxAsHex);
|
||||||
|
log.trace("offererSignatureR " + offererSignatureR);
|
||||||
|
log.trace("offererSignatureS " + offererSignatureS);
|
||||||
|
log.trace("offererPaybackAmount " + offererPaybackAmount);
|
||||||
|
log.trace("takerPaybackAmount " + takerPaybackAmount);
|
||||||
|
log.trace("offererPayoutAddress " + offererPayoutAddress);
|
||||||
|
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("BankTransferInitedMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("BankTransferInitedMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("BankTransferInitedMessage failed to arrive at peer"));
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Exception at OffererCreatesAndSignsPayoutTx " + e);
|
||||||
|
failed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.TransactionConfidence;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SetupListenerForBlockChainConfirmation extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
||||||
|
|
||||||
|
public SetupListenerForBlockChainConfirmation(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
//TODO
|
||||||
|
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||||
|
|
||||||
|
Transaction tx = sharedModel.getTrade().getDepositTransaction();
|
||||||
|
tx.getConfidence().addEventListener(new TransactionConfidence.Listener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
|
||||||
|
{
|
||||||
|
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||||
|
if (reason == ChangeReason.SEEN_PEERS)
|
||||||
|
{
|
||||||
|
sharedModel.getListener().onDepositTxConfirmedUpdate(tx.getConfidence());
|
||||||
|
}
|
||||||
|
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||||
|
{
|
||||||
|
sharedModel.getListener().onDepositTxConfirmedInBlockchain();
|
||||||
|
tx.getConfidence().removeEventListener(this);
|
||||||
|
log.trace("Tx is in blockchain");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SignAndPublishDepositTx extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
|
||||||
|
|
||||||
|
public SignAndPublishDepositTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sharedModel.getWalletFacade().offererSignAndPublishTx(sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||||
|
sharedModel.getSignedTakerDepositTxAsHex(),
|
||||||
|
sharedModel.getTxConnOutAsHex(),
|
||||||
|
sharedModel.getTxScriptSigAsHex(),
|
||||||
|
sharedModel.getOffererTxOutIndex(),
|
||||||
|
sharedModel.getTakerTxOutIndex(),
|
||||||
|
new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
||||||
|
sharedModel.getTrade().setDepositTransaction(transaction);
|
||||||
|
sharedModel.getListener().onDepositTxPublished(transaction.getHashAsString());
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.error("offererSignAndPublishTx failed:" + t);
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("offererSignAndPublishTx failed:" + e);
|
||||||
|
failed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.Contract;
|
||||||
|
import io.bitsquare.util.Utilities;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyAndSignContract extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class);
|
||||||
|
|
||||||
|
public VerifyAndSignContract(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
Contract contract = new Contract(sharedModel.getTrade().getOffer(),
|
||||||
|
sharedModel.getTrade().getTradeAmount(),
|
||||||
|
sharedModel.getTrade().getTakeOfferFeeTxId(),
|
||||||
|
sharedModel.getUser().getAccountID(),
|
||||||
|
sharedModel.getPeersAccountId(),
|
||||||
|
sharedModel.getUser().getCurrentBankAccount(),
|
||||||
|
sharedModel.getPeersBankAccount(),
|
||||||
|
sharedModel.getTrade().getOffer().getMessagePubKeyAsHex(),
|
||||||
|
sharedModel.getTakerMessagePubKey());
|
||||||
|
|
||||||
|
String contractAsJson = Utilities.objectToJson(contract);
|
||||||
|
// log.trace("Offerer contract created: " + contract);
|
||||||
|
// log.trace("Offerers contractAsJson: " + contractAsJson);
|
||||||
|
// log.trace("Takers contractAsJson: " + sharedModel.peersContractAsJson);
|
||||||
|
if (contractAsJson.equals(sharedModel.getPeersContractAsJson()))
|
||||||
|
{
|
||||||
|
log.trace("The 2 contracts as json does match");
|
||||||
|
String signature = sharedModel.getCryptoFacade().signContract(sharedModel.getWalletFacade().getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||||
|
sharedModel.getTrade().setContract(contract);
|
||||||
|
sharedModel.getTrade().setContractAsJson(contractAsJson);
|
||||||
|
sharedModel.getTrade().setContractTakerSignature(signature);
|
||||||
|
//log.trace("signature: " + signature);
|
||||||
|
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO use diff output as feedback ?
|
||||||
|
log.error("Contracts are not matching.");
|
||||||
|
log.error("Offerers contractAsJson: " + contractAsJson);
|
||||||
|
log.error("Takers contractAsJson: " + sharedModel.getPeersContractAsJson());
|
||||||
|
|
||||||
|
failed(new Exception("Contracts are not matching"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyTakeOfferFeePayment extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class);
|
||||||
|
|
||||||
|
public VerifyTakeOfferFeePayment(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
//TODO mocked yet, need a confidence listeners
|
||||||
|
int numOfPeersSeenTx = sharedModel.getWalletFacade().getNumOfPeersSeenTx(sharedModel.getTakeOfferFeeTxId());
|
||||||
|
if (numOfPeersSeenTx > 2)
|
||||||
|
{
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package io.bitsquare.trade.payment.offerer.tasks;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyTakerAccount extends AbstractOffererAsBuyerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
|
||||||
|
|
||||||
|
public VerifyTakerAccount(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
//TODO mocked yet
|
||||||
|
if (sharedModel.getBlockChainFacade().verifyAccountRegistration())
|
||||||
|
{
|
||||||
|
if (sharedModel.getBlockChainFacade().isAccountBlackListed(sharedModel.getPeersAccountId(), sharedModel.getPeersBankAccount()))
|
||||||
|
{
|
||||||
|
log.error("Taker is blacklisted");
|
||||||
|
failed(new Exception("Taker is blacklisted"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("Account registration validation for peer failed.");
|
||||||
|
failed(new Exception("Account registration validation for peer failed."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,58 +1,78 @@
|
||||||
package io.bitsquare.trade.payment.taker;
|
package io.bitsquare.trade.payment.taker;
|
||||||
|
|
||||||
import com.google.bitcoin.core.AddressFormatException;
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
import com.google.bitcoin.core.Transaction;
|
||||||
import com.google.bitcoin.core.Utils;
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
import io.bitsquare.msg.MessageFacade;
|
import io.bitsquare.msg.MessageFacade;
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
import io.bitsquare.msg.TradeMessageType;
|
|
||||||
import io.bitsquare.msg.listeners.AddressLookupListener;
|
|
||||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
|
||||||
import io.bitsquare.trade.Contract;
|
|
||||||
import io.bitsquare.trade.Offer;
|
|
||||||
import io.bitsquare.trade.Trade;
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.BankTransferInitedMessage;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.DepositTxPublishedMessage;
|
||||||
|
import io.bitsquare.trade.payment.offerer.messages.RequestTakerDepositPaymentMessage;
|
||||||
|
import io.bitsquare.trade.payment.taker.tasks.*;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import io.bitsquare.util.Utilities;
|
import io.nucleo.scheduler.SequenceScheduler;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
//TODO use states
|
//TODO use states
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public class TakerPaymentProtocol
|
public class TakerAsSellerProtocol
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(TakerPaymentProtocol.class);
|
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
|
||||||
|
|
||||||
|
|
||||||
|
// provided data
|
||||||
|
private final String id;
|
||||||
private final Trade trade;
|
private final Trade trade;
|
||||||
private final Offer offer;
|
private final TakerAsSellerProtocolListener listener;
|
||||||
private final TakerPaymentProtocolListener takerPaymentProtocolListener;
|
private final WorkerResultHandler resultHandler;
|
||||||
|
private final WorkerFaultHandler faultHandler;
|
||||||
private final MessageFacade messageFacade;
|
private final MessageFacade messageFacade;
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
private final BlockChainFacade blockChainFacade;
|
private final BlockChainFacade blockChainFacade;
|
||||||
private final CryptoFacade cryptoFacade;
|
private final CryptoFacade cryptoFacade;
|
||||||
private final User user;
|
private final User user;
|
||||||
|
// private
|
||||||
|
private final SequenceScheduler scheduler_1;
|
||||||
|
// written/read by task
|
||||||
|
private String payoutTxAsHex;
|
||||||
private PeerAddress peerAddress;
|
private PeerAddress peerAddress;
|
||||||
|
private Transaction signedTakerDepositTx;
|
||||||
|
private long takerTxOutIndex;
|
||||||
|
// written by message, read by tasks
|
||||||
|
private String peersAccountId;
|
||||||
|
private BankAccount peersBankAccount;
|
||||||
|
private String offererPubKey;
|
||||||
|
private String preparedOffererDepositTxAsHex;
|
||||||
|
private long offererTxOutIndex;
|
||||||
|
private String depositTxAsHex;
|
||||||
|
private String offererSignatureR;
|
||||||
|
private String offererSignatureS;
|
||||||
|
private BigInteger offererPaybackAmount;
|
||||||
|
private BigInteger takerPaybackAmount;
|
||||||
|
private String offererPayoutAddress;
|
||||||
private int currentStep = 0;
|
private int currentStep = 0;
|
||||||
|
private SequenceScheduler scheduler_2;
|
||||||
|
private SequenceScheduler scheduler_3;
|
||||||
|
private SequenceScheduler scheduler_4;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public TakerPaymentProtocol(Trade trade,
|
public TakerAsSellerProtocol(Trade trade,
|
||||||
TakerPaymentProtocolListener takerPaymentProtocolListener,
|
TakerAsSellerProtocolListener listener,
|
||||||
|
WorkerResultHandler resultHandler,
|
||||||
|
WorkerFaultHandler faultHandler,
|
||||||
MessageFacade messageFacade,
|
MessageFacade messageFacade,
|
||||||
WalletFacade walletFacade,
|
WalletFacade walletFacade,
|
||||||
BlockChainFacade blockChainFacade,
|
BlockChainFacade blockChainFacade,
|
||||||
|
@ -60,32 +80,271 @@ public class TakerPaymentProtocol
|
||||||
User user)
|
User user)
|
||||||
{
|
{
|
||||||
this.trade = trade;
|
this.trade = trade;
|
||||||
this.takerPaymentProtocolListener = takerPaymentProtocolListener;
|
this.listener = listener;
|
||||||
|
this.resultHandler = resultHandler;
|
||||||
|
this.faultHandler = faultHandler;
|
||||||
this.messageFacade = messageFacade;
|
this.messageFacade = messageFacade;
|
||||||
this.walletFacade = walletFacade;
|
this.walletFacade = walletFacade;
|
||||||
this.blockChainFacade = blockChainFacade;
|
this.blockChainFacade = blockChainFacade;
|
||||||
this.cryptoFacade = cryptoFacade;
|
this.cryptoFacade = cryptoFacade;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
|
||||||
offer = trade.getOffer();
|
id = trade.getId();
|
||||||
|
|
||||||
|
log.debug("TakerAsSellerProtocol created");
|
||||||
|
|
||||||
messageFacade.addTakerPaymentProtocol(this);
|
messageFacade.addTakerPaymentProtocol(this);
|
||||||
|
|
||||||
|
// start with first task sequence
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new GetPeerAddress(resultHandler, faultHandler));
|
||||||
|
tasks.add(new RequestTakeOffer(resultHandler, faultHandler));
|
||||||
|
scheduler_1 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_1.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void takeOffer()
|
public void onAcceptTakeOfferRequestMessage()
|
||||||
{
|
{
|
||||||
log.debug("1 takeOffer");
|
log.debug("onAcceptTakeOfferRequestMessage");
|
||||||
findPeerAddress();
|
if (scheduler_1.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new PayTakeOfferFee(resultHandler, faultHandler));
|
||||||
|
tasks.add(new SendTakeOfferFeePayedTxId(resultHandler, faultHandler));
|
||||||
|
scheduler_2 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_2.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_1 has not completed yet.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onRejectTakeOfferRequestMessage()
|
||||||
|
{
|
||||||
|
log.debug("onRejectTakeOfferRequestMessage");
|
||||||
|
if (scheduler_1.getHasCompleted())
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_1 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onRequestTakerDepositPaymentMessage");
|
||||||
|
peersAccountId = message.getAccountID();
|
||||||
|
peersBankAccount = message.getBankAccount();
|
||||||
|
offererPubKey = message.getOffererPubKey();
|
||||||
|
preparedOffererDepositTxAsHex = message.getPreparedOffererDepositTxAsHex();
|
||||||
|
offererTxOutIndex = message.getOffererTxOutIndex();
|
||||||
|
|
||||||
|
if (scheduler_2.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new VerifyOffererAccount(resultHandler, faultHandler));
|
||||||
|
tasks.add(new CreateAndSignContract(resultHandler, faultHandler));
|
||||||
|
tasks.add(new PayDeposit(resultHandler, faultHandler));
|
||||||
|
tasks.add(new SendSignedTakerDepositTxAsHex(resultHandler, faultHandler));
|
||||||
|
scheduler_3 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_3.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_2 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// informational, does only trigger UI feedback/update
|
||||||
|
public void onDepositTxPublishedMessage(DepositTxPublishedMessage message)
|
||||||
|
{
|
||||||
|
log.debug("onDepositTxPublishedMessage");
|
||||||
|
String txID = getWalletFacade().takerCommitDepositTx(message.getDepositTxAsHex());
|
||||||
|
listener.onDepositTxPublished(txID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// informational, store data for later, does only trigger UI feedback/update
|
||||||
|
public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage)
|
||||||
|
{
|
||||||
|
log.debug("onBankTransferInitedMessage");
|
||||||
|
|
||||||
|
depositTxAsHex = tradeMessage.getDepositTxAsHex();
|
||||||
|
offererSignatureR = tradeMessage.getOffererSignatureR();
|
||||||
|
offererSignatureS = tradeMessage.getOffererSignatureS();
|
||||||
|
offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
|
||||||
|
takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
|
||||||
|
offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
|
||||||
|
|
||||||
|
listener.onBankTransferInited(tradeMessage.getTradeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||||
|
public void onUIEventFiatReceived()
|
||||||
|
{
|
||||||
|
log.debug("onUIEventFiatReceived");
|
||||||
|
if (scheduler_3.getHasCompleted())
|
||||||
|
{
|
||||||
|
List<Worker> tasks = new ArrayList<>();
|
||||||
|
tasks.add(new SignAndPublishPayoutTx(resultHandler, faultHandler));
|
||||||
|
tasks.add(new SendPayoutTxToOfferer(resultHandler, faultHandler));
|
||||||
|
scheduler_4 = new SequenceScheduler(tasks, this);
|
||||||
|
scheduler_4.execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("scheduler_3 has not completed yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters, Setters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public String getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Trade getTrade()
|
||||||
|
{
|
||||||
|
return trade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TakerAsSellerProtocolListener getListener()
|
||||||
|
{
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageFacade getMessageFacade()
|
||||||
|
{
|
||||||
|
return messageFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WalletFacade getWalletFacade()
|
||||||
|
{
|
||||||
|
return walletFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockChainFacade getBlockChainFacade()
|
||||||
|
{
|
||||||
|
return blockChainFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CryptoFacade getCryptoFacade()
|
||||||
|
{
|
||||||
|
return cryptoFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser()
|
||||||
|
{
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PeerAddress getPeerAddress()
|
||||||
|
{
|
||||||
|
return peerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeerAddress(PeerAddress peerAddress)
|
||||||
|
{
|
||||||
|
this.peerAddress = peerAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction getSignedTakerDepositTx()
|
||||||
|
{
|
||||||
|
return signedTakerDepositTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignedTakerDepositTx(Transaction signedTakerDepositTx)
|
||||||
|
{
|
||||||
|
this.signedTakerDepositTx = signedTakerDepositTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTakerTxOutIndex()
|
||||||
|
{
|
||||||
|
return takerTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTakerTxOutIndex(long takerTxOutIndex)
|
||||||
|
{
|
||||||
|
this.takerTxOutIndex = takerTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPeersAccountId()
|
||||||
|
{
|
||||||
|
return peersAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BankAccount getPeersBankAccount()
|
||||||
|
{
|
||||||
|
return peersBankAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererPubKey()
|
||||||
|
{
|
||||||
|
return offererPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPreparedOffererDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return preparedOffererDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOffererTxOutIndex()
|
||||||
|
{
|
||||||
|
return offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return depositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererSignatureR()
|
||||||
|
{
|
||||||
|
return offererSignatureR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererSignatureS()
|
||||||
|
{
|
||||||
|
return offererSignatureS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getOffererPaybackAmount()
|
||||||
|
{
|
||||||
|
return offererPaybackAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getTakerPaybackAmount()
|
||||||
|
{
|
||||||
|
return takerPaybackAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOffererPayoutAddress()
|
||||||
|
{
|
||||||
|
return offererPayoutAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPayoutTxAsHex()
|
||||||
|
{
|
||||||
|
return payoutTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPayoutTxAsHex(String payoutTxAsHex)
|
||||||
|
{
|
||||||
|
this.payoutTxAsHex = payoutTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 1.1
|
// Step 1.1
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void findPeerAddress()
|
|
||||||
|
/* private void findPeerAddress()
|
||||||
{
|
{
|
||||||
log.debug("1.1 findPeerAddress");
|
log.debug("1.1 findPeerAddress");
|
||||||
AddressLookupListener addressLookupListener = new AddressLookupListener()
|
AddressLookupListener addressLookupListener = new AddressLookupListener()
|
||||||
|
@ -115,14 +374,13 @@ public class TakerPaymentProtocol
|
||||||
|
|
||||||
// Request the peers address from the DHT
|
// Request the peers address from the DHT
|
||||||
messageFacade.getPeerAddress(offer.getMessagePubKeyAsHex(), addressLookupListener);
|
messageFacade.getPeerAddress(offer.getMessagePubKeyAsHex(), addressLookupListener);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 1.2
|
// Step 1.2
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void requestTakeOffer()
|
/* private void requestTakeOffer()
|
||||||
{
|
{
|
||||||
log.debug("1.2 requestTakeOffer");
|
log.debug("1.2 requestTakeOffer");
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
TradeMessageListener listener = new TradeMessageListener()
|
||||||
|
@ -153,7 +411,7 @@ public class TakerPaymentProtocol
|
||||||
// Send the take offer request
|
// Send the take offer request
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId());
|
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId());
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
|
@ -167,27 +425,27 @@ public class TakerPaymentProtocol
|
||||||
|
|
||||||
|
|
||||||
// 1.4a offerer has accepted the take offer request. Move on to step 2.
|
// 1.4a offerer has accepted the take offer request. Move on to step 2.
|
||||||
public void onTakeOfferRequestAccepted()
|
/* public void onAcceptTakeOfferRequestMessage()
|
||||||
{
|
{
|
||||||
log.debug("1.4a onTakeOfferRequestAccepted");
|
log.debug("1.4a onAcceptTakeOfferRequestMessage");
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
|
|
||||||
payOfferFee(trade);
|
payOfferFee(trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.4b Offerer has rejected the take offer request. The UI controller will handle the case.
|
// 1.4b Offerer has rejected the take offer request. The UI controller will onResult the case.
|
||||||
public void onTakeOfferRequestRejected()
|
public void onRejectTakeOfferRequestMessage()
|
||||||
{
|
{
|
||||||
log.debug("1.4b onTakeOfferRequestRejected");
|
log.debug("1.4b onRejectTakeOfferRequestMessage");
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.1
|
// Step 2.1
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void payOfferFee(Trade trade)
|
/* private void payOfferFee(Trade trade)
|
||||||
{
|
{
|
||||||
log.debug("2.1 payTakeOfferFee");
|
log.debug("2.1 payTakeOfferFee");
|
||||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||||
|
@ -201,7 +459,7 @@ public class TakerPaymentProtocol
|
||||||
// Offer fee payed successfully.
|
// Offer fee payed successfully.
|
||||||
trade.setTakeOfferFeeTxID(transaction.getHashAsString());
|
trade.setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
|
|
||||||
// move on
|
// move on
|
||||||
sendTakerOfferFeeTxID(transaction.getHashAsString());
|
sendTakerOfferFeeTxID(transaction.getHashAsString());
|
||||||
|
@ -211,19 +469,19 @@ public class TakerPaymentProtocol
|
||||||
public void onFailure(Throwable t)
|
public void onFailure(Throwable t)
|
||||||
{
|
{
|
||||||
log.debug("2.1 payTakeOfferFee onFailure");
|
log.debug("2.1 payTakeOfferFee onFailure");
|
||||||
takerPaymentProtocolListener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
// listener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Pay the offer fee
|
// Pay the offer fee
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
walletFacade.payTakeOfferFee(trade.getId(), callback);
|
walletFacade.payTakeOfferFee(trade.getId(), callback);
|
||||||
} catch (InsufficientMoneyException e)
|
} catch (InsufficientMoneyException e)
|
||||||
{
|
{
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -235,7 +493,7 @@ public class TakerPaymentProtocol
|
||||||
// 0 block confirmation is acceptable for the fee to not block the process
|
// 0 block confirmation is acceptable for the fee to not block the process
|
||||||
// The offerer will wait until a minimum of peers seen the tx before sending his data.
|
// The offerer will wait until a minimum of peers seen the tx before sending his data.
|
||||||
// We also get the multisig tx delivered
|
// We also get the multisig tx delivered
|
||||||
private void sendTakerOfferFeeTxID(String takeOfferFeeTxID)
|
/* private void sendTakerOfferFeeTxID(String takeOfferFeeTxID)
|
||||||
{
|
{
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID");
|
log.debug("2.2 sendTakerOfferFeeTxID");
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
TradeMessageListener listener = new TradeMessageListener()
|
||||||
|
@ -245,7 +503,7 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID onResult");
|
log.debug("2.2 sendTakerOfferFeeTxID onResult");
|
||||||
// Message has arrived
|
// Message has arrived
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
//listener.onProgress(getProgress());
|
||||||
|
|
||||||
// We wait until the offerer send us the data
|
// We wait until the offerer send us the data
|
||||||
}
|
}
|
||||||
|
@ -254,21 +512,21 @@ public class TakerPaymentProtocol
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.debug("2.2 sendTakerOfferFeeTxID onFailed");
|
log.debug("2.2 sendTakerOfferFeeTxID onFailed");
|
||||||
takerPaymentProtocolListener.onFailure("requestAccountDetails onSendTradingMessageFailed");
|
// //TakerAsSellerProtocol.this. listener.onFailure("requestAccountDetails onSendTradingMessageFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// this.listener.onProgress(getProgress());
|
||||||
|
|
||||||
// 2.3. send request for the account details and send fee tx id so offerer can verify that the fee has been paid.
|
// 2.3. send request for the account details and send fee tx id so offerer can verify that the fee has been paid.
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
||||||
trade.getId(),
|
trade.getId(),
|
||||||
trade.getTradeAmount(),
|
trade.getTradeAmount(),
|
||||||
takeOfferFeeTxID,
|
takeOfferFeeTxID,
|
||||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString());
|
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString());
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// 2.3 - 2.6 Offerers tasks, we are in waiting mode
|
// 2.3 - 2.6 Offerers tasks, we are in waiting mode
|
||||||
|
@ -279,27 +537,27 @@ public class TakerPaymentProtocol
|
||||||
// Step 2.7 Incoming msg from offerer
|
// Step 2.7 Incoming msg from offerer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onTakerDepositPaymentRequested(TradeMessage requestTradeMessage)
|
/*public void onRequestTakerDepositPaymentMessage(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.7 onTakerDepositPaymentRequested");
|
log.debug("2.7 onRequestTakerDepositPaymentMessage");
|
||||||
verifyOfferer(requestTradeMessage);
|
verifyOfferer(requestTradeMessage);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.8 Verify offerers account registration and against the blacklist
|
// Step 2.8 Verify offerers account registration and against the blacklist
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void verifyOfferer(TradeMessage requestTradeMessage)
|
/*private void verifyOfferer(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.8 verifyOfferer");
|
log.debug("2.8 verifyOfferer");
|
||||||
log.debug("2.8.1 verifyAccountRegistration");
|
log.debug("2.8.1 verifyAccountRegistration");
|
||||||
if (blockChainFacade.verifyAccountRegistration())
|
if (blockChainFacade.verifyAccountRegistration())
|
||||||
{
|
{
|
||||||
log.debug("2.8.2 isAccountBlackListed");
|
log.debug("2.8.2 isAccountBlackListed");
|
||||||
if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountID(), requestTradeMessage.getBankAccount()))
|
if (blockChainFacade.isAccountBlackListed(requestTradeMessage.getAccountId(), requestTradeMessage.getBankAccount()))
|
||||||
{
|
{
|
||||||
takerPaymentProtocolListener.onFailure("Offerer is blacklisted.");
|
// listener.onFailure("Offerer is blacklisted.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -308,35 +566,35 @@ public class TakerPaymentProtocol
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
takerPaymentProtocolListener.onFailure("Offerers account registration is invalid.");
|
// listener.onFailure("Offerers account registration is invalid.");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.9 Create and sign the contract
|
// Step 2.9 Create and sign the contract
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void createAndSignContract(TradeMessage requestTradeMessage)
|
/* private void createAndSignContract(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.9 createAndSignContract");
|
log.debug("2.9 createAndSignContract");
|
||||||
checkNotNull(offer);
|
checkNotNull(trade.getOffer());
|
||||||
checkNotNull(trade.getTradeAmount());
|
checkNotNull(trade.getTradeAmount());
|
||||||
checkNotNull(trade.getTakeOfferFeeTxID());
|
checkNotNull(trade.getTakeOfferFeeTxId());
|
||||||
checkNotNull(requestTradeMessage.getAccountID());
|
checkNotNull(requestTradeMessage.getAccountId());
|
||||||
checkNotNull(user.getAccountID());
|
checkNotNull(user.getAccountId());
|
||||||
checkNotNull(requestTradeMessage.getBankAccount());
|
checkNotNull(requestTradeMessage.getBankAccount());
|
||||||
checkNotNull(user.getCurrentBankAccount());
|
checkNotNull(user.getCurrentBankAccount());
|
||||||
checkNotNull(user.getMessagePubKeyAsHex());
|
checkNotNull(user.getMessagePubKeyAsHex());
|
||||||
|
|
||||||
Contract contract = new Contract(offer,
|
Contract contract = new Contract(trade.getOffer(),
|
||||||
trade.getTradeAmount(),
|
trade.getTradeAmount(),
|
||||||
trade.getTakeOfferFeeTxID(),
|
trade.getTakeOfferFeeTxId(),
|
||||||
requestTradeMessage.getAccountID(),
|
requestTradeMessage.getAccountId(),
|
||||||
user.getAccountID(),
|
user.getAccountId(),
|
||||||
requestTradeMessage.getBankAccount(),
|
requestTradeMessage.getBankAccount(),
|
||||||
user.getCurrentBankAccount(),
|
user.getCurrentBankAccount(),
|
||||||
offer.getMessagePubKeyAsHex(),
|
trade.getOffer().getMessagePubKeyAsHex(),
|
||||||
user.getMessagePubKeyAsHex()
|
user.getMessagePubKeyAsHex()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -352,14 +610,14 @@ public class TakerPaymentProtocol
|
||||||
trade.setContractTakerSignature(signature);
|
trade.setContractTakerSignature(signature);
|
||||||
|
|
||||||
payDeposit(requestTradeMessage);
|
payDeposit(requestTradeMessage);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.10 Pay in the funds to the deposit tx and sign it
|
// Step 2.10 Pay in the funds to the deposit tx and sign it
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void payDeposit(TradeMessage requestTradeMessage)
|
/*private void payDeposit(TradeMessageOld requestTradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("2.10 payDeposit");
|
log.debug("2.10 payDeposit");
|
||||||
|
|
||||||
|
@ -369,7 +627,7 @@ public class TakerPaymentProtocol
|
||||||
|
|
||||||
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
||||||
String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
||||||
String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
|
String arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex();
|
||||||
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
||||||
|
|
||||||
checkNotNull(takerInputAmount);
|
checkNotNull(takerInputAmount);
|
||||||
|
@ -380,8 +638,8 @@ public class TakerPaymentProtocol
|
||||||
checkNotNull(preparedOffererDepositTxAsHex);
|
checkNotNull(preparedOffererDepositTxAsHex);
|
||||||
|
|
||||||
log.debug("2.10 offererCreatesMSTxAndAddPayment");
|
log.debug("2.10 offererCreatesMSTxAndAddPayment");
|
||||||
log.debug("takerAmount " + BtcFormatter.satoshiToString(takerInputAmount));
|
log.debug("takerAmount " + BtcFormatter.formatSatoshis(takerInputAmount));
|
||||||
log.debug("msOutputAmount " + BtcFormatter.satoshiToString(msOutputAmount));
|
log.debug("msOutputAmount " + BtcFormatter.formatSatoshis(msOutputAmount));
|
||||||
log.debug("offerer pubkey " + offererPubKey);
|
log.debug("offerer pubkey " + offererPubKey);
|
||||||
log.debug("taker pubkey " + takerPubKey);
|
log.debug("taker pubkey " + takerPubKey);
|
||||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||||
|
@ -396,14 +654,14 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage());
|
log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 2.11 Send the tx to the offerer
|
// Step 2.11 Send the tx to the offerer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx, long takerTxOutIndex, long offererTxOutIndex)
|
/* private void sendSignedTakerDepositTxAsHex(Transaction signedTakerDepositTx, long takerTxOutIndex, long offererTxOutIndex)
|
||||||
{
|
{
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex");
|
log.debug("2.11 sendSignedTakerDepositTxAsHex");
|
||||||
|
|
||||||
|
@ -414,21 +672,21 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onResult");
|
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onResult");
|
||||||
// Message arrived at taker
|
// Message arrived at taker
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// //TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
||||||
takerPaymentProtocolListener.onFailure("sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
////TakerAsSellerProtocol.this. listener.onFailure("sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// this.listener.onProgress(getProgress());
|
||||||
|
|
||||||
BankAccount bankAccount = user.getCurrentBankAccount();
|
BankAccount bankAccount = user.getCurrentBankAccount();
|
||||||
String accountID = user.getAccountID();
|
String accountID = user.getAccountId();
|
||||||
String messagePubKey = user.getMessagePubKeyAsHex();
|
String messagePubKey = user.getMessagePubKeyAsHex();
|
||||||
String contractAsJson = trade.getContractAsJson();
|
String contractAsJson = trade.getContractAsJson();
|
||||||
String signature = trade.getTakerSignature();
|
String signature = trade.getTakerSignature();
|
||||||
|
@ -443,7 +701,7 @@ public class TakerPaymentProtocol
|
||||||
log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex);
|
log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex);
|
||||||
log.debug("2.10 payoutAddress: " + payoutAddress);
|
log.debug("2.10 payoutAddress: " + payoutAddress);
|
||||||
|
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_OFFERER_DEPOSIT_PUBLICATION,
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REQUEST_OFFERER_DEPOSIT_PUBLICATION,
|
||||||
trade.getId(),
|
trade.getId(),
|
||||||
bankAccount,
|
bankAccount,
|
||||||
accountID,
|
accountID,
|
||||||
|
@ -460,7 +718,7 @@ public class TakerPaymentProtocol
|
||||||
|
|
||||||
log.debug("2.11 sendTradingMessage");
|
log.debug("2.11 sendTradingMessage");
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
|
@ -472,14 +730,14 @@ public class TakerPaymentProtocol
|
||||||
// Step 3.6 Incoming msg from offerer
|
// Step 3.6 Incoming msg from offerer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onDepositTxPublished(TradeMessage tradeMessage)
|
/* public void onDepositTxPublishedMessage(TradeMessageOld tradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.6 DepositTxID received: " + tradeMessage.getDepositTxAsHex());
|
log.debug("3.6 DepositTxID received: " + tradeMessage.getDepositTxAsHex());
|
||||||
|
|
||||||
String txID = walletFacade.takerCommitDepositTx(tradeMessage.getDepositTxAsHex());
|
String txID = walletFacade.takerCommitDepositTx(tradeMessage.getDepositTxAsHex());
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
// listener.onProgress(getProgress());
|
||||||
takerPaymentProtocolListener.onDepositTxPublished(txID);
|
listener.onDepositTxPublishedMessage(txID);
|
||||||
}
|
} */
|
||||||
|
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
|
@ -491,11 +749,11 @@ public class TakerPaymentProtocol
|
||||||
// Step 3.11 Incoming msg from offerer
|
// Step 3.11 Incoming msg from offerer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void onBankTransferInited(TradeMessage tradeMessage)
|
/* public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.11 Bank transfer inited msg received");
|
log.debug("3.11 Bank transfer inited msg received");
|
||||||
takerPaymentProtocolListener.onBankTransferInited(tradeMessage);
|
listener.onBankTransferInitedMessage(tradeMessage);
|
||||||
}
|
} */
|
||||||
|
|
||||||
//************************************************************************************************
|
//************************************************************************************************
|
||||||
// Taker will check periodically his bank account until he received the money. That might take a while...
|
// Taker will check periodically his bank account until he received the money. That might take a while...
|
||||||
|
@ -506,9 +764,9 @@ public class TakerPaymentProtocol
|
||||||
// Step 3.12 User clicked the "bank transfer received" button, so we release the funds for pay out
|
// Step 3.12 User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void releaseBTC(TradeMessage tradeMessage)
|
/* public void onUIEventFiatReceived(TradeMessageOld tradeMessage)
|
||||||
{
|
{
|
||||||
log.debug("3.12 releaseBTC");
|
log.debug("3.12 onUIEventFiatReceived");
|
||||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -516,7 +774,7 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
System.out.println("######### 3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
System.out.println("######### 3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
||||||
log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
||||||
takerPaymentProtocolListener.onTradeCompleted(transaction.getHashAsString());
|
listener.onTradeCompleted(transaction.getHashAsString());
|
||||||
|
|
||||||
sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||||
}
|
}
|
||||||
|
@ -526,7 +784,7 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.error("######### 3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
log.error("######### 3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
||||||
System.err.println("3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
System.err.println("3.12 onFailure walletFacade.takerSignsAndSendsTx");
|
||||||
takerPaymentProtocolListener.onFailure("takerSignsAndSendsTx failed " + t.getMessage());
|
// listener.onFailure("takerSignsAndSendsTx failed " + t.getMessage());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try
|
try
|
||||||
|
@ -551,13 +809,13 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.error("3.12 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
log.error("3.12 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Step 3.13 Send payout txID to offerer
|
// Step 3.13 Send payout txID to offerer
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void sendPayoutTxToOfferer(String payoutTxAsHex)
|
/*void sendPayoutTxToOfferer(String payoutTxAsHex)
|
||||||
{
|
{
|
||||||
log.debug("3.13 sendPayoutTxToOfferer ");
|
log.debug("3.13 sendPayoutTxToOfferer ");
|
||||||
TradeMessageListener listener = new TradeMessageListener()
|
TradeMessageListener listener = new TradeMessageListener()
|
||||||
|
@ -567,27 +825,28 @@ public class TakerPaymentProtocol
|
||||||
{
|
{
|
||||||
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult");
|
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult");
|
||||||
log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!");
|
log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!");
|
||||||
takerPaymentProtocolListener.onProgress(getProgress());
|
//TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailed()
|
public void onFailed()
|
||||||
{
|
{
|
||||||
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
||||||
takerPaymentProtocolListener.onFailure("sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
//TakerAsSellerProtocol.this. listener.onFailure("sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onFailed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getId());
|
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.PAYOUT_TX_PUBLISHED, trade.getId());
|
||||||
tradeMessage.setPayoutTxAsHex(payoutTxAsHex);
|
tradeMessage.setPayoutTxAsHex(payoutTxAsHex);
|
||||||
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
|
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
|
||||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||||
}
|
} */
|
||||||
|
|
||||||
private double getProgress()
|
/* private double getProgress()
|
||||||
{
|
{
|
||||||
currentStep++;
|
currentStep++;
|
||||||
int numberOfSteps = 10;
|
int numberOfSteps = 10;
|
||||||
return (double) currentStep / (double) numberOfSteps;
|
return (double) currentStep / (double) numberOfSteps;
|
||||||
}
|
} */
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.bitsquare.trade.payment.taker;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
|
||||||
|
public interface TakerAsSellerProtocolListener
|
||||||
|
{
|
||||||
|
void onDepositTxPublished(String depositTxId);
|
||||||
|
|
||||||
|
void onBankTransferInited(String tradeId);
|
||||||
|
|
||||||
|
void onTradeCompleted(Trade trade, String hashAsString);
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
package io.bitsquare.trade.payment.taker;
|
|
||||||
|
|
||||||
import io.bitsquare.msg.TradeMessage;
|
|
||||||
|
|
||||||
public interface TakerPaymentProtocolListener
|
|
||||||
{
|
|
||||||
void onProgress(double progress);
|
|
||||||
|
|
||||||
void onFailure(String failureMessage);
|
|
||||||
|
|
||||||
void onDepositTxPublished(String depositTxID);
|
|
||||||
|
|
||||||
void onBankTransferInited(TradeMessage tradeMessage);
|
|
||||||
|
|
||||||
void onTradeCompleted(String hashAsString);
|
|
||||||
}
|
|
|
@ -1,8 +1,8 @@
|
||||||
package io.bitsquare.msg.listeners;
|
package io.bitsquare.trade.payment.taker.listeners;
|
||||||
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
|
||||||
public interface AddressLookupListener
|
public interface GetPeerAddressListener
|
||||||
{
|
{
|
||||||
void onResult(PeerAddress peerAddress);
|
void onResult(PeerAddress peerAddress);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class PayoutTxPublishedMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1288653559218403873L;
|
||||||
|
private final String tradeId;
|
||||||
|
private String payoutTxAsHex;
|
||||||
|
|
||||||
|
public PayoutTxPublishedMessage(String tradeId, String payoutTxAsHex)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.payoutTxAsHex = payoutTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPayoutTxAsHex()
|
||||||
|
{
|
||||||
|
return payoutTxAsHex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class RequestOffererPublishDepositTxMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 2179683654379803071L;
|
||||||
|
private final String tradeId;
|
||||||
|
private BankAccount bankAccount;
|
||||||
|
private String accountID;
|
||||||
|
private String takerMessagePubKey;
|
||||||
|
private String signedTakerDepositTxAsHex;
|
||||||
|
private String txScriptSigAsHex;
|
||||||
|
private String txConnOutAsHex;
|
||||||
|
private String contractAsJson;
|
||||||
|
private String takerContractSignature;
|
||||||
|
private String takerPayoutAddress;
|
||||||
|
private long takerTxOutIndex;
|
||||||
|
|
||||||
|
|
||||||
|
private long offererTxOutIndex;
|
||||||
|
|
||||||
|
public RequestOffererPublishDepositTxMessage(String tradeId,
|
||||||
|
BankAccount bankAccount,
|
||||||
|
String accountID,
|
||||||
|
String takerMessagePubKey,
|
||||||
|
String signedTakerDepositTxAsHex,
|
||||||
|
String txScriptSigAsHex,
|
||||||
|
String txConnOutAsHex,
|
||||||
|
String contractAsJson,
|
||||||
|
String takerContractSignature,
|
||||||
|
String takerPayoutAddress,
|
||||||
|
long takerTxOutIndex,
|
||||||
|
long offererTxOutIndex)
|
||||||
|
{
|
||||||
|
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.bankAccount = bankAccount;
|
||||||
|
this.accountID = accountID;
|
||||||
|
this.takerMessagePubKey = takerMessagePubKey;
|
||||||
|
this.signedTakerDepositTxAsHex = signedTakerDepositTxAsHex;
|
||||||
|
this.txScriptSigAsHex = txScriptSigAsHex;
|
||||||
|
this.txConnOutAsHex = txConnOutAsHex;
|
||||||
|
this.contractAsJson = contractAsJson;
|
||||||
|
this.takerContractSignature = takerContractSignature;
|
||||||
|
this.takerPayoutAddress = takerPayoutAddress;
|
||||||
|
this.takerTxOutIndex = takerTxOutIndex;
|
||||||
|
this.offererTxOutIndex = offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOffererTxOutIndex()
|
||||||
|
{
|
||||||
|
return offererTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BankAccount getBankAccount()
|
||||||
|
{
|
||||||
|
return bankAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccountId()
|
||||||
|
{
|
||||||
|
return accountID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerMessagePubKey()
|
||||||
|
{
|
||||||
|
return takerMessagePubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignedTakerDepositTxAsHex()
|
||||||
|
{
|
||||||
|
return signedTakerDepositTxAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTxScriptSigAsHex()
|
||||||
|
{
|
||||||
|
return txScriptSigAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTxConnOutAsHex()
|
||||||
|
{
|
||||||
|
return txConnOutAsHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContractAsJson()
|
||||||
|
{
|
||||||
|
return contractAsJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerContractSignature()
|
||||||
|
{
|
||||||
|
return takerContractSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerPayoutAddress()
|
||||||
|
{
|
||||||
|
return takerPayoutAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTakerTxOutIndex()
|
||||||
|
{
|
||||||
|
return takerTxOutIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class RequestTakeOfferMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 4660151440192191798L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
public RequestTakeOfferMessage(String tradeId)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.messages;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.TradeMessage;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class TakeOfferFeePayedMessage implements Serializable, TradeMessage
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -5057935061275354312L;
|
||||||
|
private final String tradeId;
|
||||||
|
|
||||||
|
private BigInteger tradeAmount;
|
||||||
|
private String takeOfferFeeTxID;
|
||||||
|
private String takerMultiSigPubKey;
|
||||||
|
|
||||||
|
public TakeOfferFeePayedMessage(String tradeId, String takeOfferFeeTxID, BigInteger tradeAmount, String takerMultiSigPubKey)
|
||||||
|
{
|
||||||
|
this.tradeId = tradeId;
|
||||||
|
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||||
|
this.tradeAmount = tradeAmount;
|
||||||
|
this.takerMultiSigPubKey = takerMultiSigPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTradeId()
|
||||||
|
{
|
||||||
|
return tradeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getTradeAmount()
|
||||||
|
{
|
||||||
|
return tradeAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakeOfferFeeTxID()
|
||||||
|
{
|
||||||
|
return takeOfferFeeTxID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTakerMultiSigPubKey()
|
||||||
|
{
|
||||||
|
return takerMultiSigPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||||
|
import io.nucleo.scheduler.tasks.AbstractTask;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class AbstractTakerAsSellerTask extends AbstractTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AbstractTakerAsSellerTask.class);
|
||||||
|
|
||||||
|
protected TakerAsSellerProtocol sharedModel;
|
||||||
|
|
||||||
|
public AbstractTakerAsSellerTask(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
addResultHandlers(resultHandler);
|
||||||
|
addFaultHandlers(faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setModel(Object model)
|
||||||
|
{
|
||||||
|
sharedModel = (TakerAsSellerProtocol) model;
|
||||||
|
super.setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.Contract;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.bitsquare.util.Utilities;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class CreateAndSignContract extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||||
|
|
||||||
|
public CreateAndSignContract(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
Trade trade = sharedModel.getTrade();
|
||||||
|
Contract contract = new Contract(trade.getOffer(),
|
||||||
|
trade.getTradeAmount(),
|
||||||
|
trade.getTakeOfferFeeTxId(),
|
||||||
|
sharedModel.getPeersAccountId(),
|
||||||
|
sharedModel.getUser().getAccountID(),
|
||||||
|
sharedModel.getPeersBankAccount(),
|
||||||
|
sharedModel.getUser().getCurrentBankAccount(),
|
||||||
|
trade.getOffer().getMessagePubKeyAsHex(),
|
||||||
|
sharedModel.getUser().getMessagePubKeyAsHex()
|
||||||
|
);
|
||||||
|
|
||||||
|
String contractAsJson = Utilities.objectToJson(contract);
|
||||||
|
String signature = sharedModel.getCryptoFacade().signContract(sharedModel.getWalletFacade().getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||||
|
//log.trace("contract: " + contract);
|
||||||
|
//log.debug("contractAsJson: " + contractAsJson);
|
||||||
|
//log.trace("contract signature: " + signature);
|
||||||
|
|
||||||
|
trade.setContract(contract);
|
||||||
|
trade.setContractAsJson(contractAsJson);
|
||||||
|
trade.setContractTakerSignature(signature);
|
||||||
|
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.trade.payment.taker.listeners.GetPeerAddressListener;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import net.tomp2p.peers.PeerAddress;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class GetPeerAddress extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
|
||||||
|
|
||||||
|
public GetPeerAddress(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
sharedModel.getMessageFacade().getPeerAddress(sharedModel.getTrade().getOffer().getMessagePubKeyAsHex(), new GetPeerAddressListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult(PeerAddress address)
|
||||||
|
{
|
||||||
|
log.trace("Received address = " + address.toString());
|
||||||
|
sharedModel.setPeerAddress(address);
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("Lookup for peer address failed.");
|
||||||
|
failed(new Exception("Lookup for peer address failed."));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import io.bitsquare.trade.Trade;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class PayDeposit extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
||||||
|
|
||||||
|
public PayDeposit(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Trade trade = sharedModel.getTrade();
|
||||||
|
BigInteger collateralAmount = trade.getCollateralAmount();
|
||||||
|
sharedModel.setSignedTakerDepositTx(sharedModel.getWalletFacade().takerAddPaymentAndSignTx(trade.getTradeAmount().add(collateralAmount),
|
||||||
|
trade.getTradeAmount().add(collateralAmount).add(collateralAmount),
|
||||||
|
sharedModel.getOffererPubKey(),
|
||||||
|
sharedModel.getWalletFacade().getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(),
|
||||||
|
trade.getOffer().getArbitrator().getPubKeyAsHex(),
|
||||||
|
sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||||
|
trade.getId()));
|
||||||
|
|
||||||
|
log.trace("sharedModel.signedTakerDepositTx: " + sharedModel.getSignedTakerDepositTx());
|
||||||
|
sharedModel.setTakerTxOutIndex(sharedModel.getSignedTakerDepositTx().getInput(1).getOutpoint().getIndex());
|
||||||
|
|
||||||
|
complete();
|
||||||
|
} catch (InsufficientMoneyException e)
|
||||||
|
{
|
||||||
|
log.error("Pay deposit failed due InsufficientMoneyException " + e);
|
||||||
|
failed(new Exception("Pay deposit failed due InsufficientMoneyException " + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class PayTakeOfferFee extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
|
||||||
|
|
||||||
|
public PayTakeOfferFee(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sharedModel.getWalletFacade().payTakeOfferFee(sharedModel.getTrade().getId(), new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
||||||
|
sharedModel.getTrade().setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.error("Take offer fee paid failed with exception: " + t);
|
||||||
|
failed(new Exception("Take offer fee paid failed with exception: " + t));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (InsufficientMoneyException e)
|
||||||
|
{
|
||||||
|
log.error("Take offer fee paid failed due InsufficientMoneyException " + e);
|
||||||
|
failed(new Exception("Take offer fee paid failed due InsufficientMoneyException " + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.RequestTakeOfferMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class RequestTakeOffer extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
|
||||||
|
|
||||||
|
public RequestTakeOffer(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
RequestTakeOfferMessage msg = new RequestTakeOfferMessage(sharedModel.getTrade().getId());
|
||||||
|
sharedModel.getMessageFacade().sendTradingMessage(sharedModel.getPeerAddress(), msg, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RequestTakeOfferMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("RequestTakeOfferMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("RequestTakeOfferMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendPayoutTxToOfferer extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
||||||
|
|
||||||
|
public SendPayoutTxToOfferer(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(sharedModel.getTrade().getId(), sharedModel.getPayoutTxAsHex());
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), tradeMessage, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("PayoutTxPublishedMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("PayoutTxPublishedMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendSignedTakerDepositTxAsHex extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
||||||
|
|
||||||
|
public SendSignedTakerDepositTxAsHex(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(sharedModel.getTrade().getId(),
|
||||||
|
sharedModel.getUser().getCurrentBankAccount(),
|
||||||
|
sharedModel.getUser().getAccountID(),
|
||||||
|
sharedModel.getUser().getMessagePubKeyAsHex(),
|
||||||
|
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().bitcoinSerialize()),
|
||||||
|
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().getInput(1).getScriptBytes()),
|
||||||
|
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
|
||||||
|
sharedModel.getTrade().getContractAsJson(),
|
||||||
|
sharedModel.getTrade().getTakerSignature(),
|
||||||
|
sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getAddressString(),
|
||||||
|
sharedModel.getTakerTxOutIndex(),
|
||||||
|
sharedModel.getOffererTxOutIndex()
|
||||||
|
);
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), tradeMessage, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("RequestOffererDepositPublicationMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("RequestOffererDepositPublicationMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||||
|
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SendTakeOfferFeePayedTxId extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedTxId.class);
|
||||||
|
|
||||||
|
public SendTakeOfferFeePayedTxId(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(sharedModel.getTrade().getId(),
|
||||||
|
sharedModel.getTrade().getTakeOfferFeeTxId(),
|
||||||
|
sharedModel.getTrade().getTradeAmount(),
|
||||||
|
sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getPubKeyAsHexString());
|
||||||
|
|
||||||
|
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), msg, new TradeMessageListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
log.trace("TakeOfferFeePayedMessage successfully arrived at peer");
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailed()
|
||||||
|
{
|
||||||
|
log.error("TakeOfferFeePayedMessage failed to arrive at peer");
|
||||||
|
failed(new Exception("TakeOfferFeePayedMessage failed to arrive at peer"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SignAndPublishPayoutTx extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
||||||
|
|
||||||
|
public SignAndPublishPayoutTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String depositTxAsHex = sharedModel.getDepositTxAsHex();
|
||||||
|
String offererSignatureR = sharedModel.getOffererSignatureR();
|
||||||
|
String offererSignatureS = sharedModel.getOffererSignatureS();
|
||||||
|
BigInteger offererPaybackAmount = sharedModel.getOffererPaybackAmount();
|
||||||
|
BigInteger takerPaybackAmount = sharedModel.getTakerPaybackAmount();
|
||||||
|
String offererPayoutAddress = sharedModel.getOffererPayoutAddress();
|
||||||
|
|
||||||
|
sharedModel.getWalletFacade().takerSignsAndSendsTx(depositTxAsHex,
|
||||||
|
offererSignatureR,
|
||||||
|
offererSignatureS,
|
||||||
|
offererPaybackAmount,
|
||||||
|
takerPaybackAmount,
|
||||||
|
offererPayoutAddress,
|
||||||
|
sharedModel.getTrade().getId(),
|
||||||
|
new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.debug("takerSignsAndSendsTx " + transaction);
|
||||||
|
sharedModel.getListener().onTradeCompleted(sharedModel.getTrade(), transaction.getHashAsString());
|
||||||
|
sharedModel.setPayoutTxAsHex(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.error("Exception at takerSignsAndSendsTx " + t);
|
||||||
|
failed(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error("Exception at takerSignsAndSendsTx " + e);
|
||||||
|
failed(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.bitsquare.trade.payment.taker.tasks;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VerifyOffererAccount extends AbstractTakerAsSellerTask
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
||||||
|
|
||||||
|
public VerifyOffererAccount(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
super(resultHandler, faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
log.trace("execute");
|
||||||
|
|
||||||
|
//TODO mocked yet
|
||||||
|
if (sharedModel.getBlockChainFacade().verifyAccountRegistration())
|
||||||
|
{
|
||||||
|
if (sharedModel.getBlockChainFacade().isAccountBlackListed(sharedModel.getPeersAccountId(), sharedModel.getPeersBankAccount()))
|
||||||
|
{
|
||||||
|
log.error("Offerer is blacklisted");
|
||||||
|
failed(new Exception("Offerer is blacklisted"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.error("Account Registration for peer failed.");
|
||||||
|
failed(new Exception("Account Registration for peer failed."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ public class DSAKeyUtil
|
||||||
public static PublicKey getPublicKeyFromHexString(String publicKeyAsHex) throws NoSuchAlgorithmException, InvalidKeySpecException
|
public static PublicKey getPublicKeyFromHexString(String publicKeyAsHex) throws NoSuchAlgorithmException, InvalidKeySpecException
|
||||||
{
|
{
|
||||||
final byte[] bytes = Utils.parseAsHexOrBase58(publicKeyAsHex);
|
final byte[] bytes = Utils.parseAsHexOrBase58(publicKeyAsHex);
|
||||||
final KeyFactory keyFactory = KeyFactory.INSTANCE("DSA");
|
final KeyFactory keyFactory = KeyFactory.GET_INSTANCE("DSA");
|
||||||
return keyFactory.generatePublic(new X509EncodedKeySpec(bytes));
|
return keyFactory.generatePublic(new X509EncodedKeySpec(bytes));
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ public class DSAKeyUtil
|
||||||
} catch (Throwable throwable)
|
} catch (Throwable throwable)
|
||||||
{
|
{
|
||||||
if (throwable instanceof FileNotFoundException)
|
if (throwable instanceof FileNotFoundException)
|
||||||
log.debug("Files not found. That is ok for the first run.");
|
log.debug("Files not found. That is ok for the first execute.");
|
||||||
else
|
else
|
||||||
log.error("Could not read key files. " + throwable);
|
log.error("Could not read key files. " + throwable);
|
||||||
|
|
||||||
|
|
37
src/main/java/io/nucleo/scheduler/AbstractScheduler.java
Normal file
37
src/main/java/io/nucleo/scheduler/AbstractScheduler.java
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package io.nucleo.scheduler;
|
||||||
|
|
||||||
|
import com.sun.istack.internal.NotNull;
|
||||||
|
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractScheduler extends AbstractWorker implements WorkerResultHandler, WorkerFaultHandler
|
||||||
|
{
|
||||||
|
protected List<Worker> workerElements = new ArrayList<>();
|
||||||
|
|
||||||
|
public void setWorkers(@NotNull List<Worker> workerElements)
|
||||||
|
{
|
||||||
|
this.workerElements = workerElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void executeWorker(Worker worker)
|
||||||
|
{
|
||||||
|
((AbstractWorker) worker).setModel(model);
|
||||||
|
worker.addResultHandlers(this);
|
||||||
|
worker.addFaultHandlers(this);
|
||||||
|
worker.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResult()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFault(Throwable throwable)
|
||||||
|
{
|
||||||
|
failed(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package io.nucleo.scheduler;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.tasks.AbstractDependencyManagedTask;
|
||||||
|
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not tested yet as not used...
|
||||||
|
*/
|
||||||
|
public class DependencyManagedScheduler extends AbstractScheduler
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(DependencyManagedScheduler.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
if (workerElements.size() > 0)
|
||||||
|
workerElements.stream().forEach(this::executeWorker);
|
||||||
|
else
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void executeWorker(Worker worker)
|
||||||
|
{
|
||||||
|
((AbstractWorker) worker).setModel(model);
|
||||||
|
if (((AbstractDependencyManagedTask) worker).areAllDependenciesAvailable())
|
||||||
|
{
|
||||||
|
worker.addResultHandlers(this);
|
||||||
|
worker.addFaultHandlers(this);
|
||||||
|
worker.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(Worker worker)
|
||||||
|
{
|
||||||
|
Predicate<Worker> notCompleted = w -> !w.getHasCompleted();
|
||||||
|
if (workerElements.stream().filter(notCompleted).count() == 0)
|
||||||
|
complete();
|
||||||
|
else
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/io/nucleo/scheduler/ParallelScheduler.java
Normal file
34
src/main/java/io/nucleo/scheduler/ParallelScheduler.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package io.nucleo.scheduler;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not tested yet as not used...
|
||||||
|
*/
|
||||||
|
public class ParallelScheduler extends AbstractScheduler
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(ParallelScheduler.class);
|
||||||
|
private long numberOfChildrenCompleted;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
if (workerElements.size() > 0)
|
||||||
|
workerElements.stream().forEach(this::executeWorker);
|
||||||
|
else
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(Worker worker)
|
||||||
|
{
|
||||||
|
Predicate<Worker> notCompleted = w -> !w.getHasCompleted();
|
||||||
|
if (workerElements.stream().filter(notCompleted).count() == 0)
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/main/java/io/nucleo/scheduler/SequenceScheduler.java
Normal file
44
src/main/java/io/nucleo/scheduler/SequenceScheduler.java
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package io.nucleo.scheduler;
|
||||||
|
|
||||||
|
import com.sun.istack.internal.NotNull;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SequenceScheduler extends AbstractScheduler
|
||||||
|
{
|
||||||
|
private Iterator<Worker> workerIterator;
|
||||||
|
|
||||||
|
public SequenceScheduler(List<Worker> workerElements, Object model)
|
||||||
|
{
|
||||||
|
setWorkers(workerElements);
|
||||||
|
setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SequenceScheduler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWorkers(@NotNull List<Worker> workerElements)
|
||||||
|
{
|
||||||
|
workerIterator = new LinkedList<>(workerElements).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
if (workerIterator != null && workerIterator.hasNext())
|
||||||
|
executeWorker(workerIterator.next());
|
||||||
|
else
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(Worker worker)
|
||||||
|
{
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package io.nucleo.scheduler.example;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||||
|
|
||||||
|
public class ExamplePropertyProviderModel extends PropertyProviderModel
|
||||||
|
{
|
||||||
|
public final Object flashVars;
|
||||||
|
public Object user;
|
||||||
|
|
||||||
|
public ExamplePropertyProviderModel(Object flashVars)
|
||||||
|
{
|
||||||
|
this.flashVars = flashVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.nucleo.scheduler.example;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||||
|
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class SchedulerTestRunner implements WorkerResultHandler, WorkerFaultHandler
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SchedulerTestRunner.class);
|
||||||
|
private static SchedulerTestRunner schedulerTestRunner;
|
||||||
|
|
||||||
|
public SchedulerTestRunner()
|
||||||
|
{
|
||||||
|
/* Map<Object, Object> flashVars = new HashMap<>();
|
||||||
|
flashVars.put("userName", "bully");
|
||||||
|
|
||||||
|
Object model = new ExamplePropertyProviderModel(flashVars);
|
||||||
|
ExampleAS3Scheduler exampleScheduler = new ExampleAS3Scheduler();
|
||||||
|
|
||||||
|
exampleScheduler.setModel(model);
|
||||||
|
exampleScheduler.setResultHandler(() -> {
|
||||||
|
log.debug("setResultHandler ");
|
||||||
|
});
|
||||||
|
exampleScheduler.setFaultHandler((throwable) -> {
|
||||||
|
log.debug("setFaultHandler ");
|
||||||
|
});
|
||||||
|
exampleScheduler.execute(); */
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
schedulerTestRunner = new SchedulerTestRunner();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFault(Throwable throwable)
|
||||||
|
{
|
||||||
|
log.debug("onFault " + this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResult(Worker worker)
|
||||||
|
{
|
||||||
|
log.debug("onResult " + this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package io.nucleo.scheduler.model;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class PropertyProviderModel
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PropertyProviderModel.class);
|
||||||
|
|
||||||
|
public PropertyProviderModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean areAllDependenciesAvailable(List<String> propertyNames)
|
||||||
|
{
|
||||||
|
Predicate<String> isPropertyNotNull = (propertyName) -> read(propertyName) != null;
|
||||||
|
return propertyNames.stream().allMatch(isPropertyNotNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object read(String key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return getField(key).get(this);
|
||||||
|
} catch (IllegalAccessException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Private
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
private Field getField(String key)
|
||||||
|
{
|
||||||
|
Class clazz = this.getClass();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Field field = clazz.getDeclaredField(key);
|
||||||
|
field.setAccessible(true); // make sure a private field is accessible for reflection
|
||||||
|
return field;
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package io.nucleo.scheduler.tasks;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for all tasks using a IPropertyProviderModel instance as a shared model.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractDependencyManagedTask extends AbstractTask
|
||||||
|
{
|
||||||
|
private PropertyProviderModel propertyProviderModel;
|
||||||
|
private List<String> readDependencyKeys = new ArrayList<>();
|
||||||
|
|
||||||
|
public AbstractDependencyManagedTask()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// IRunnable implementation
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setModel(Object model)
|
||||||
|
{
|
||||||
|
propertyProviderModel = (PropertyProviderModel) model;
|
||||||
|
|
||||||
|
super.setModel(model);
|
||||||
|
|
||||||
|
initReadDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Abstract Methods
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be overwritten in subclasses
|
||||||
|
* Used to read the needed data objects for the task.
|
||||||
|
* Typically stored as instance variable in the task.
|
||||||
|
*/
|
||||||
|
protected void initReadDependencies()
|
||||||
|
{
|
||||||
|
// user = read(IUser);
|
||||||
|
// channel = read("channel");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Final protected
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
final protected Object read(String key)
|
||||||
|
{
|
||||||
|
readDependencyKeys.add(key);
|
||||||
|
|
||||||
|
return propertyProviderModel.read(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean areAllDependenciesAvailable()
|
||||||
|
{
|
||||||
|
return propertyProviderModel.areAllDependenciesAvailable(readDependencyKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/main/java/io/nucleo/scheduler/tasks/AbstractTask.java
Normal file
13
src/main/java/io/nucleo/scheduler/tasks/AbstractTask.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package io.nucleo.scheduler.tasks;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for all tasks.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTask extends AbstractWorker
|
||||||
|
{
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AbstractTask.class);
|
||||||
|
}
|
55
src/main/java/io/nucleo/scheduler/worker/AbstractWorker.java
Normal file
55
src/main/java/io/nucleo/scheduler/worker/AbstractWorker.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package io.nucleo.scheduler.worker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractWorker implements Worker
|
||||||
|
{
|
||||||
|
protected List<WorkerResultHandler> resultHandlers = new ArrayList<>();
|
||||||
|
protected List<WorkerFaultHandler> faultHandlers = new ArrayList<>();
|
||||||
|
protected Object model;
|
||||||
|
protected boolean hasFailed;
|
||||||
|
protected boolean hasCompleted;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
abstract public void execute();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addResultHandlers(WorkerResultHandler resultHandler)
|
||||||
|
{
|
||||||
|
resultHandlers.add(resultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addFaultHandlers(WorkerFaultHandler faultHandler)
|
||||||
|
{
|
||||||
|
faultHandlers.add(faultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModel(Object model)
|
||||||
|
{
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getHasCompleted()
|
||||||
|
{
|
||||||
|
return hasCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void complete()
|
||||||
|
{
|
||||||
|
hasCompleted = true;
|
||||||
|
resultHandlers.stream().forEach(e -> e.onResult(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void failed(Throwable throwable)
|
||||||
|
{
|
||||||
|
hasFailed = true;
|
||||||
|
faultHandlers.stream().forEach(e -> e.onFault(throwable));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void destroy()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
19
src/main/java/io/nucleo/scheduler/worker/Worker.java
Normal file
19
src/main/java/io/nucleo/scheduler/worker/Worker.java
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package io.nucleo.scheduler.worker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base interface for all runnable objects (tasks, schedulers)
|
||||||
|
*/
|
||||||
|
public interface Worker
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Starts the execution.
|
||||||
|
*/
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
void addResultHandlers(WorkerResultHandler resultHandler);
|
||||||
|
|
||||||
|
void addFaultHandlers(WorkerFaultHandler faultHandler);
|
||||||
|
|
||||||
|
boolean getHasCompleted();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package io.nucleo.scheduler.worker;
|
||||||
|
|
||||||
|
public interface WorkerFaultHandler
|
||||||
|
{
|
||||||
|
void onFault(Throwable throwable);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package io.nucleo.scheduler.worker;
|
||||||
|
|
||||||
|
public interface WorkerResultHandler
|
||||||
|
{
|
||||||
|
void onResult(Worker worker);
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package io.bitsquare;
|
package io.bitsquare;
|
||||||
|
|
||||||
import io.bitsquare.btc.BtcValidatorTest;
|
import io.bitsquare.btc.BtcValidatorTest;
|
||||||
import io.bitsquare.currency.BitcoinTest;
|
|
||||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||||
|
import io.nucleo.scheduler.SequenceSchedulerTest;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Suite;
|
import org.junit.runners.Suite;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import org.junit.runners.Suite;
|
||||||
BtcValidatorTest.class,
|
BtcValidatorTest.class,
|
||||||
BitSquareConverterTest.class,
|
BitSquareConverterTest.class,
|
||||||
BitSquareValidatorTest.class,
|
BitSquareValidatorTest.class,
|
||||||
BitcoinTest.class
|
SequenceSchedulerTest.class
|
||||||
})
|
})
|
||||||
|
|
||||||
public class BitSquareTestSuite
|
public class BitSquareTestSuite
|
||||||
|
|
|
@ -19,16 +19,16 @@ public class BtcValidatorTest
|
||||||
amount = BigInteger.ZERO;
|
amount = BigInteger.ZERO;
|
||||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||||
|
|
||||||
amount = FeePolicy.TX_FEE_depr;
|
amount = FeePolicy.TX_FEE;
|
||||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||||
|
|
||||||
amount = Transaction.MIN_NONDUST_OUTPUT;
|
amount = Transaction.MIN_NONDUST_OUTPUT;
|
||||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||||
|
|
||||||
amount = FeePolicy.TX_FEE_depr.add(Transaction.MIN_NONDUST_OUTPUT);
|
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT);
|
||||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||||
|
|
||||||
amount = FeePolicy.TX_FEE_depr.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE);
|
amount = FeePolicy.TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(BigInteger.ONE);
|
||||||
assertTrue("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
assertTrue("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
package io.bitsquare.currency;
|
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class BitcoinTest
|
|
||||||
{
|
|
||||||
@Test
|
|
||||||
public void testBitcoin()
|
|
||||||
{
|
|
||||||
Bitcoin bitcoin;
|
|
||||||
Bitcoin compareValue;
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin("0");
|
|
||||||
assertTrue(bitcoin.isZero());
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin("0");
|
|
||||||
compareValue = new Bitcoin("1");
|
|
||||||
assertTrue(bitcoin.isLess(compareValue));
|
|
||||||
assertFalse(compareValue.isLess(bitcoin));
|
|
||||||
assertFalse(compareValue.isEqual(bitcoin));
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin("1");
|
|
||||||
compareValue = new Bitcoin("0");
|
|
||||||
assertFalse(bitcoin.isLess(compareValue));
|
|
||||||
assertTrue(compareValue.isLess(bitcoin));
|
|
||||||
assertFalse(compareValue.isEqual(bitcoin));
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin("1");
|
|
||||||
compareValue = new Bitcoin("1");
|
|
||||||
assertFalse(bitcoin.isLess(compareValue));
|
|
||||||
assertFalse(compareValue.isLess(bitcoin));
|
|
||||||
assertTrue(compareValue.isEqual(bitcoin));
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin(Transaction.MIN_NONDUST_OUTPUT);
|
|
||||||
assertTrue(bitcoin.isMinValue());
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin(Transaction.MIN_NONDUST_OUTPUT.subtract(BigInteger.ONE));
|
|
||||||
assertFalse(bitcoin.isMinValue());
|
|
||||||
|
|
||||||
bitcoin = new Bitcoin(Transaction.MIN_NONDUST_OUTPUT.add(BigInteger.ONE));
|
|
||||||
assertTrue(bitcoin.isMinValue());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,14 @@
|
||||||
package io.bitsquare.gui.util;
|
package io.bitsquare.gui.util;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccountType;
|
||||||
|
import io.bitsquare.locale.Country;
|
||||||
|
import io.bitsquare.trade.Direction;
|
||||||
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.user.Arbitrator;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Currency;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
@ -34,5 +43,37 @@ public class BitSquareValidatorTest
|
||||||
assertFalse(BitSquareValidator.validateStringNotEmpty(null));
|
assertFalse(BitSquareValidator.validateStringNotEmpty(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTradeAmountOutOfRange()
|
||||||
|
{
|
||||||
|
|
||||||
|
assertFalse(BitSquareValidator.tradeAmountOutOfRange(BigInteger.ZERO, new MockOffer(BigInteger.TEN, BigInteger.valueOf(0))));
|
||||||
|
assertTrue(BitSquareValidator.tradeAmountOutOfRange(BigInteger.ZERO, new MockOffer(BigInteger.TEN, BigInteger.valueOf(1))));
|
||||||
|
assertFalse(BitSquareValidator.tradeAmountOutOfRange(BigInteger.TEN, new MockOffer(BigInteger.TEN, BigInteger.valueOf(0))));
|
||||||
|
assertFalse(BitSquareValidator.tradeAmountOutOfRange(BigInteger.TEN, new MockOffer(BigInteger.TEN, BigInteger.valueOf(2))));
|
||||||
|
assertTrue(BitSquareValidator.tradeAmountOutOfRange(BigInteger.TEN, new MockOffer(BigInteger.ONE, BigInteger.valueOf(0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGreaterThanZero()
|
||||||
|
{
|
||||||
|
assertFalse(BitSquareValidator.greaterThanZero(BigInteger.ZERO));
|
||||||
|
assertFalse(BitSquareValidator.greaterThanZero(BigInteger.valueOf(-1)));
|
||||||
|
assertTrue(BitSquareValidator.greaterThanZero(BigInteger.ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MockOffer extends Offer
|
||||||
|
{
|
||||||
|
|
||||||
|
public MockOffer(BigInteger amount, BigInteger minAmount)
|
||||||
|
{
|
||||||
|
super(null, null, 0, amount, minAmount, null, null, null, null, null, 0, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MockOffer(String messagePubKeyAsHex, Direction direction, double price, BigInteger amount, BigInteger minAmount, BankAccountType bankAccountType, Currency currency, Country bankAccountCountry, String bankAccountUID, Arbitrator arbitrator, int collateral, List<Country> acceptedCountries, List<Locale> acceptedLanguageLocales)
|
||||||
|
{
|
||||||
|
super(messagePubKeyAsHex, direction, price, amount, minAmount, bankAccountType, currency, bankAccountCountry, bankAccountUID, arbitrator, collateral, acceptedCountries, acceptedLanguageLocales);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
228
src/test/java/io/nucleo/scheduler/SequenceSchedulerTest.java
Normal file
228
src/test/java/io/nucleo/scheduler/SequenceSchedulerTest.java
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
package io.nucleo.scheduler;
|
||||||
|
|
||||||
|
import io.nucleo.scheduler.tasks.SyncWorker1;
|
||||||
|
import io.nucleo.scheduler.tasks.SyncWorker2;
|
||||||
|
import io.nucleo.scheduler.worker.Worker;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class SequenceSchedulerTest
|
||||||
|
{
|
||||||
|
private final boolean[] hasCompleted = new boolean[1];
|
||||||
|
private final boolean[] hasFailed = new boolean[1];
|
||||||
|
private final boolean[] worker1HasCompleted = new boolean[1];
|
||||||
|
private final boolean[] worker1HasFailed = new boolean[1];
|
||||||
|
private final boolean[] worker2HasCompleted = new boolean[1];
|
||||||
|
private final boolean[] worker2HasFailed = new boolean[1];
|
||||||
|
private SequenceScheduler sequenceScheduler;
|
||||||
|
private Map<String, String> model = new HashMap<>();
|
||||||
|
private List<Worker> workerList = new ArrayList<>();
|
||||||
|
private Throwable worker1Throwable;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
sequenceScheduler = new SequenceScheduler();
|
||||||
|
sequenceScheduler.addResultHandlers((worker) -> {
|
||||||
|
hasCompleted[0] = true;
|
||||||
|
});
|
||||||
|
sequenceScheduler.addFaultHandlers(throwable -> {
|
||||||
|
hasFailed[0] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
hasCompleted[0] = false;
|
||||||
|
hasFailed[0] = false;
|
||||||
|
workerList.clear();
|
||||||
|
model.clear();
|
||||||
|
worker1Throwable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmpty()
|
||||||
|
{
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
assertTrue(sequenceScheduler.getHasCompleted());
|
||||||
|
assertTrue(hasCompleted[0]);
|
||||||
|
assertFalse(hasFailed[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmpty2()
|
||||||
|
{
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
assertTrue(sequenceScheduler.getHasCompleted());
|
||||||
|
assertTrue(hasCompleted[0]);
|
||||||
|
assertFalse(hasFailed[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneWithCompleted()
|
||||||
|
{
|
||||||
|
Worker worker1 = getWorker1(false);
|
||||||
|
workerList.add(worker1);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertTrue(sequenceScheduler.getHasCompleted());
|
||||||
|
assertTrue(hasCompleted[0]);
|
||||||
|
assertFalse(hasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker1.getHasCompleted());
|
||||||
|
assertTrue(worker1HasCompleted[0]);
|
||||||
|
assertFalse(worker1HasFailed[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneWithFailed()
|
||||||
|
{
|
||||||
|
Worker worker1 = getWorker1(true);
|
||||||
|
workerList.add(worker1);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertFalse(sequenceScheduler.getHasCompleted());
|
||||||
|
assertFalse(hasCompleted[0]);
|
||||||
|
assertTrue(hasFailed[0]);
|
||||||
|
|
||||||
|
assertFalse(worker1.getHasCompleted());
|
||||||
|
assertFalse(worker1HasCompleted[0]);
|
||||||
|
assertTrue(worker1HasFailed[0]);
|
||||||
|
assertEquals(SyncWorker1.ERR_MSG, worker1Throwable.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
public void testTwoCompleted()
|
||||||
|
{
|
||||||
|
Worker worker1 = getWorker1(false);
|
||||||
|
Worker worker2 = getWorker2(false);
|
||||||
|
workerList.add(worker1);
|
||||||
|
workerList.add(worker2);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertTrue(sequenceScheduler.getHasCompleted());
|
||||||
|
assertTrue(hasCompleted[0]);
|
||||||
|
assertFalse(hasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker1.getHasCompleted());
|
||||||
|
assertTrue(worker1HasCompleted[0]);
|
||||||
|
assertFalse(worker1HasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker2.getHasCompleted());
|
||||||
|
assertTrue(worker2HasCompleted[0]);
|
||||||
|
assertFalse(worker2HasFailed[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoReverseOrder()
|
||||||
|
{
|
||||||
|
model.put("worker1State", "");
|
||||||
|
model.put("worker2State", "");
|
||||||
|
Worker worker1 = getWorker1(false);
|
||||||
|
Worker worker2 = getWorker2(false);
|
||||||
|
workerList.add(worker2);
|
||||||
|
workerList.add(worker1);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.setModel(model);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertEquals(SyncWorker1.STATE, model.get("worker1State"));
|
||||||
|
assertEquals(SyncWorker2.STATE, model.get("worker2State"));
|
||||||
|
|
||||||
|
assertTrue(sequenceScheduler.getHasCompleted());
|
||||||
|
assertTrue(hasCompleted[0]);
|
||||||
|
assertFalse(hasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker1.getHasCompleted());
|
||||||
|
assertTrue(worker1HasCompleted[0]);
|
||||||
|
assertFalse(worker1HasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker2.getHasCompleted());
|
||||||
|
assertTrue(worker2HasCompleted[0]);
|
||||||
|
assertFalse(worker2HasFailed[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoFirstFailed()
|
||||||
|
{
|
||||||
|
Worker worker1 = getWorker1(true);
|
||||||
|
Worker worker2 = getWorker2(false);
|
||||||
|
workerList.add(worker1);
|
||||||
|
workerList.add(worker2);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertFalse(sequenceScheduler.getHasCompleted());
|
||||||
|
assertFalse(hasCompleted[0]);
|
||||||
|
assertTrue(hasFailed[0]);
|
||||||
|
|
||||||
|
assertFalse(worker1.getHasCompleted());
|
||||||
|
assertFalse(worker1HasCompleted[0]);
|
||||||
|
assertTrue(worker1HasFailed[0]);
|
||||||
|
|
||||||
|
assertFalse(worker2.getHasCompleted());
|
||||||
|
assertFalse(worker2HasCompleted[0]);
|
||||||
|
assertFalse(worker2HasFailed[0]); // second has not been executed and is not failed!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoSecondFailed()
|
||||||
|
{
|
||||||
|
Worker worker1 = getWorker1(false);
|
||||||
|
Worker worker2 = getWorker2(true);
|
||||||
|
workerList.add(worker1);
|
||||||
|
workerList.add(worker2);
|
||||||
|
sequenceScheduler.setWorkers(workerList);
|
||||||
|
sequenceScheduler.execute();
|
||||||
|
|
||||||
|
assertFalse(sequenceScheduler.getHasCompleted());
|
||||||
|
assertFalse(hasCompleted[0]);
|
||||||
|
assertTrue(hasFailed[0]);
|
||||||
|
|
||||||
|
assertTrue(worker1.getHasCompleted());
|
||||||
|
assertTrue(worker1HasCompleted[0]);
|
||||||
|
assertFalse(worker1HasFailed[0]);
|
||||||
|
|
||||||
|
assertFalse(worker2.getHasCompleted());
|
||||||
|
assertFalse(worker2HasCompleted[0]);
|
||||||
|
assertTrue(worker2HasFailed[0]); // second has not been executed and is not failed!
|
||||||
|
}
|
||||||
|
|
||||||
|
private Worker getWorker1(boolean letItFail)
|
||||||
|
{
|
||||||
|
Worker worker1 = new SyncWorker1(letItFail);
|
||||||
|
worker1.addResultHandlers((worker) -> {
|
||||||
|
worker1HasCompleted[0] = true;
|
||||||
|
});
|
||||||
|
worker1.addFaultHandlers(throwable -> {
|
||||||
|
worker1HasFailed[0] = true;
|
||||||
|
worker1Throwable = throwable;
|
||||||
|
});
|
||||||
|
return worker1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Worker getWorker2(boolean letItFail)
|
||||||
|
{
|
||||||
|
Worker worker2 = new SyncWorker2(letItFail);
|
||||||
|
worker2.addResultHandlers((worker) -> {
|
||||||
|
worker2HasCompleted[0] = true;
|
||||||
|
});
|
||||||
|
worker2.addFaultHandlers(throwable -> {
|
||||||
|
worker2HasFailed[0] = true;
|
||||||
|
});
|
||||||
|
return worker2;
|
||||||
|
}
|
||||||
|
}
|
29
src/test/java/io/nucleo/scheduler/tasks/SyncWorker1.java
Normal file
29
src/test/java/io/nucleo/scheduler/tasks/SyncWorker1.java
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package io.nucleo.scheduler.tasks;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SyncWorker1 extends AbstractTask
|
||||||
|
{
|
||||||
|
|
||||||
|
public static String ERR_MSG = "Failure message";
|
||||||
|
public static String STATE = "ok";
|
||||||
|
private boolean letItFail;
|
||||||
|
|
||||||
|
public SyncWorker1(boolean letItFail)
|
||||||
|
{
|
||||||
|
|
||||||
|
this.letItFail = letItFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
System.out.println("execute " + this);
|
||||||
|
if (model != null) ((Map<String, String>) model).put("worker1State", STATE);
|
||||||
|
if (letItFail)
|
||||||
|
failed(new Exception(ERR_MSG));
|
||||||
|
else
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
src/test/java/io/nucleo/scheduler/tasks/SyncWorker2.java
Normal file
27
src/test/java/io/nucleo/scheduler/tasks/SyncWorker2.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package io.nucleo.scheduler.tasks;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SyncWorker2 extends AbstractTask
|
||||||
|
{
|
||||||
|
public static String ERR_MSG = "Failure message";
|
||||||
|
public static String STATE = "ok";
|
||||||
|
private boolean letItFail;
|
||||||
|
|
||||||
|
public SyncWorker2(boolean letItFail)
|
||||||
|
{
|
||||||
|
this.letItFail = letItFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute()
|
||||||
|
{
|
||||||
|
System.out.println("execute " + this);
|
||||||
|
if (model != null) ((Map<String, String>) model).put("worker2State", STATE);
|
||||||
|
if (letItFail)
|
||||||
|
failed(new Exception(ERR_MSG));
|
||||||
|
else
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue