mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-03-15 10:26:37 -04:00
changed trade protocol to use tasks, added scheduler framework
This commit is contained in:
parent
4f26d76746
commit
7e55b7325a
17
pom.xml
17
pom.xml
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project 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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@ -196,6 +196,19 @@
|
||||
<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>
|
||||
-->
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
|
@ -17,7 +17,7 @@ public class BtcFormatter
|
||||
public static BigInteger mBTC = new BigInteger("100000");
|
||||
|
||||
|
||||
public static String satoshiToString(BigInteger value)
|
||||
public static String formatSatoshis(BigInteger value)
|
||||
{
|
||||
return Utils.bitcoinValueToFriendlyString(value);
|
||||
}
|
||||
@ -30,7 +30,14 @@ public class BtcFormatter
|
||||
|
||||
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)
|
||||
|
@ -19,7 +19,7 @@ public class BtcValidator
|
||||
|
||||
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)
|
||||
|
@ -2,22 +2,16 @@ package io.bitsquare.btc;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.currency.Bitcoin;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FeePolicy
|
||||
{
|
||||
public static final BigInteger TX_FEE_depr = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
public static final BigInteger ACCOUNT_REGISTRATION_FEE_depr = Utils.toNanoCoins("0.01");
|
||||
public static final BigInteger CREATE_OFFER_FEE_depr = Utils.toNanoCoins("0.001");
|
||||
public static final BigInteger TAKE_OFFER_FEE_depr = CREATE_OFFER_FEE_depr;
|
||||
|
||||
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;
|
||||
|
||||
public static final BigInteger TX_FEE = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE;
|
||||
public static final BigInteger ACCOUNT_REGISTRATION_FEE = Utils.toNanoCoins("0.01");
|
||||
public static final BigInteger CREATE_OFFER_FEE = Utils.toNanoCoins("0.001");
|
||||
public static final BigInteger TAKE_OFFER_FEE = CREATE_OFFER_FEE;
|
||||
private static final Logger log = LoggerFactory.getLogger(FeePolicy.class);
|
||||
private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR";
|
||||
private static final String createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg";
|
||||
|
@ -86,7 +86,7 @@ public class WalletFacade
|
||||
|
||||
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 give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
||||
// a future version.
|
||||
@ -94,7 +94,7 @@ public class WalletFacade
|
||||
|
||||
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())
|
||||
{
|
||||
@ -527,21 +527,21 @@ public class WalletFacade
|
||||
|
||||
public boolean isRegistrationFeeBalanceSufficient()
|
||||
{
|
||||
return getRegistrationBalance().compareTo(FeePolicy.ACCOUNT_REGISTRATION_FEE_depr) >= 0;
|
||||
return getRegistrationBalance().compareTo(FeePolicy.ACCOUNT_REGISTRATION_FEE) >= 0;
|
||||
}
|
||||
|
||||
public boolean isUnusedTradeAddressBalanceAboveCreationFee()
|
||||
{
|
||||
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
||||
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()
|
||||
{
|
||||
AddressEntry unUsedAddressEntry = getUnusedTradeAddressInfo();
|
||||
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);
|
||||
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);
|
||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
||||
BigInteger fee = FeePolicy.ACCOUNT_REGISTRATION_FEE.subtract(Transaction.MIN_NONDUST_OUTPUT).subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForRegistrationFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
@ -588,12 +588,11 @@ public class WalletFacade
|
||||
printInputs("payRegistrationFee", tx);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public String payCreateOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
Transaction tx = new Transaction(params);
|
||||
BigInteger fee = FeePolicy.CREATE_OFFER_FEE_depr.subtract(FeePolicy.TX_FEE_depr);
|
||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
||||
BigInteger fee = FeePolicy.CREATE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForCreateOfferFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
@ -603,18 +602,18 @@ public class WalletFacade
|
||||
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||
|
||||
printInputs("payTakeOfferFee", tx);
|
||||
printInputs("payCreateOfferFee", tx);
|
||||
log.debug("tx=" + tx);
|
||||
|
||||
return tx.getHashAsString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
|
||||
public String payTakeOfferFee(String offerId, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||
{
|
||||
Transaction tx = new Transaction(params);
|
||||
BigInteger fee = FeePolicy.TAKE_OFFER_FEE_depr.subtract(FeePolicy.TX_FEE_depr);
|
||||
log.trace("fee: " + BtcFormatter.satoshiToString(fee));
|
||||
BigInteger fee = FeePolicy.TAKE_OFFER_FEE.subtract(FeePolicy.TX_FEE);
|
||||
log.trace("fee: " + BtcFormatter.formatSatoshis(fee));
|
||||
tx.addOutput(fee, feePolicy.getAddressForTakeOfferFee());
|
||||
|
||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||
@ -643,7 +642,7 @@ public class WalletFacade
|
||||
FutureCallback<Transaction> callback) throws AddressFormatException, InsufficientMoneyException, IllegalArgumentException
|
||||
{
|
||||
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);
|
||||
// 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.trace("inputs: ");
|
||||
log.trace("offererInputAmount=" + BtcFormatter.satoshiToString(offererInputAmount));
|
||||
log.trace("offererInputAmount=" + BtcFormatter.formatSatoshis(offererInputAmount));
|
||||
log.trace("offererPubKey=" + offererPubKey);
|
||||
log.trace("takerPubKey=" + takerPubKey);
|
||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||
@ -730,8 +729,8 @@ public class WalletFacade
|
||||
{
|
||||
log.debug("takerAddPaymentAndSignTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("takerInputAmount=" + BtcFormatter.satoshiToString(takerInputAmount));
|
||||
log.trace("msOutputAmount=" + BtcFormatter.satoshiToString(msOutputAmount));
|
||||
log.trace("takerInputAmount=" + BtcFormatter.formatSatoshis(takerInputAmount));
|
||||
log.trace("msOutputAmount=" + BtcFormatter.formatSatoshis(msOutputAmount));
|
||||
log.trace("offererPubKey=" + offererPubKey);
|
||||
log.trace("takerPubKey=" + takerPubKey);
|
||||
log.trace("arbitratorPubKey=" + arbitratorPubKey);
|
||||
@ -786,7 +785,7 @@ public class WalletFacade
|
||||
tx.addOutput(tempTx.getOutput(1));
|
||||
|
||||
// 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);
|
||||
|
||||
// Now we sign our input
|
||||
@ -835,13 +834,13 @@ public class WalletFacade
|
||||
// 3. step: deposit tx
|
||||
// Offerer signs tx and publishes it
|
||||
|
||||
public Transaction offererSignAndPublishTx(String offerersFirstTxAsHex,
|
||||
String takersSignedTxAsHex,
|
||||
String takersSignedConnOutAsHex,
|
||||
String takersSignedScriptSigAsHex,
|
||||
long offererTxOutIndex,
|
||||
long takerTxOutIndex,
|
||||
FutureCallback<Transaction> callback)
|
||||
public void offererSignAndPublishTx(String offerersFirstTxAsHex,
|
||||
String takersSignedTxAsHex,
|
||||
String takersSignedConnOutAsHex,
|
||||
String takersSignedScriptSigAsHex,
|
||||
long offererTxOutIndex,
|
||||
long takerTxOutIndex,
|
||||
FutureCallback<Transaction> callback)
|
||||
{
|
||||
log.debug("offererSignAndPublishTx");
|
||||
log.trace("inputs: ");
|
||||
@ -881,7 +880,7 @@ public class WalletFacade
|
||||
takersSignedTxInput.setParent(tx);
|
||||
tx.addInput(takersSignedTxInput);
|
||||
|
||||
//TODO handle non change output cases
|
||||
//TODO onResult non change output cases
|
||||
// add outputs from takers tx, they are already correct
|
||||
tx.addOutput(takersSignedTx.getOutput(0));
|
||||
if (takersSignedTx.getOutputs().size() > 1)
|
||||
@ -942,7 +941,6 @@ public class WalletFacade
|
||||
Futures.addCallback(broadcastComplete, callback);
|
||||
printInputs("tx", tx);
|
||||
log.debug("tx = " + tx);
|
||||
return tx;
|
||||
}
|
||||
|
||||
// 4 step deposit tx: Offerer send deposit tx to taker
|
||||
@ -981,8 +979,8 @@ public class WalletFacade
|
||||
log.debug("offererCreatesAndSignsPayoutTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("depositTxID=" + depositTxID);
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||
log.trace("takerAddress=" + takerAddress);
|
||||
|
||||
// Offerer has published depositTx earlier, so he has it in his wallet
|
||||
@ -1007,24 +1005,22 @@ public class WalletFacade
|
||||
}
|
||||
|
||||
// 6. step payout tx: Taker signs and publish tx
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
|
||||
public Transaction takerSignsAndSendsTx(String depositTxAsHex,
|
||||
String offererSignatureR,
|
||||
String offererSignatureS,
|
||||
BigInteger offererPaybackAmount,
|
||||
BigInteger takerPaybackAmount,
|
||||
String offererAddress,
|
||||
String tradeID,
|
||||
FutureCallback<Transaction> callback) throws AddressFormatException
|
||||
public void takerSignsAndSendsTx(String depositTxAsHex,
|
||||
String offererSignatureR,
|
||||
String offererSignatureS,
|
||||
BigInteger offererPaybackAmount,
|
||||
BigInteger takerPaybackAmount,
|
||||
String offererAddress,
|
||||
String tradeID,
|
||||
FutureCallback<Transaction> callback) throws AddressFormatException
|
||||
{
|
||||
log.debug("takerSignsAndSendsTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||
log.trace("offererSignatureR=" + offererSignatureR);
|
||||
log.trace("offererSignatureS=" + offererSignatureS);
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||
log.trace("offererAddress=" + offererAddress);
|
||||
log.trace("callback=" + callback);
|
||||
|
||||
@ -1062,7 +1058,6 @@ public class WalletFacade
|
||||
log.trace("Check if wallet is consistent: result=" + wallet.isConsistent());
|
||||
printInputs("takerSignsAndSendsTx", tx);
|
||||
log.debug("tx = " + tx);
|
||||
return tx;
|
||||
}
|
||||
|
||||
|
||||
@ -1103,8 +1098,8 @@ public class WalletFacade
|
||||
log.trace("createPayoutTx");
|
||||
log.trace("inputs: ");
|
||||
log.trace("depositTxAsHex=" + depositTxAsHex);
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.satoshiToString(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.satoshiToString(takerPaybackAmount));
|
||||
log.trace("offererPaybackAmount=" + BtcFormatter.formatSatoshis(offererPaybackAmount));
|
||||
log.trace("takerPaybackAmount=" + BtcFormatter.formatSatoshis(takerPaybackAmount));
|
||||
log.trace("offererAddress=" + offererAddress);
|
||||
log.trace("takerAddress=" + takerAddress);
|
||||
|
||||
@ -1122,7 +1117,7 @@ public class WalletFacade
|
||||
{
|
||||
for (TransactionInput input : tx.getInputs())
|
||||
if (input.getConnectedOutput() != null)
|
||||
log.trace(tracePrefix + ": " + BtcFormatter.satoshiToString(input.getConnectedOutput().getValue()));
|
||||
log.trace(tracePrefix + " input value : " + BtcFormatter.formatSatoshis(input.getConnectedOutput().getValue()));
|
||||
else
|
||||
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.gui.components.NetworkSyncPane;
|
||||
import io.bitsquare.gui.market.MarketController;
|
||||
import io.bitsquare.gui.orders.OrdersController;
|
||||
import io.bitsquare.gui.util.Icons;
|
||||
import io.bitsquare.gui.util.Transitions;
|
||||
import io.bitsquare.locale.Localisation;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.Direction;
|
||||
import io.bitsquare.trade.Trading;
|
||||
@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class MainController implements Initializable, NavigationController
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(MainController.class);
|
||||
private static MainController mainController;
|
||||
private static MainController INSTANCE;
|
||||
|
||||
private final User user;
|
||||
private final WalletFacade walletFacade;
|
||||
@ -85,7 +85,7 @@ public class MainController implements Initializable, NavigationController
|
||||
this.trading = trading;
|
||||
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()
|
||||
{
|
||||
messageFacade.init();
|
||||
messageFacade.addTakeOfferRequestListener(this::showTakeOfferRequest);
|
||||
messageFacade.addTakeOfferRequestListener(this::onTakeOfferRequested);
|
||||
|
||||
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));
|
||||
alertButton.setId("nav-alert-button");
|
||||
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"));
|
||||
ordersButtonButtonHolder.getChildren().add(alertButton);
|
||||
}
|
||||
@ -289,13 +291,13 @@ public class MainController implements Initializable, NavigationController
|
||||
balanceTextField.setEditable(false);
|
||||
balanceTextField.setPrefWidth(90);
|
||||
balanceTextField.setId("nav-balance-label");
|
||||
balanceTextField.setText(BtcFormatter.satoshiToString(walletFacade.getWalletBalance()));
|
||||
balanceTextField.setText(BtcFormatter.formatSatoshis(walletFacade.getWalletBalance()));
|
||||
walletFacade.addBalanceListener(new BalanceListener()
|
||||
{
|
||||
@Override
|
||||
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.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
@ -181,7 +180,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
public void onPrevious(ActionEvent actionEvent)
|
||||
public void onPrevious()
|
||||
{
|
||||
if (index > 0)
|
||||
{
|
||||
@ -193,7 +192,7 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onNext(ActionEvent actionEvent)
|
||||
public void onNext()
|
||||
{
|
||||
if (index < allArbitrators.size() - 1)
|
||||
{
|
||||
@ -205,14 +204,14 @@ public class ArbitratorOverviewController implements Initializable, ChildControl
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onSelect(ActionEvent actionEvent)
|
||||
public void onSelect()
|
||||
{
|
||||
settings.addAcceptedArbitrator(currentArbitrator);
|
||||
storage.write(settings.getClass().getName(), settings);
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onClose(ActionEvent actionEvent)
|
||||
public void onClose()
|
||||
{
|
||||
Stage stage = (Stage) rootContainer.getScene().getWindow();
|
||||
stage.close();
|
||||
|
@ -29,7 +29,6 @@ import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
@ -232,7 +231,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
public void onSelectIDType(ActionEvent actionEvent)
|
||||
public void onSelectIDType()
|
||||
{
|
||||
idType = idTypeComboBox.getSelectionModel().getSelectedItem();
|
||||
if (idType != null)
|
||||
@ -259,7 +258,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onAddLanguage(ActionEvent actionEvent)
|
||||
public void onAddLanguage()
|
||||
{
|
||||
Locale item = languageComboBox.getSelectionModel().getSelectedItem();
|
||||
if (!languageList.contains(item) && item != null)
|
||||
@ -271,14 +270,14 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onClearLanguages(ActionEvent actionEvent)
|
||||
public void onClearLanguages()
|
||||
{
|
||||
languageList.clear();
|
||||
languagesTextField.setText("");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onAddMethod(ActionEvent actionEvent)
|
||||
public void onAddMethod()
|
||||
{
|
||||
Arbitrator.METHOD item = methodsComboBox.getSelectionModel().getSelectedItem();
|
||||
if (!methodList.contains(item) && item != null)
|
||||
@ -290,7 +289,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onClearMethods(ActionEvent actionEvent)
|
||||
public void onClearMethods()
|
||||
{
|
||||
methodList.clear();
|
||||
methodsTextField.setText("");
|
||||
@ -298,7 +297,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
|
||||
|
||||
@FXML
|
||||
public void onAddIDVerification(ActionEvent actionEvent)
|
||||
public void onAddIDVerification()
|
||||
{
|
||||
Arbitrator.ID_VERIFICATION idVerification = idVerificationsComboBox.getSelectionModel().getSelectedItem();
|
||||
if (idVerification != null)
|
||||
@ -314,14 +313,14 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onClearIDVerifications(ActionEvent actionEvent)
|
||||
public void onClearIDVerifications()
|
||||
{
|
||||
idVerificationList.clear();
|
||||
idVerificationsTextField.setText("");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onSaveProfile(ActionEvent actionEvent)
|
||||
public void onSaveProfile()
|
||||
{
|
||||
arbitrator = getEditedArbitrator();
|
||||
if (arbitrator != null)
|
||||
@ -349,7 +348,7 @@ public class ArbitratorRegistrationController implements Initializable, ChildCon
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void onPaymentDone(ActionEvent actionEvent)
|
||||
public void onPaymentDone()
|
||||
{
|
||||
//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.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
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, ChildController> controllers = new HashMap<>();
|
||||
private SingleSelectionModel<Tab> selectionModel;
|
||||
@ -24,6 +27,7 @@ public class LazyLoadingTabPane extends TabPane
|
||||
private String[] tabContentFXMLUrls;
|
||||
private Storage storage;
|
||||
private ChildController childController;
|
||||
private int selectedTabIndex = -1;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -50,9 +54,17 @@ public class LazyLoadingTabPane extends TabPane
|
||||
selectionModel = getSelectionModel();
|
||||
selectionModel.selectedItemProperty().addListener((observableValue, oldTab, newTab) -> onTabSelectedIndexChanged());
|
||||
|
||||
Object indexObject = storage.read(storageId);
|
||||
if (indexObject != null)
|
||||
selectionModel.select((int) indexObject);
|
||||
if (selectedTabIndex == -1)
|
||||
{
|
||||
Object indexObject = storage.read(storageId);
|
||||
log.trace("saved index" + indexObject);
|
||||
if (indexObject != null)
|
||||
selectionModel.select((int) indexObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionModel.select(selectedTabIndex);
|
||||
}
|
||||
|
||||
onTabSelectedIndexChanged();
|
||||
}
|
||||
@ -81,6 +93,7 @@ public class LazyLoadingTabPane extends TabPane
|
||||
private void onTabSelectedIndexChanged()
|
||||
{
|
||||
int index = selectionModel.getSelectedIndex();
|
||||
log.trace("onTabSelectedIndexChanged index" + index);
|
||||
if (index < tabContentFXMLUrls.length && index >= 0)
|
||||
{
|
||||
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;
|
||||
if (valueSentToMe.compareTo(BigInteger.ZERO) == 0)
|
||||
{
|
||||
amount.set("-" + BtcFormatter.satoshiToString(valueSentFromMe));
|
||||
amount.set("-" + BtcFormatter.formatSatoshis(valueSentFromMe));
|
||||
|
||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||
{
|
||||
@ -62,7 +62,7 @@ public class TransactionsListItem
|
||||
}
|
||||
else if (valueSentFromMe.compareTo(BigInteger.ZERO) == 0)
|
||||
{
|
||||
amount.set(BtcFormatter.satoshiToString(valueSentToMe));
|
||||
amount.set(BtcFormatter.formatSatoshis(valueSentToMe));
|
||||
type.set("Received with");
|
||||
|
||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||
@ -83,7 +83,7 @@ public class TransactionsListItem
|
||||
}
|
||||
else
|
||||
{
|
||||
amount.set(BtcFormatter.satoshiToString(valueSentToMe.subtract(valueSentFromMe)));
|
||||
amount.set(BtcFormatter.formatSatoshis(valueSentToMe.subtract(valueSentFromMe)));
|
||||
|
||||
boolean outgoing = false;
|
||||
for (TransactionOutput transactionOutput : transaction.getOutputs())
|
||||
|
@ -83,7 +83,7 @@ public class WithdrawalController implements Initializable, ChildController, Hib
|
||||
|
||||
if (BigInteger.ZERO.compareTo(newValue.getBalance()) <= 0)
|
||||
{
|
||||
amountTextField.setText(BtcFormatter.satoshiToString(newValue.getBalance()));
|
||||
amountTextField.setText(BtcFormatter.formatSatoshis(newValue.getBalance()));
|
||||
withdrawFromTextField.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" +
|
||||
"Sending address: " + withdrawFromTextField.getText() + "\n" +
|
||||
"Receiving address: " + withdrawToTextField.getText() + "\n" +
|
||||
"Transaction fee: " + BtcFormatter.satoshiToString(FeePolicy.TX_FEE_depr) + "\n" +
|
||||
"You receive in total: " + BtcFormatter.satoshiToString(amount.subtract(FeePolicy.TX_FEE_depr)) + " BTC\n\n" +
|
||||
"Transaction fee: " + BtcFormatter.formatSatoshis(FeePolicy.TX_FEE) + "\n" +
|
||||
"You receive in total: " + BtcFormatter.formatSatoshis(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" +
|
||||
"Are you sure you withdraw that amount?");
|
||||
if (response == Dialog.Actions.OK)
|
||||
{
|
||||
|
@ -84,7 +84,7 @@ public class WithdrawalListItem
|
||||
this.balance = balance;
|
||||
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)
|
||||
{
|
||||
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()));
|
||||
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;
|
||||
}
|
||||
|
||||
int collateral = (int) (BitSquareConverter.stringToDouble2(collateralTextField.getText()));
|
||||
int collateral = (int) (BitSquareConverter.stringToDouble(collateralTextField.getText()));
|
||||
Arbitrator arbitrator = settings.getRandomArbitrator(collateral, getAmountAsBI());
|
||||
if (arbitrator == null)
|
||||
{
|
||||
@ -189,7 +189,7 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
{
|
||||
offer = new Offer(user.getMessagePubKeyAsHex(),
|
||||
direction,
|
||||
BitSquareConverter.stringToDouble2(priceTextField.getText()),
|
||||
BitSquareConverter.stringToDouble(priceTextField.getText()),
|
||||
BtcFormatter.stringValueToSatoshis(amountTextField.getText()),
|
||||
BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()),
|
||||
user.getCurrentBankAccount().getBankAccountType(),
|
||||
@ -202,39 +202,38 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
settings.getAcceptedLanguageLocales());
|
||||
|
||||
|
||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
||||
{
|
||||
log.info("sendResult onSuccess:" + transaction);
|
||||
if (transaction != null)
|
||||
{
|
||||
offer.setOfferFeePaymentTxID(transaction.getHashAsString());
|
||||
setupSuccessScreen(transaction);
|
||||
|
||||
placeOfferTitle.setText("Transaction sent:");
|
||||
try
|
||||
{
|
||||
trading.addOffer(offer);
|
||||
} catch (IOException e)
|
||||
{
|
||||
Popups.openErrorPopup("Error on adding offer", "Could not add offer to orderbook. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.warn("sendResult onFailure:" + t);
|
||||
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t);
|
||||
placeOfferButton.setDisable(false);
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
walletFacade.payCreateOfferFee(offer.getId(), callback);
|
||||
walletFacade.payCreateOfferFee(offer.getId(), new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction)
|
||||
{
|
||||
log.info("sendResult onSuccess:" + transaction);
|
||||
if (transaction != null)
|
||||
{
|
||||
offer.setOfferFeePaymentTxID(transaction.getHashAsString());
|
||||
setupSuccessScreen(transaction);
|
||||
|
||||
placeOfferTitle.setText("Transaction sent:");
|
||||
try
|
||||
{
|
||||
trading.addOffer(offer);
|
||||
} catch (IOException e)
|
||||
{
|
||||
Popups.openErrorPopup("Error on adding offer", "Could not add offer to orderbook. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.warn("sendResult onFailure:" + t);
|
||||
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t);
|
||||
placeOfferButton.setDisable(false);
|
||||
}
|
||||
});
|
||||
placeOfferButton.setDisable(true);
|
||||
} catch (InsufficientMoneyException e1)
|
||||
{
|
||||
@ -279,8 +278,8 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
|
||||
private double getVolume()
|
||||
{
|
||||
double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
|
||||
double amountAsDouble = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
double priceAsDouble = BitSquareConverter.stringToDouble(priceTextField.getText());
|
||||
return amountAsDouble * priceAsDouble;
|
||||
}
|
||||
|
||||
@ -293,10 +292,10 @@ public class CreateOfferController implements Initializable, ChildController, Hi
|
||||
@SuppressWarnings("UnusedAssignment")
|
||||
private boolean inputValid()
|
||||
{
|
||||
double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
|
||||
double minAmountAsDouble = BitSquareConverter.stringToDouble2(minAmountTextField.getText());
|
||||
double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
double collateralAsDouble = BitSquareConverter.stringToDouble2(collateralTextField.getText());
|
||||
double priceAsDouble = BitSquareConverter.stringToDouble(priceTextField.getText());
|
||||
double minAmountAsDouble = BitSquareConverter.stringToDouble(minAmountTextField.getText());
|
||||
double amountAsDouble = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
double collateralAsDouble = BitSquareConverter.stringToDouble(collateralTextField.getText());
|
||||
|
||||
return priceAsDouble > 0 &&
|
||||
amountAsDouble > 0 &&
|
||||
|
@ -13,7 +13,7 @@ import io.bitsquare.gui.MainController;
|
||||
import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.NavigationItem;
|
||||
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.util.BitSquareConverter;
|
||||
import io.bitsquare.gui.util.BitSquareFormatter;
|
||||
@ -115,7 +115,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||
{
|
||||
orderBook.init();
|
||||
|
||||
// setup table
|
||||
// init table
|
||||
setCountryColumnCellFactory();
|
||||
setBankAccountTypeColumnCellFactory();
|
||||
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.");
|
||||
if (response == Dialog.Actions.OK)
|
||||
{
|
||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (registrationMissingAction == settingsCommandLink)
|
||||
{
|
||||
MainController.INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.SETTINGS);
|
||||
}
|
||||
else if (registrationMissingAction == depositFeeCommandLink)
|
||||
{
|
||||
MainController.INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||
MainController.GET_INSTANCE().navigateToView(NavigationItem.FUNDS);
|
||||
}
|
||||
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.");
|
||||
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())
|
||||
{
|
||||
TakerTradeController takerTradeController = (TakerTradeController) navigationController.navigateToView(NavigationItem.TAKE_OFFER);
|
||||
TakerOfferController takerOfferController = (TakerOfferController) navigationController.navigateToView(NavigationItem.TAKE_OFFER);
|
||||
|
||||
BigInteger requestedAmount;
|
||||
if (!"".equals(amount.getText()))
|
||||
@ -337,8 +337,8 @@ public class OrderBookController implements Initializable, ChildController
|
||||
else
|
||||
requestedAmount = offer.getAmount();
|
||||
|
||||
if (takerTradeController != null)
|
||||
takerTradeController.initWithData(offer, requestedAmount);
|
||||
if (takerOfferController != null)
|
||||
takerOfferController.initWithData(offer, requestedAmount);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -541,7 +541,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||
} catch (ParseException e)
|
||||
{
|
||||
amount.setText(oldValue);
|
||||
d = BitSquareConverter.stringToDouble2(oldValue);
|
||||
d = BitSquareConverter.stringToDouble(oldValue);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import io.bitsquare.gui.components.ValidatedTextField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?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">
|
||||
<panes>
|
||||
|
||||
<TitledPane fx:id="profileTitledPane" text="Offer details">
|
||||
<TitledPane fx:id="takeOfferTitledPane" text="Offer details">
|
||||
<ScrollPane fitToWidth="true">
|
||||
<GridPane hgap="5.0" vgap="5.0">
|
||||
<padding>
|
||||
@ -18,43 +19,41 @@
|
||||
<Label text="Take offer:" id="headline-label"/>
|
||||
|
||||
<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"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<TextField fx:id="totalTextField" GridPane.rowIndex="6" GridPane.columnIndex="1"/>
|
||||
|
||||
|
||||
<Button text="Take offer and pay" onAction="#onTakeOffer" defaultButton="true" GridPane.rowIndex="7" GridPane.columnIndex="1"/>
|
||||
<TextField fx:id="totalTextField" editable="false" GridPane.rowIndex="6" 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="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"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<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"/>
|
||||
<TextField fx:id="supportedCountriesTextField" GridPane.rowIndex="13" GridPane.columnIndex="1"/>
|
||||
<TextField fx:id="supportedCountriesTextField" editable="false" GridPane.rowIndex="13" GridPane.columnIndex="1"/>
|
||||
|
||||
|
||||
<columnConstraints>
|
||||
@ -63,30 +62,110 @@
|
||||
</columnConstraints>
|
||||
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
|
||||
<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="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 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>
|
||||
</ScrollPane>
|
||||
</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 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>
|
||||
|
||||
</panes>
|
||||
|
@ -1,32 +1,30 @@
|
||||
package io.bitsquare.gui.market.trade;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.bank.BankAccountType;
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.currency.Bitcoin;
|
||||
import io.bitsquare.currency.Fiat;
|
||||
import io.bitsquare.gui.ChildController;
|
||||
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.BitSquareFormatter;
|
||||
import io.bitsquare.locale.CountryUtil;
|
||||
import io.bitsquare.locale.LanguageUtil;
|
||||
import io.bitsquare.gui.util.BitSquareValidator;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.trade.Direction;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.Trading;
|
||||
import io.bitsquare.user.Arbitrator;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.util.Currency;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Accordion;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -38,18 +36,29 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
private final Trading trading;
|
||||
private final WalletFacade walletFacade;
|
||||
private final MessageFacade messageFacade;
|
||||
|
||||
private NavigationController navigationController;
|
||||
private Offer offer;
|
||||
private Bitcoin requestedAmount;
|
||||
private BigInteger requestedAmount;
|
||||
private String tradeId;
|
||||
private String depositTxId;
|
||||
|
||||
@FXML
|
||||
private AnchorPane rootContainer;
|
||||
@FXML
|
||||
private Accordion accordion;
|
||||
@FXML
|
||||
private TitledPane profileTitledPane;
|
||||
private TitledPane takeOfferTitledPane, waitBankTxTitledPane, summaryTitledPane;
|
||||
@FXML
|
||||
private TextField amountTextField, priceTextField, volumeTextField, collateralTextField, feeTextField, totalTextField, bankAccountTypeTextField, countryTextField,
|
||||
arbitratorsTextField, supportedLanguagesTextField, supportedCountriesTextField;
|
||||
|
||||
private ValidatedTextField amountTextField;
|
||||
@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
|
||||
@ -61,23 +70,6 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
this.trading = trading;
|
||||
this.walletFacade = walletFacade;
|
||||
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 void initWithData(Offer offer, Bitcoin requestedAmount)
|
||||
public void initWithData(Offer offer, BigInteger requestedAmount)
|
||||
{
|
||||
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,35 +93,35 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
@Override
|
||||
public void initialize(URL url, ResourceBundle rb)
|
||||
{
|
||||
accordion.setExpandedPane(profileTitledPane);
|
||||
accordion.setExpandedPane(takeOfferTitledPane);
|
||||
}
|
||||
|
||||
if (offer != null && requestedAmount != null)
|
||||
{
|
||||
amountTextField.setText(requestedAmount.getFormattedValue());
|
||||
amountTextField.setPromptText(new Bitcoin(offer.getMinAmount()).getFormattedValue() + " - " + new Bitcoin(offer.getAmount()).getFormattedValue());
|
||||
priceTextField.setText(new Fiat(offer.getPrice()).getFormattedValue());
|
||||
public void applyData()
|
||||
{
|
||||
amountTextField.setText(BtcFormatter.formatSatoshis(requestedAmount));
|
||||
amountTextField.setPromptText(BtcFormatter.formatSatoshis(offer.getMinAmount()) + " - " + BtcFormatter.formatSatoshis(offer.getAmount()));
|
||||
priceTextField.setText(BitSquareFormatter.formatPrice(offer.getPrice()));
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
applyTotal();
|
||||
feeTextField.setText(BtcFormatter.formatSatoshis(getFee()));
|
||||
totalTextField.setText(getFormattedTotal());
|
||||
|
||||
bankAccountTypeTextField.setText(offer.getBankAccountType().toString());
|
||||
countryTextField.setText(offer.getBankAccountCountry().getName());
|
||||
|
||||
//todo list
|
||||
// arbitratorsTextField.setText(offer.getArbitrator().getName());
|
||||
|
||||
supportedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(offer.getAcceptedLanguageLocales()));
|
||||
supportedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(offer.getAcceptedCountries()));
|
||||
|
||||
amountTextField.textProperty().addListener(e -> {
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
applyTotal();
|
||||
feeTextField.setText(getFee().getFormattedValue());
|
||||
totalTextField.setText(getFormattedTotal());
|
||||
|
||||
bankAccountTypeTextField.setText(offer.getBankAccountType().toString());
|
||||
countryTextField.setText(offer.getBankAccountCountry().getName());
|
||||
|
||||
//todo list
|
||||
// arbitratorsTextField.setText(offer.getArbitrator().getName());
|
||||
|
||||
supportedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(offer.getAcceptedLanguageLocales()));
|
||||
supportedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(offer.getAcceptedCountries()));
|
||||
|
||||
amountTextField.textProperty().addListener(e -> {
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
applyTotal();
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -145,19 +140,103 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GUI handlers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@FXML
|
||||
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 void applyCollateral()
|
||||
{
|
||||
collateralTextField.setText(getFormattedCollateral());
|
||||
@ -181,18 +260,23 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
|
||||
private String getFormattedTotal()
|
||||
{
|
||||
return BitSquareFormatter.formatVolume(getTotal());
|
||||
return BitSquareFormatter.formatVolume(getTotal().doubleValue());
|
||||
}
|
||||
|
||||
private String getFormattedCollateral()
|
||||
{
|
||||
return BtcFormatter.satoshiToString(getCollateralInSatoshis());
|
||||
return BtcFormatter.formatSatoshis(getCollateralInSatoshis());
|
||||
}
|
||||
|
||||
// values
|
||||
private double getAmountAsDouble()
|
||||
{
|
||||
return BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
return BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
}
|
||||
|
||||
private BigInteger getAmountInSatoshis()
|
||||
{
|
||||
return BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||
}
|
||||
|
||||
private double getVolume()
|
||||
@ -200,22 +284,32 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
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()
|
||||
{
|
||||
double amount = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
double amount = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
||||
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.FormBuilder;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import io.bitsquare.trade.Direction;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
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 java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
@ -149,21 +146,21 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
row = -1;
|
||||
|
||||
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 -> {
|
||||
applyVolume();
|
||||
applyCollateral();
|
||||
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);
|
||||
|
||||
FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", BitSquareFormatter.formatPrice(offer.getPrice()), ++row);
|
||||
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
|
||||
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
|
||||
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);
|
||||
|
||||
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
|
||||
@ -228,48 +225,48 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
return;
|
||||
}
|
||||
|
||||
if (trading.isOfferTradable(offer))
|
||||
{
|
||||
trade = trading.createTrade(offer);
|
||||
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||
//if (trading.isOfferAlreadyInTrades(offer))
|
||||
// {
|
||||
trade = trading.createTrade(offer);
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountID()))
|
||||
if (blockChainFacade.isAccountIDBlacklisted(offer.getAccountId()))
|
||||
{
|
||||
Popups.openErrorPopup("Offerers account ID is blacklisted", "Offerers account ID is blacklisted.");
|
||||
return;
|
||||
} */
|
||||
|
||||
amountTextField.setEditable(false);
|
||||
amountTextField.setEditable(false);
|
||||
|
||||
gridPane.getChildren().clear();
|
||||
gridPane.getChildren().clear();
|
||||
|
||||
row = -1;
|
||||
FormBuilder.addHeaderLabel(gridPane, "Trade request inited", ++row, 0);
|
||||
row = -1;
|
||||
FormBuilder.addHeaderLabel(gridPane, "Trade request inited", ++row, 0);
|
||||
|
||||
Label statusTextField = FormBuilder.addLabel(gridPane, "Current activity:", "Request confirmation from offerer to take that offer.", ++row);
|
||||
GridPane.setColumnSpan(statusTextField, 2);
|
||||
FormBuilder.addLabel(gridPane, "Progress:", "", ++row);
|
||||
progressBar = new ProgressBar();
|
||||
progressBar.setProgress(0.0);
|
||||
progressBar.setPrefWidth(300);
|
||||
GridPane.setFillWidth(progressBar, true);
|
||||
gridPane.add(progressBar, 1, row);
|
||||
Label statusTextField = FormBuilder.addLabel(gridPane, "Current activity:", "Request confirmation from offerer to take that offer.", ++row);
|
||||
GridPane.setColumnSpan(statusTextField, 2);
|
||||
FormBuilder.addLabel(gridPane, "Progress:", "", ++row);
|
||||
progressBar = new ProgressBar();
|
||||
progressBar.setProgress(0.0);
|
||||
progressBar.setPrefWidth(300);
|
||||
GridPane.setFillWidth(progressBar, true);
|
||||
gridPane.add(progressBar, 1, row);
|
||||
|
||||
FormBuilder.addLabel(gridPane, "Status:", "", ++row);
|
||||
ConfidenceProgressIndicator progressIndicator = new ConfidenceProgressIndicator();
|
||||
progressIndicator.setPrefSize(20, 20);
|
||||
progressIndicator.setLayoutY(2);
|
||||
Pane progressIndicatorHolder = new Pane();
|
||||
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
||||
gridPane.add(progressIndicatorHolder, 1, row);
|
||||
FormBuilder.addLabel(gridPane, "Status:", "", ++row);
|
||||
ConfidenceProgressIndicator progressIndicator = new ConfidenceProgressIndicator();
|
||||
progressIndicator.setPrefSize(20, 20);
|
||||
progressIndicator.setLayoutY(2);
|
||||
Pane progressIndicatorHolder = new Pane();
|
||||
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
||||
gridPane.add(progressIndicatorHolder, 1, row);
|
||||
|
||||
TakerPaymentProtocol takerPaymentProtocol = trading.addTakerPaymentProtocol(trade, new TakerPaymentProtocolListener()
|
||||
/*TakerPaymentProtocol takerPaymentProtocol = trading.addTakerPaymentProtocol(trade, new TakerPaymentProtocolListener()
|
||||
{
|
||||
@Override
|
||||
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.");
|
||||
break;
|
||||
} */
|
||||
/*
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -306,13 +304,13 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxID)
|
||||
public void onDepositTxPublishedMessage(String depositTxID)
|
||||
{
|
||||
buildDepositPublishedScreen(depositTxID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBankTransferInited(TradeMessage tradeMessage)
|
||||
public void onBankTransferInitedMessage(TradeMessage tradeMessage)
|
||||
{
|
||||
buildBankTransferInitedScreen(tradeMessage);
|
||||
}
|
||||
@ -324,9 +322,9 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
}
|
||||
});
|
||||
|
||||
takerPaymentProtocol.takeOffer();
|
||||
}
|
||||
takerPaymentProtocol.takeOffer(); */
|
||||
}
|
||||
//}
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
private void updateTx(Trade trade)
|
||||
@ -347,7 +345,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
// confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, transaction, progressIndicator);
|
||||
}
|
||||
|
||||
private void buildBankTransferInitedScreen(TradeMessage tradeMessage)
|
||||
private void buildBankTransferInitedScreen()
|
||||
{
|
||||
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.");
|
||||
gridPane.add(nextButton, 1, ++row);
|
||||
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();
|
||||
trading.releaseBTC(trade.getId(), tradeMessage);
|
||||
trading.releaseBTC(trade.getId());
|
||||
|
||||
nextButton.setText("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()));
|
||||
|
||||
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())
|
||||
{
|
||||
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, "Refunded collateral:", BtcFormatter.satoshiToString(trade.getCollateralAmount()), ++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.formatSatoshis(trade.getCollateralAmount()), ++row);
|
||||
}
|
||||
else
|
||||
{
|
||||
//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 (BTC):", BtcFormatter.satoshiToString(offer.getAmount()), ++row);
|
||||
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount()), ++row);
|
||||
}
|
||||
|
||||
gridPane.add(nextButton, 1, ++row);
|
||||
@ -440,18 +438,18 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
|
||||
private double getVolume()
|
||||
{
|
||||
return offer.getPrice() * BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
return offer.getPrice() * BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
}
|
||||
|
||||
private String getTotalToPayAsString()
|
||||
{
|
||||
if (takerIsSelling())
|
||||
{
|
||||
return BtcFormatter.satoshiToString(getTotalToPay());
|
||||
return BtcFormatter.formatSatoshis(getTotalToPay());
|
||||
}
|
||||
else
|
||||
{
|
||||
return BtcFormatter.satoshiToString(getTotalToPay()) + "\n" +
|
||||
return BtcFormatter.formatSatoshis(getTotalToPay()) + "\n" +
|
||||
BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency());
|
||||
}
|
||||
}
|
||||
@ -460,22 +458,22 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
{
|
||||
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
|
||||
{
|
||||
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()
|
||||
{
|
||||
collateralTextField.setText(BtcFormatter.satoshiToString(getCollateralInSatoshis()));
|
||||
collateralTextField.setText(BtcFormatter.formatSatoshis(getCollateralInSatoshis()));
|
||||
}
|
||||
|
||||
private BigInteger getCollateralInSatoshis()
|
||||
{
|
||||
double amount = BitSquareConverter.stringToDouble2(amountTextField.getText());
|
||||
double amount = BitSquareConverter.stringToDouble(amountTextField.getText());
|
||||
double resultDouble = amount * (double) offer.getCollateral() / 100.0;
|
||||
return BtcFormatter.doubleValueToSatoshis(resultDouble);
|
||||
}
|
||||
|
@ -16,20 +16,38 @@ import org.slf4j.LoggerFactory;
|
||||
public class OrdersController implements Initializable, ChildController, NavigationController
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(OrdersController.class);
|
||||
private static int SELECTED_TAB_INDEX = -1;
|
||||
private static OrdersController INSTANCE;
|
||||
private final Storage storage;
|
||||
|
||||
@FXML
|
||||
private LazyLoadingTabPane tabPane;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private OrdersController(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
|
||||
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());
|
||||
}
|
||||
|
||||
@ -59,6 +78,7 @@ public class OrdersController implements Initializable, ChildController, Navigat
|
||||
tabPane.cleanup();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interface implementation: NavigationController
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -68,7 +68,6 @@ public class OfferController implements Initializable, ChildController, Hibernat
|
||||
@Override
|
||||
public void setNavigationController(NavigationController navigationController)
|
||||
{
|
||||
log.debug("setNavigationController" + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,6 @@ import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.geometry.Pos;
|
||||
@ -165,20 +164,15 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||
|
||||
initCopyIcons();
|
||||
|
||||
if (tradeItems.size() > 0)
|
||||
{
|
||||
openTradesTable.getSelectionModel().select(0);
|
||||
}
|
||||
// select
|
||||
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getCurrentPendingTrade().getId())).findFirst();
|
||||
if (currentTradeItemOptional.isPresent())
|
||||
openTradesTable.getSelectionModel().select(currentTradeItemOptional.get());
|
||||
|
||||
tradeItems.addListener(new ListChangeListener<PendingTradesListItem>()
|
||||
{
|
||||
@Override
|
||||
public void onChanged(Change<? extends PendingTradesListItem> change)
|
||||
tradeItems.addListener((ListChangeListener<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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void bankTransferInited(ActionEvent actionEvent)
|
||||
public void bankTransferInited()
|
||||
{
|
||||
trading.onBankTransferInited(currentTrade.getId());
|
||||
trading.onUIEventBankTransferInited(currentTrade.getId());
|
||||
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()));
|
||||
|
||||
bankAccountTypeTextField.setText(BtcFormatter.satoshiToString(trade.getTradeAmount()));
|
||||
bankAccountTypeTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount()));
|
||||
holderNameTextField.setText(fiatPayed);
|
||||
primaryBankAccountIDTextField.setText(BtcFormatter.satoshiToString(FeePolicy.CREATE_OFFER_FEE_depr.add(FeePolicy.TX_FEE_depr)));
|
||||
secondaryBankAccountIDTextField.setText(BtcFormatter.satoshiToString(trade.getCollateralAmount()));
|
||||
primaryBankAccountIDTextField.setText(BtcFormatter.formatSatoshis(FeePolicy.CREATE_OFFER_FEE.add(FeePolicy.TX_FEE)));
|
||||
secondaryBankAccountIDTextField.setText(BtcFormatter.formatSatoshis(trade.getCollateralAmount()));
|
||||
|
||||
holderNameCopyIcon.setVisible(false);
|
||||
primaryBankAccountIDCopyIcon.setVisible(false);
|
||||
|
@ -15,21 +15,11 @@ public class BitSquareConverter
|
||||
{
|
||||
try
|
||||
{
|
||||
return stringToDouble2(input);
|
||||
input = input.replace(",", ".");
|
||||
return Double.parseDouble(input);
|
||||
} catch (NumberFormatException | NullPointerException e)
|
||||
{
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(",", ".");
|
||||
return Double.parseDouble(input);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package io.bitsquare.gui.util;
|
||||
|
||||
import io.bitsquare.bank.BankAccountType;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import java.math.BigInteger;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.effect.BlurType;
|
||||
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 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
|
||||
{
|
||||
resetTextFields(textFields);
|
||||
|
@ -187,7 +187,7 @@ public class ConfidenceDisplay
|
||||
}
|
||||
|
||||
if (balanceTextField != null)
|
||||
balanceTextField.setText(BtcFormatter.satoshiToString(balance));
|
||||
balanceTextField.setText(BtcFormatter.formatSatoshis(balance));
|
||||
}
|
||||
|
||||
private void updateConfidence(Transaction tx)
|
||||
|
@ -4,8 +4,14 @@ import com.google.inject.Inject;
|
||||
import io.bitsquare.BitSquare;
|
||||
import io.bitsquare.msg.listeners.*;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
|
||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||
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.util.DSAKeyUtil;
|
||||
import io.bitsquare.util.FileUtil;
|
||||
@ -46,9 +52,10 @@ public class MessageFacade
|
||||
private final List<OrderBookListener> orderBookListeners = new ArrayList<>();
|
||||
private final List<TakeOfferRequestListener> takeOfferRequestListeners = 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 List<OffererPaymentProtocol> offererPaymentProtocols = new ArrayList<>();
|
||||
|
||||
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocols = new HashMap<>();
|
||||
|
||||
private final List<PingPeerListener> pingPeerListeners = new ArrayList<>();
|
||||
private final BooleanProperty isDirty = new SimpleBooleanProperty(false);
|
||||
private Peer myPeer;
|
||||
@ -66,7 +73,7 @@ public class MessageFacade
|
||||
{
|
||||
/* try
|
||||
{
|
||||
masterPeer = BootstrapMasterPeer.INSTANCE(MASTER_PEER_PORT);
|
||||
masterPeer = BootstrapMasterPeer.GET_INSTANCE(MASTER_PEER_PORT);
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (masterPeer != null)
|
||||
@ -97,7 +104,7 @@ public class MessageFacade
|
||||
} catch (IOException e)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// TODO don't get updates at first run....
|
||||
// TODO don't get updates at first execute....
|
||||
if (lastTimeStamp != timeStamp)
|
||||
{
|
||||
isDirty.setValue(!isDirty.get());
|
||||
@ -423,7 +430,8 @@ public class MessageFacade
|
||||
// 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 FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
||||
@ -435,32 +443,44 @@ public class MessageFacade
|
||||
if (baseFuture.isSuccess() && getPeerAddressFuture.getData() != null)
|
||||
{
|
||||
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
||||
Platform.runLater(() -> onAddressFound(peerAddress, listener));
|
||||
Platform.runLater(() -> listener.onResult(peerAddress));
|
||||
}
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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 FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||
@ -499,51 +519,47 @@ public class MessageFacade
|
||||
|
||||
private void processTradingMessage(TradeMessage tradeMessage, PeerAddress sender)
|
||||
{
|
||||
//TODO change to map (key: offerID) instead of list (offererPaymentProtocols, takerPaymentProtocols)
|
||||
log.info("processTradingMessage " + tradeMessage.getType());
|
||||
switch (tradeMessage.getType())
|
||||
{
|
||||
case REQUEST_TAKE_OFFER:
|
||||
// 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;
|
||||
// log.trace("processTradingMessage TradeId " + tradeMessage.getTradeId());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getSimpleName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getCanonicalName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getTypeName());
|
||||
|
||||
default:
|
||||
log.info("default");
|
||||
break;
|
||||
if (tradeMessage instanceof RequestTakeOfferMessage)
|
||||
{
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public PublicKey getPubKey()
|
||||
{
|
||||
return keyPair.getPublic();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Event Listeners
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -646,24 +662,24 @@ public class MessageFacade
|
||||
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)
|
||||
@ -781,5 +797,4 @@ public class MessageFacade
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,277 +1,6 @@
|
||||
package io.bitsquare.msg;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigInteger;
|
||||
import java.util.UUID;
|
||||
|
||||
//TODO refactor
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public class TradeMessage implements Serializable
|
||||
public interface TradeMessage
|
||||
{
|
||||
private static final long serialVersionUID = 7916445031849763995L;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
public String getTradeId();
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
||||
public interface TakeOfferRequestListener
|
||||
{
|
||||
void onTakeOfferRequested(TradeMessage tradeMessage, PeerAddress sender);
|
||||
void onTakeOfferRequested(String offerId, PeerAddress sender);
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ public class Storage
|
||||
|
||||
@GuardedBy("lock")
|
||||
private Map<String, Serializable> rootMap = new HashMap<>();
|
||||
private boolean dirty;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -120,7 +119,6 @@ public class Storage
|
||||
try
|
||||
{
|
||||
lock.lock();
|
||||
dirty = true;
|
||||
rootMap.put(key, value);
|
||||
saveObjectToFile((Serializable) rootMap);
|
||||
} finally
|
||||
@ -141,21 +139,12 @@ public class Storage
|
||||
return read(classInstance.getClass().getName() + "." + propertyKey);
|
||||
}
|
||||
|
||||
|
||||
// read from local rootMap, just if not found read from disc
|
||||
public Serializable read(String key)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock.lock();
|
||||
if (dirty)
|
||||
{
|
||||
final Map<String, Serializable> map = readRootMap();
|
||||
if (map != null)
|
||||
{
|
||||
rootMap = map;
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
if (rootMap.containsKey(key))
|
||||
{
|
||||
// log.trace("Read object with key = " + key + " / value = " + rootMap.get(key));
|
||||
@ -163,8 +152,21 @@ public class Storage
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("Object with key = " + key + " not found.");
|
||||
return null;
|
||||
final Map<String, Serializable> map = readRootMap();
|
||||
if (map != null)
|
||||
{
|
||||
rootMap = map;
|
||||
}
|
||||
if (rootMap.containsKey(key))
|
||||
{
|
||||
// log.trace("Read object with key = " + key + " / value = " + rootMap.get(key));
|
||||
return rootMap.get(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Object with key = " + key + " not found.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} finally
|
||||
{
|
||||
@ -205,7 +207,7 @@ public class Storage
|
||||
} 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;
|
||||
} catch (ClassNotFoundException | IOException e2)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ public class Trade implements Serializable
|
||||
private Transaction depositTransaction;
|
||||
private Transaction payoutTransaction;
|
||||
|
||||
private State state = State.NONE;
|
||||
private State state = State.OPEN;
|
||||
|
||||
public Trade(Offer offer)
|
||||
{
|
||||
@ -39,21 +39,6 @@ public class Trade implements Serializable
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return offer.getId();
|
||||
}
|
||||
|
||||
public Offer getOffer()
|
||||
{
|
||||
return offer;
|
||||
}
|
||||
|
||||
public String getTakeOfferFeeTxID()
|
||||
{
|
||||
return takeOfferFeeTxID;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTxID(String takeOfferFeeTxID)
|
||||
{
|
||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||
@ -80,16 +65,31 @@ public class Trade implements Serializable
|
||||
contractChangedProperty.set(!contractChangedProperty.get());
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return offer.getId();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
public Offer getOffer()
|
||||
{
|
||||
return offer;
|
||||
}
|
||||
|
||||
public String getTakeOfferFeeTxId()
|
||||
{
|
||||
return takeOfferFeeTxID;
|
||||
}
|
||||
|
||||
public String getContractAsJson()
|
||||
{
|
||||
return contractAsJson;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setContractAsJson(String contractAsJson)
|
||||
{
|
||||
this.contractAsJson = contractAsJson;
|
||||
@ -122,7 +122,6 @@ public class Trade implements Serializable
|
||||
payoutTxChangedProperty.set(!payoutTxChangedProperty.get());
|
||||
}
|
||||
|
||||
|
||||
public State getState()
|
||||
{
|
||||
return state;
|
||||
@ -134,7 +133,6 @@ public class Trade implements Serializable
|
||||
stateChangedProperty.set(state.toString());
|
||||
}
|
||||
|
||||
|
||||
public SimpleBooleanProperty getDepositTxChangedProperty()
|
||||
{
|
||||
return depositTxChangedProperty;
|
||||
@ -186,7 +184,7 @@ public class Trade implements Serializable
|
||||
|
||||
public static enum State
|
||||
{
|
||||
NONE,
|
||||
OPEN,
|
||||
ACCEPTED,
|
||||
COMPLETED
|
||||
}
|
||||
|
@ -7,16 +7,18 @@ import com.google.inject.Inject;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.gui.popups.Popups;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
|
||||
import io.bitsquare.trade.payment.offerer.OffererPaymentProtocolListener;
|
||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
|
||||
import io.bitsquare.trade.payment.taker.TakerPaymentProtocolListener;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocolListener;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||
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.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@ -32,8 +34,8 @@ import org.slf4j.LoggerFactory;
|
||||
public class Trading
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
||||
private final Map<String, TakerPaymentProtocol> takerPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, OffererPaymentProtocol> offererPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, OffererAsBuyerProtocol> offererPaymentProtocols = new HashMap<>();
|
||||
private final String storageKey;
|
||||
private final User user;
|
||||
|
||||
@ -44,9 +46,10 @@ public class Trading
|
||||
private final CryptoFacade cryptoFacade;
|
||||
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 Trade currentPendingTrade;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -73,15 +76,15 @@ public class Trading
|
||||
|
||||
Object offersObject = storage.read(storageKey + ".offers");
|
||||
if (offersObject instanceof HashMap)
|
||||
myOffers = (Map<String, Offer>) offersObject;
|
||||
offers = (Map<String, Offer>) offersObject;
|
||||
|
||||
Object tradesObject = storage.read(storageKey + ".trades");
|
||||
if (tradesObject instanceof HashMap)
|
||||
trades = (Map<String, Trade>) tradesObject;
|
||||
|
||||
messageFacade.addTakeOfferRequestListener((offerId, sender) -> createOffererAsBuyerProtocol(offerId, sender));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -92,15 +95,15 @@ public class Trading
|
||||
|
||||
private void saveOffers()
|
||||
{
|
||||
storage.write(storageKey + ".offers", myOffers);
|
||||
storage.write(storageKey + ".offers", offers);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
myOffers.put(offer.getId(), offer);
|
||||
offers.put(offer.getId(), offer);
|
||||
saveOffers();
|
||||
|
||||
messageFacade.addOffer(offer);
|
||||
@ -108,17 +111,12 @@ public class Trading
|
||||
|
||||
public void removeOffer(Offer offer) throws IOException
|
||||
{
|
||||
myOffers.remove(offer.getId());
|
||||
offers.remove(offer.getId());
|
||||
saveOffers();
|
||||
|
||||
messageFacade.removeOffer(offer);
|
||||
}
|
||||
|
||||
public boolean isOfferTradable(Offer offer)
|
||||
{
|
||||
return !trades.containsKey(offer.getId());
|
||||
}
|
||||
|
||||
|
||||
public Trade createTrade(Offer offer)
|
||||
{
|
||||
@ -144,85 +142,88 @@ public class Trading
|
||||
return this.newTradeProperty;
|
||||
}
|
||||
|
||||
|
||||
public TakerPaymentProtocol addTakerPaymentProtocol(Trade trade, TakerPaymentProtocolListener listener)
|
||||
public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener, WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
TakerPaymentProtocol takerPaymentProtocol = new TakerPaymentProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
Trade trade = createTrade(offer);
|
||||
trade.setTradeAmount(amount);
|
||||
|
||||
TakerAsSellerProtocol takerPaymentProtocol = new TakerAsSellerProtocol(trade, listener, resultHandler, faultHandler, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
takerPaymentProtocols.put(trade.getId(), takerPaymentProtocol);
|
||||
return takerPaymentProtocol;
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
|
||||
OffererPaymentProtocol addOffererPaymentProtocol(Trade trade, OffererPaymentProtocolListener listener)
|
||||
public void createOffererAsBuyerProtocol(String offerId, PeerAddress sender)
|
||||
{
|
||||
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))
|
||||
log.trace("createOffererAsBuyerProtocol offerId = " + offerId);
|
||||
Offer offer = offers.get(offerId);
|
||||
if (offer != null && offers.containsKey(offer.getId()))
|
||||
{
|
||||
Trade trade = createTrade(offer);
|
||||
OffererPaymentProtocol offererPaymentProtocol = addOffererPaymentProtocol(trade, new OffererPaymentProtocolListener()
|
||||
offers.remove(offer);
|
||||
|
||||
currentPendingTrade = createTrade(offer);
|
||||
OffererAsBuyerProtocolListener listener = new OffererAsBuyerProtocolListener()
|
||||
{
|
||||
@Override
|
||||
public void onProgress(double progress)
|
||||
{
|
||||
//log.debug("onProgress " + progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String failureMessage)
|
||||
{
|
||||
log.warn(failureMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxID)
|
||||
{
|
||||
log.debug("trading onDepositTxPublished " + depositTxID);
|
||||
log.trace("trading onDepositTxPublishedMessage " + depositTxID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDepositTxConfirmedUpdate(TransactionConfidence confidence)
|
||||
{
|
||||
log.debug("trading onDepositTxConfirmedUpdate");
|
||||
log.trace("trading onDepositTxConfirmedUpdate");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPayoutTxPublished(String payoutTxAsHex)
|
||||
{
|
||||
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
|
||||
trade.setPayoutTransaction(payoutTx);
|
||||
trade.setState(Trade.State.COMPLETED);
|
||||
log.debug("trading onPayoutTxPublished");
|
||||
currentPendingTrade.setPayoutTransaction(payoutTx);
|
||||
currentPendingTrade.setState(Trade.State.COMPLETED);
|
||||
log.debug("trading onPayoutTxPublishedMessage");
|
||||
}
|
||||
|
||||
@Override
|
||||
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)
|
||||
// will probably created earlier, so let it for the moment like that....
|
||||
offererPaymentProtocol.onTakeOfferRequested(sender);
|
||||
WorkerResultHandler resultHandler = new WorkerResultHandler()
|
||||
{
|
||||
@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
|
||||
{
|
||||
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
|
||||
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()
|
||||
{
|
||||
return myOffers;
|
||||
return offers;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
import com.google.bitcoin.core.*;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
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.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.util.Utilities;
|
||||
import java.math.BigInteger;
|
||||
import javafx.util.Pair;
|
||||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
//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 Offer offer;
|
||||
private final OffererPaymentProtocolListener offererPaymentProtocolListener;
|
||||
|
||||
private final OffererAsBuyerProtocolListener listener;
|
||||
private final WorkerResultHandler resultHandler;
|
||||
private final WorkerFaultHandler faultHandler;
|
||||
private final MessageFacade messageFacade;
|
||||
|
||||
private final WalletFacade walletFacade;
|
||||
|
||||
private final BlockChainFacade blockChainFacade;
|
||||
|
||||
private final CryptoFacade cryptoFacade;
|
||||
|
||||
private final User user;
|
||||
private PeerAddress peerAddress;
|
||||
private boolean isTakeOfferRequested;
|
||||
private int currentStep = 0;
|
||||
// private
|
||||
private final SequenceScheduler scheduler_1;
|
||||
// data written/read by tasks
|
||||
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 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public OffererPaymentProtocol(Trade trade,
|
||||
OffererPaymentProtocolListener offererPaymentProtocolListener,
|
||||
public OffererAsBuyerProtocol(Trade trade,
|
||||
PeerAddress peerAddress,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
BlockChainFacade blockChainFacade,
|
||||
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.offererPaymentProtocolListener = offererPaymentProtocolListener;
|
||||
this.peerAddress = peerAddress;
|
||||
this.listener = listener;
|
||||
this.resultHandler = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
this.messageFacade = messageFacade;
|
||||
this.walletFacade = walletFacade;
|
||||
this.blockChainFacade = blockChainFacade;
|
||||
this.cryptoFacade = cryptoFacade;
|
||||
this.user = user;
|
||||
|
||||
offer = trade.getOffer();
|
||||
id = trade.getId();
|
||||
|
||||
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.
|
||||
// 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");
|
||||
|
||||
@ -108,7 +340,7 @@ public class OffererPaymentProtocol
|
||||
if (isTakeOfferRequested)
|
||||
{
|
||||
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()
|
||||
{
|
||||
@Override
|
||||
@ -140,7 +372,7 @@ public class OffererPaymentProtocol
|
||||
log.debug("1.3 onTakeOfferRequested ACCEPT_TAKE_OFFER_REQUEST onResult");
|
||||
// The accept message has arrived at the peer
|
||||
// We set requested flag and remove the offer from the orderbook
|
||||
offererPaymentProtocolListener.onProgress(getProgress());
|
||||
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
isTakeOfferRequested = true;
|
||||
log.debug("1.3 messageFacade.removeOffer");
|
||||
@ -153,18 +385,18 @@ public class OffererPaymentProtocol
|
||||
public void 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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//************************************************************************************************
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onTakeOfferFeePayed(TradeMessage requestTradeMessage)
|
||||
/* public void onTakeOfferFeePayedMessage(SendProofOfTakerOfferFeePaymentMessage requestTradeMessage)
|
||||
{
|
||||
log.debug("2.3 onTakeOfferFeePayed");
|
||||
trade.setTakeOfferFeeTxID(requestTradeMessage.getTakeOfferFeeTxID());
|
||||
log.debug("2.3 onTakeOfferFeePayedMessage");
|
||||
trade.setTakeOfferFeeTxID(requestTradeMessage.getTakeOfferFeeTxId());
|
||||
trade.setTradeAmount(requestTradeMessage.getTradeAmount());
|
||||
verifyTakeOfferFeePayment(requestTradeMessage);
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 2.4
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void verifyTakeOfferFeePayment(TradeMessage requestTradeMessage)
|
||||
/* private void verifyTakeOfferFeePayment(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
log.debug("2.4 verifyTakeOfferFeePayment");
|
||||
//TODO just dummy now, will be async
|
||||
int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(requestTradeMessage.getTakeOfferFeeTxID());
|
||||
int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(requestTradeMessage.getTakeOfferFeeTxId());
|
||||
if (numOfPeersSeenTx > 2)
|
||||
{
|
||||
createDepositTx(requestTradeMessage);
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 2.5
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void createDepositTx(TradeMessage requestTradeMessage)
|
||||
/* private void createDepositTx(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
checkNotNull(requestTradeMessage);
|
||||
|
||||
@ -222,7 +453,7 @@ public class OffererPaymentProtocol
|
||||
checkNotNull(arbitratorPubKey);
|
||||
|
||||
log.debug("2.5 offererCreatesMSTxAndAddPayment");
|
||||
log.debug("offererInputAmount " + BtcFormatter.satoshiToString(offererInputAmount));
|
||||
log.debug("offererInputAmount " + BtcFormatter.formatSatoshis(offererInputAmount));
|
||||
log.debug("offerer pubkey " + offererPubKey);
|
||||
log.debug("taker pubkey " + takerPubKey);
|
||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||
@ -242,13 +473,13 @@ public class OffererPaymentProtocol
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
// Send all the requested data
|
||||
@ -260,7 +491,7 @@ public class OffererPaymentProtocol
|
||||
{
|
||||
log.debug("2.6 sendDepositTxAndDataForContract onResult");
|
||||
// Message arrived at taker
|
||||
offererPaymentProtocolListener.onProgress(getProgress());
|
||||
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
// We wait until we get the signed tx back
|
||||
}
|
||||
@ -269,19 +500,19 @@ public class OffererPaymentProtocol
|
||||
public void 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());
|
||||
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");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
} */
|
||||
|
||||
//************************************************************************************************
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onDepositTxReadyForPublication(TradeMessage requestTradeMessage)
|
||||
/* public void onRequestOffererPublishDepositTxMessage(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
log.debug("3.1 onDepositTxReadyForPublication");
|
||||
log.debug("3.1 onRequestOffererPublishDepositTxMessage");
|
||||
takerPayoutAddress = requestTradeMessage.getTakerPayoutAddress();
|
||||
verifyTaker(requestTradeMessage);
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.1 verifyAccountRegistration");
|
||||
if (blockChainFacade.verifyAccountRegistration())
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -322,20 +553,19 @@ public class OffererPaymentProtocol
|
||||
}
|
||||
else
|
||||
{
|
||||
offererPaymentProtocolListener.onFailure("Takers account registration is invalid.");
|
||||
// offererPaymentProtocolListener.onFailure("Takers account registration is invalid.");
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 3.3 Verify and sign the contract
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void verifyAndSignContract(TradeMessage requestTradeMessage)
|
||||
/* private void verifyAndSignContract(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
Contract contract = new Contract(offer,
|
||||
trade.getTradeAmount(),
|
||||
trade.getTakeOfferFeeTxID(),
|
||||
trade.getTakeOfferFeeTxId(),
|
||||
user.getAccountID(),
|
||||
requestTradeMessage.getAccountID(),
|
||||
user.getCurrentBankAccount(),
|
||||
@ -364,13 +594,13 @@ public class OffererPaymentProtocol
|
||||
{
|
||||
log.error("3.3 verifyContract failed");
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 3.4 Sign and publish the deposit tx
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void signAndPublishDepositTx(TradeMessage requestTradeMessage)
|
||||
/* private void signAndPublishDepositTx(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
log.debug("3.4 signAndPublishDepositTx");
|
||||
|
||||
@ -410,13 +640,13 @@ public class OffererPaymentProtocol
|
||||
e.getStackTrace();// Could not understand form of connected output script: RETURN
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
|
||||
@ -426,24 +656,24 @@ public class OffererPaymentProtocol
|
||||
public void onResult()
|
||||
{
|
||||
log.debug("3.5 sendDepositTxIdToTaker DEPOSIT_TX_PUBLISHED onResult");
|
||||
offererPaymentProtocolListener.onProgress(getProgress());
|
||||
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void 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");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
|
||||
// wait for at least 1 confirmation, then pay Fiat
|
||||
offererPaymentProtocolListener.onDepositTxPublished(tradeMessage.getDepositTxID());
|
||||
offererPaymentProtocolListener.onDepositTxPublishedMessage(tradeMessage.getDepositTxID());
|
||||
setupListenerForBlockChainConfirmation(transaction);
|
||||
}
|
||||
} */
|
||||
|
||||
//************************************************************************************************
|
||||
// 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");
|
||||
|
||||
@ -477,6 +707,7 @@ public class OffererPaymentProtocol
|
||||
onDepositTxConfirmedInBlockchain();
|
||||
transaction.getConfidenceForAddress().removeEventListener(this);
|
||||
} */
|
||||
/*
|
||||
|
||||
}
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void updateConfirmation(TransactionConfidence confidence)
|
||||
/* private void updateConfirmation(TransactionConfidence confidence)
|
||||
{
|
||||
log.debug("3.8 updateConfirmation " + confidence);
|
||||
offererPaymentProtocolListener.onDepositTxConfirmedUpdate(confidence);
|
||||
}
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||
}
|
||||
} */
|
||||
|
||||
//************************************************************************************************
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void bankTransferInited()
|
||||
/*
|
||||
public void onBankTransferInitedMessage()
|
||||
{
|
||||
log.debug("3.10 bankTransferInited");
|
||||
log.debug("3.10 onBankTransferInitedMessage");
|
||||
|
||||
TradeMessageListener listener = new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.debug("3.10 bankTransferInited BANK_TX_INITED onResult");
|
||||
offererPaymentProtocolListener.onProgress(getProgress());
|
||||
log.debug("3.10 onBankTransferInitedMessage BANK_TX_INITED onResult");
|
||||
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.warn("3.10 bankTransferInited BANK_TX_INITED onFailed");
|
||||
offererPaymentProtocolListener.onFailure("bankTransferInited BANK_TX_INITED");
|
||||
log.warn("3.10 onBankTransferInitedMessage BANK_TX_INITED onFailed");
|
||||
// offererPaymentProtocolListener.onFailure("onBankTransferInitedMessage BANK_TX_INITED");
|
||||
}
|
||||
};
|
||||
|
||||
@ -560,7 +791,7 @@ public class OffererPaymentProtocol
|
||||
String offererSignatureS = offererSignature.s.toString();
|
||||
String depositTxAsHex = result.getValue();
|
||||
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,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
@ -583,7 +814,7 @@ public class OffererPaymentProtocol
|
||||
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.
|
||||
@ -594,25 +825,23 @@ public class OffererPaymentProtocol
|
||||
// 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("3.14 TRADE COMPLETE!!!!!!!!!!!");
|
||||
|
||||
offererPaymentProtocolListener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
|
||||
}
|
||||
log.debug("onPayoutTxPublishedMessage");
|
||||
offererPaymentProtocolListener.onPayoutTxPublishedMessage(tradeMessage.getPayoutTxAsHex());
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Util
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private double getProgress()
|
||||
/* private double getProgress()
|
||||
{
|
||||
currentStep++;
|
||||
int numberOfSteps = 10;
|
||||
return (double) currentStep / (double) numberOfSteps;
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
}
|
@ -2,19 +2,12 @@ package io.bitsquare.trade.payment.offerer;
|
||||
|
||||
import com.google.bitcoin.core.TransactionConfidence;
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public interface OffererPaymentProtocolListener
|
||||
public interface OffererAsBuyerProtocolListener
|
||||
{
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
void onProgress(double progress);
|
||||
|
||||
void onFailure(String failureMessage);
|
||||
|
||||
void onDepositTxPublished(String depositTxID);
|
||||
|
||||
void onDepositTxConfirmedInBlockchain();
|
||||
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
void onDepositTxConfirmedUpdate(TransactionConfidence confidence);
|
||||
|
||||
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,91 +1,350 @@
|
||||
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.Utils;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.BtcFormatter;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
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.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.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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
//TODO use states
|
||||
@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 Offer offer;
|
||||
private final TakerPaymentProtocolListener takerPaymentProtocolListener;
|
||||
|
||||
private final TakerAsSellerProtocolListener listener;
|
||||
private final WorkerResultHandler resultHandler;
|
||||
private final WorkerFaultHandler faultHandler;
|
||||
private final MessageFacade messageFacade;
|
||||
private final WalletFacade walletFacade;
|
||||
private final BlockChainFacade blockChainFacade;
|
||||
private final CryptoFacade cryptoFacade;
|
||||
private final User user;
|
||||
// private
|
||||
private final SequenceScheduler scheduler_1;
|
||||
// written/read by task
|
||||
private String payoutTxAsHex;
|
||||
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 SequenceScheduler scheduler_2;
|
||||
private SequenceScheduler scheduler_3;
|
||||
private SequenceScheduler scheduler_4;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public TakerPaymentProtocol(Trade trade,
|
||||
TakerPaymentProtocolListener takerPaymentProtocolListener,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
BlockChainFacade blockChainFacade,
|
||||
CryptoFacade cryptoFacade,
|
||||
User user)
|
||||
public TakerAsSellerProtocol(Trade trade,
|
||||
TakerAsSellerProtocolListener listener,
|
||||
WorkerResultHandler resultHandler,
|
||||
WorkerFaultHandler faultHandler,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
BlockChainFacade blockChainFacade,
|
||||
CryptoFacade cryptoFacade,
|
||||
User user)
|
||||
{
|
||||
this.trade = trade;
|
||||
this.takerPaymentProtocolListener = takerPaymentProtocolListener;
|
||||
this.listener = listener;
|
||||
this.resultHandler = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
this.messageFacade = messageFacade;
|
||||
this.walletFacade = walletFacade;
|
||||
this.blockChainFacade = blockChainFacade;
|
||||
this.cryptoFacade = cryptoFacade;
|
||||
this.user = user;
|
||||
|
||||
offer = trade.getOffer();
|
||||
id = trade.getId();
|
||||
|
||||
log.debug("TakerAsSellerProtocol created");
|
||||
|
||||
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");
|
||||
findPeerAddress();
|
||||
|
||||
|
||||
log.debug("onAcceptTakeOfferRequestMessage");
|
||||
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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void findPeerAddress()
|
||||
|
||||
/* private void findPeerAddress()
|
||||
{
|
||||
log.debug("1.1 findPeerAddress");
|
||||
AddressLookupListener addressLookupListener = new AddressLookupListener()
|
||||
@ -115,14 +374,13 @@ public class TakerPaymentProtocol
|
||||
|
||||
// Request the peers address from the DHT
|
||||
messageFacade.getPeerAddress(offer.getMessagePubKeyAsHex(), addressLookupListener);
|
||||
}
|
||||
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 1.2
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void requestTakeOffer()
|
||||
/* private void requestTakeOffer()
|
||||
{
|
||||
log.debug("1.2 requestTakeOffer");
|
||||
TradeMessageListener listener = new TradeMessageListener()
|
||||
@ -153,7 +411,7 @@ public class TakerPaymentProtocol
|
||||
// Send the take offer request
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.REQUEST_TAKE_OFFER, trade.getId());
|
||||
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.
|
||||
public void onTakeOfferRequestAccepted()
|
||||
/* public void onAcceptTakeOfferRequestMessage()
|
||||
{
|
||||
log.debug("1.4a onTakeOfferRequestAccepted");
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
log.debug("1.4a onAcceptTakeOfferRequestMessage");
|
||||
// listener.onProgress(getProgress());
|
||||
|
||||
payOfferFee(trade);
|
||||
}
|
||||
|
||||
// 1.4b Offerer has rejected the take offer request. The UI controller will handle the case.
|
||||
public void onTakeOfferRequestRejected()
|
||||
// 1.4b Offerer has rejected the take offer request. The UI controller will onResult the case.
|
||||
public void onRejectTakeOfferRequestMessage()
|
||||
{
|
||||
log.debug("1.4b onTakeOfferRequestRejected");
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
}
|
||||
log.debug("1.4b onRejectTakeOfferRequestMessage");
|
||||
// listener.onProgress(getProgress());
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 2.1
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void payOfferFee(Trade trade)
|
||||
/* private void payOfferFee(Trade trade)
|
||||
{
|
||||
log.debug("2.1 payTakeOfferFee");
|
||||
FutureCallback<Transaction> callback = new FutureCallback<Transaction>()
|
||||
@ -201,7 +459,7 @@ public class TakerPaymentProtocol
|
||||
// Offer fee payed successfully.
|
||||
trade.setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
// listener.onProgress(getProgress());
|
||||
|
||||
// move on
|
||||
sendTakerOfferFeeTxID(transaction.getHashAsString());
|
||||
@ -211,19 +469,19 @@ public class TakerPaymentProtocol
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.debug("2.1 payTakeOfferFee onFailure");
|
||||
takerPaymentProtocolListener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
||||
// listener.onFailure("payTakeOfferFee onFailure " + t.getMessage());
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
// Pay the offer fee
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
// listener.onProgress(getProgress());
|
||||
walletFacade.payTakeOfferFee(trade.getId(), callback);
|
||||
} 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
|
||||
// The offerer will wait until a minimum of peers seen the tx before sending his data.
|
||||
// We also get the multisig tx delivered
|
||||
private void sendTakerOfferFeeTxID(String takeOfferFeeTxID)
|
||||
/* private void sendTakerOfferFeeTxID(String takeOfferFeeTxID)
|
||||
{
|
||||
log.debug("2.2 sendTakerOfferFeeTxID");
|
||||
TradeMessageListener listener = new TradeMessageListener()
|
||||
@ -245,7 +503,7 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.debug("2.2 sendTakerOfferFeeTxID onResult");
|
||||
// Message has arrived
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
//listener.onProgress(getProgress());
|
||||
|
||||
// We wait until the offerer send us the data
|
||||
}
|
||||
@ -254,21 +512,21 @@ public class TakerPaymentProtocol
|
||||
public void 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.
|
||||
TradeMessage tradeMessage = new TradeMessage(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
||||
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.TAKE_OFFER_FEE_PAYED,
|
||||
trade.getId(),
|
||||
trade.getTradeAmount(),
|
||||
takeOfferFeeTxID,
|
||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString());
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//************************************************************************************************
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onTakerDepositPaymentRequested(TradeMessage requestTradeMessage)
|
||||
/*public void onRequestTakerDepositPaymentMessage(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
log.debug("2.7 onTakerDepositPaymentRequested");
|
||||
log.debug("2.7 onRequestTakerDepositPaymentMessage");
|
||||
verifyOfferer(requestTradeMessage);
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.1 verifyAccountRegistration");
|
||||
if (blockChainFacade.verifyAccountRegistration())
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -308,35 +566,35 @@ public class TakerPaymentProtocol
|
||||
}
|
||||
else
|
||||
{
|
||||
takerPaymentProtocolListener.onFailure("Offerers account registration is invalid.");
|
||||
// listener.onFailure("Offerers account registration is invalid.");
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 2.9 Create and sign the contract
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createAndSignContract(TradeMessage requestTradeMessage)
|
||||
/* private void createAndSignContract(TradeMessageOld requestTradeMessage)
|
||||
{
|
||||
log.debug("2.9 createAndSignContract");
|
||||
checkNotNull(offer);
|
||||
checkNotNull(trade.getOffer());
|
||||
checkNotNull(trade.getTradeAmount());
|
||||
checkNotNull(trade.getTakeOfferFeeTxID());
|
||||
checkNotNull(requestTradeMessage.getAccountID());
|
||||
checkNotNull(user.getAccountID());
|
||||
checkNotNull(trade.getTakeOfferFeeTxId());
|
||||
checkNotNull(requestTradeMessage.getAccountId());
|
||||
checkNotNull(user.getAccountId());
|
||||
checkNotNull(requestTradeMessage.getBankAccount());
|
||||
checkNotNull(user.getCurrentBankAccount());
|
||||
checkNotNull(user.getMessagePubKeyAsHex());
|
||||
|
||||
Contract contract = new Contract(offer,
|
||||
Contract contract = new Contract(trade.getOffer(),
|
||||
trade.getTradeAmount(),
|
||||
trade.getTakeOfferFeeTxID(),
|
||||
requestTradeMessage.getAccountID(),
|
||||
user.getAccountID(),
|
||||
trade.getTakeOfferFeeTxId(),
|
||||
requestTradeMessage.getAccountId(),
|
||||
user.getAccountId(),
|
||||
requestTradeMessage.getBankAccount(),
|
||||
user.getCurrentBankAccount(),
|
||||
offer.getMessagePubKeyAsHex(),
|
||||
trade.getOffer().getMessagePubKeyAsHex(),
|
||||
user.getMessagePubKeyAsHex()
|
||||
);
|
||||
|
||||
@ -352,14 +610,14 @@ public class TakerPaymentProtocol
|
||||
trade.setContractTakerSignature(signature);
|
||||
|
||||
payDeposit(requestTradeMessage);
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
|
||||
@ -369,7 +627,7 @@ public class TakerPaymentProtocol
|
||||
|
||||
String offererPubKey = requestTradeMessage.getOffererPubKey();
|
||||
String takerPubKey = walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString();
|
||||
String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
|
||||
String arbitratorPubKey = trade.getOffer().getArbitrator().getPubKeyAsHex();
|
||||
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
|
||||
|
||||
checkNotNull(takerInputAmount);
|
||||
@ -380,8 +638,8 @@ public class TakerPaymentProtocol
|
||||
checkNotNull(preparedOffererDepositTxAsHex);
|
||||
|
||||
log.debug("2.10 offererCreatesMSTxAndAddPayment");
|
||||
log.debug("takerAmount " + BtcFormatter.satoshiToString(takerInputAmount));
|
||||
log.debug("msOutputAmount " + BtcFormatter.satoshiToString(msOutputAmount));
|
||||
log.debug("takerAmount " + BtcFormatter.formatSatoshis(takerInputAmount));
|
||||
log.debug("msOutputAmount " + BtcFormatter.formatSatoshis(msOutputAmount));
|
||||
log.debug("offerer pubkey " + offererPubKey);
|
||||
log.debug("taker pubkey " + takerPubKey);
|
||||
log.debug("arbitrator pubkey " + arbitratorPubKey);
|
||||
@ -396,14 +654,14 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.error("2.10 error at walletFacade.takerAddPaymentAndSign: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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");
|
||||
|
||||
@ -414,21 +672,21 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.debug("2.11 sendSignedTakerDepositTxAsHex REQUEST_TAKER_DEPOSIT_PAYMENT onResult");
|
||||
// Message arrived at taker
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
// //TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void 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();
|
||||
String accountID = user.getAccountID();
|
||||
String accountID = user.getAccountId();
|
||||
String messagePubKey = user.getMessagePubKeyAsHex();
|
||||
String contractAsJson = trade.getContractAsJson();
|
||||
String signature = trade.getTakerSignature();
|
||||
@ -443,7 +701,7 @@ public class TakerPaymentProtocol
|
||||
log.debug("2.10 txConnOutAsHex: " + txConnOutAsHex);
|
||||
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(),
|
||||
bankAccount,
|
||||
accountID,
|
||||
@ -460,7 +718,7 @@ public class TakerPaymentProtocol
|
||||
|
||||
log.debug("2.11 sendTradingMessage");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
//************************************************************************************************
|
||||
@ -472,14 +730,14 @@ public class TakerPaymentProtocol
|
||||
// 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());
|
||||
|
||||
String txID = walletFacade.takerCommitDepositTx(tradeMessage.getDepositTxAsHex());
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
takerPaymentProtocolListener.onDepositTxPublished(txID);
|
||||
}
|
||||
// listener.onProgress(getProgress());
|
||||
listener.onDepositTxPublishedMessage(txID);
|
||||
} */
|
||||
|
||||
|
||||
//************************************************************************************************
|
||||
@ -491,11 +749,11 @@ public class TakerPaymentProtocol
|
||||
// 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");
|
||||
takerPaymentProtocolListener.onBankTransferInited(tradeMessage);
|
||||
}
|
||||
listener.onBankTransferInitedMessage(tradeMessage);
|
||||
} */
|
||||
|
||||
//************************************************************************************************
|
||||
// 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
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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>()
|
||||
{
|
||||
@Override
|
||||
@ -516,7 +774,7 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
System.out.println("######### 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()));
|
||||
}
|
||||
@ -526,7 +784,7 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.error("######### 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
|
||||
@ -551,13 +809,13 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.error("3.12 offererCreatesAndSignsPayoutTx onFailed AddressFormatException " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 3.13 Send payout txID to offerer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void sendPayoutTxToOfferer(String payoutTxAsHex)
|
||||
/*void sendPayoutTxToOfferer(String payoutTxAsHex)
|
||||
{
|
||||
log.debug("3.13 sendPayoutTxToOfferer ");
|
||||
TradeMessageListener listener = new TradeMessageListener()
|
||||
@ -567,27 +825,28 @@ public class TakerPaymentProtocol
|
||||
{
|
||||
log.debug("3.13 sendPayoutTxToOfferer PAYOUT_TX_PUBLISHED onResult");
|
||||
log.debug("3.13 TRADE COMPLETE!!!!!!!!!!!");
|
||||
takerPaymentProtocolListener.onProgress(getProgress());
|
||||
//TakerAsSellerProtocol.this. listener.onFailure(getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void 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);
|
||||
log.debug("3.13 sendTradeMessage PAYOUT_TX_PUBLISHED");
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, listener);
|
||||
}
|
||||
} */
|
||||
|
||||
private double getProgress()
|
||||
/* private double getProgress()
|
||||
{
|
||||
currentStep++;
|
||||
int numberOfSteps = 10;
|
||||
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;
|
||||
|
||||
public interface AddressLookupListener
|
||||
public interface GetPeerAddressListener
|
||||
{
|
||||
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
|
||||
{
|
||||
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));
|
||||
} */
|
||||
|
||||
@ -60,7 +60,7 @@ public class DSAKeyUtil
|
||||
} catch (Throwable throwable)
|
||||
{
|
||||
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
|
||||
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;
|
||||
|
||||
import io.bitsquare.btc.BtcValidatorTest;
|
||||
import io.bitsquare.currency.BitcoinTest;
|
||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||
import io.nucleo.scheduler.SequenceSchedulerTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@ -12,7 +12,7 @@ import org.junit.runners.Suite;
|
||||
BtcValidatorTest.class,
|
||||
BitSquareConverterTest.class,
|
||||
BitSquareValidatorTest.class,
|
||||
BitcoinTest.class
|
||||
SequenceSchedulerTest.class
|
||||
})
|
||||
|
||||
public class BitSquareTestSuite
|
||||
|
@ -19,16 +19,16 @@ public class BtcValidatorTest
|
||||
amount = BigInteger.ZERO;
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = FeePolicy.TX_FEE_depr;
|
||||
amount = FeePolicy.TX_FEE;
|
||||
assertFalse("tx unfunded, pending", BtcValidator.isMinSpendableAmount(amount));
|
||||
|
||||
amount = Transaction.MIN_NONDUST_OUTPUT;
|
||||
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));
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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 static org.junit.Assert.assertFalse;
|
||||
@ -34,5 +43,37 @@ public class BitSquareValidatorTest
|
||||
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…
x
Reference in New Issue
Block a user