mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-06-07 06:32:47 -04:00
payment to MS fund
This commit is contained in:
parent
7d0676a995
commit
a4efa29bcd
37 changed files with 1081 additions and 546 deletions
|
@ -19,11 +19,13 @@ git clone --recursive git://github.com/bitsquare/bitsquare
|
||||||
* bitcoinj integration
|
* bitcoinj integration
|
||||||
* Setup with account registration and tx with OP_RETURN + embedded and blinded bank account data
|
* Setup with account registration and tx with OP_RETURN + embedded and blinded bank account data
|
||||||
* Offer fee payment with a OP_RETURN tx and fees to miners
|
* Offer fee payment with a OP_RETURN tx and fees to miners
|
||||||
|
* Pay in to MS fund
|
||||||
|
|
||||||
### Next steps:
|
### Next steps:
|
||||||
* Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer)
|
* Payout from MS fund
|
||||||
* Arbitrator integration
|
* Arbitrator integration
|
||||||
* Messaging system
|
* Messaging system
|
||||||
|
* Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer)
|
||||||
* ...
|
* ...
|
||||||
|
|
||||||
|
|
||||||
|
|
6
TODO.txt
6
TODO.txt
|
@ -1,5 +1,4 @@
|
||||||
- payment process update with new models
|
- pay out from MS in payment process
|
||||||
- btc payments in payment process
|
|
||||||
- arbitration integration
|
- arbitration integration
|
||||||
|
|
||||||
Messaging!
|
Messaging!
|
||||||
|
@ -9,8 +8,7 @@ low prio:
|
||||||
- add settings after setup
|
- add settings after setup
|
||||||
- settings screen
|
- settings screen
|
||||||
- return to setup when unregistered, change/add bank accounts from settings
|
- return to setup when unregistered, change/add bank accounts from settings
|
||||||
- warning popups
|
- BigInteger for all btc values
|
||||||
-
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.bitsquare;
|
package io.bitsquare;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
@ -45,9 +46,11 @@ public class BitSquare extends Application
|
||||||
final Storage storage = injector.getInstance(Storage.class);
|
final Storage storage = injector.getInstance(Storage.class);
|
||||||
user.updateFromStorage((User) storage.read(user.getClass().getName()));
|
user.updateFromStorage((User) storage.read(user.getClass().getName()));
|
||||||
|
|
||||||
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
// mock
|
||||||
initSettings(settings, storage, user);
|
initSettings(settings, storage, user);
|
||||||
|
|
||||||
|
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
|
||||||
|
|
||||||
stage.setTitle("BitSquare");
|
stage.setTitle("BitSquare");
|
||||||
|
|
||||||
GuiceFXMLLoader.setInjector(injector);
|
GuiceFXMLLoader.setInjector(injector);
|
||||||
|
@ -83,55 +86,62 @@ public class BitSquare extends Application
|
||||||
{
|
{
|
||||||
// write default settings
|
// write default settings
|
||||||
settings.getAcceptedCountryLocales().clear();
|
settings.getAcceptedCountryLocales().clear();
|
||||||
settings.getAcceptedLanguageLocales().clear();
|
// settings.addAcceptedLanguageLocale(Locale.getDefault());
|
||||||
|
settings.addAcceptedLanguageLocale(MockData.getLocales().get(0));
|
||||||
settings.addAcceptedLanguageLocale(Locale.getDefault());
|
|
||||||
settings.addAcceptedCountryLocale(Locale.getDefault());
|
|
||||||
|
|
||||||
//TODO mock
|
|
||||||
settings.addAcceptedLanguageLocale(new Locale("en", "US"));
|
settings.addAcceptedLanguageLocale(new Locale("en", "US"));
|
||||||
settings.addAcceptedLanguageLocale(new Locale("es", "ES"));
|
settings.addAcceptedLanguageLocale(new Locale("es", "ES"));
|
||||||
|
|
||||||
settings.addAcceptedCountryLocale(new Locale("de", "AT"));
|
settings.getAcceptedCountryLocales().clear();
|
||||||
|
//settings.addAcceptedCountryLocale(Locale.getDefault());
|
||||||
|
settings.addAcceptedCountryLocale(MockData.getLocales().get(0));
|
||||||
settings.addAcceptedCountryLocale(new Locale("en", "US"));
|
settings.addAcceptedCountryLocale(new Locale("en", "US"));
|
||||||
settings.addAcceptedCountryLocale(new Locale("es", "ES"));
|
settings.addAcceptedCountryLocale(new Locale("es", "ES"));
|
||||||
|
|
||||||
settings.addArbitrator(new Arbitrator("Charly Boom", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Charly_Boom"));
|
settings.getAcceptedArbitrators().clear();
|
||||||
settings.addArbitrator(new Arbitrator("Tom Shang", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Tom_Shang"));
|
settings.addAcceptedArbitrator(new Arbitrator("uid_1", "Charlie Boom", UUID.randomUUID().toString(),
|
||||||
settings.addArbitrator(new Arbitrator("Edward Snow", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Edward_Swow"));
|
UUID.randomUUID().toString(), "http://www.arbit.io/Charly_Boom", 0.1, 10, Utils.toNanoCoins("0.01")));
|
||||||
settings.addArbitrator(new Arbitrator("Julian Sander", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Julian_Sander"));
|
settings.addAcceptedArbitrator(new Arbitrator("uid_2", "Tom Shang", UUID.randomUUID().toString(),
|
||||||
|
UUID.randomUUID().toString(), "http://www.arbit.io/Tom_Shang", 0, 1, Utils.toNanoCoins("0.001")));
|
||||||
|
settings.addAcceptedArbitrator(new Arbitrator("uid_3", "Edward Snow", UUID.randomUUID().toString(),
|
||||||
|
UUID.randomUUID().toString(), "http://www.arbit.io/Edward_Swow", 0.2, 5, Utils.toNanoCoins("0.05")));
|
||||||
|
settings.addAcceptedArbitrator(new Arbitrator("uid_4", "Julian Sander", UUID.randomUUID().toString(),
|
||||||
|
UUID.randomUUID().toString(), "http://www.arbit.io/Julian_Sander", 0, 20, Utils.toNanoCoins("0.1")));
|
||||||
|
|
||||||
|
settings.setMinCollateral(0.01);
|
||||||
|
settings.setMaxCollateral(0.1);
|
||||||
|
|
||||||
storage.write(settings.getClass().getName(), settings);
|
storage.write(settings.getClass().getName(), settings);
|
||||||
|
|
||||||
initMockUser(storage, user);
|
//initMockUser(storage, user);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
settings.updateFromStorage(savedSettings);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initMockUser(Storage storage, User user)
|
private void initMockUser(Storage storage, User user)
|
||||||
{
|
{
|
||||||
|
user.getBankAccounts().clear();
|
||||||
|
|
||||||
BankAccount bankAccount1 = new BankAccount(new BankAccountType(BankAccountType.BankAccountTypeEnum.SEPA, "Iban", "Bic"),
|
BankAccount bankAccount1 = new BankAccount(new BankAccountType(BankAccountType.BankAccountTypeEnum.SEPA, "Iban", "Bic"),
|
||||||
MockData.getCurrencies().get(0),
|
MockData.getCurrencies().get(0),
|
||||||
MockData.getLocales().get(0),
|
MockData.getLocales().get(0),
|
||||||
"Main account",
|
"Main EUR account",
|
||||||
"Manfred Karrer",
|
"Manfred Karrer",
|
||||||
"564613242346",
|
"564613242346",
|
||||||
"23432432434"
|
"23432432434"
|
||||||
);
|
);
|
||||||
BankAccount bankAccount2 = new BankAccount(new BankAccountType(BankAccountType.BankAccountTypeEnum.OK_PAY, "Number", "ID"),
|
user.addBankAccount(bankAccount1);
|
||||||
MockData.getCurrencies().get(0),
|
|
||||||
MockData.getLocales().get(0),
|
BankAccount bankAccount2 = new BankAccount(new BankAccountType(BankAccountType.BankAccountTypeEnum.INTERNATIONAL, "Number", "ID"),
|
||||||
"OK account",
|
MockData.getCurrencies().get(1),
|
||||||
|
MockData.getLocales().get(2),
|
||||||
|
"US account",
|
||||||
"Manfred Karrer",
|
"Manfred Karrer",
|
||||||
"22312123123123123",
|
"22312123123123123",
|
||||||
"asdasdasdas"
|
"asdasdasdas"
|
||||||
);
|
);
|
||||||
user.addBankAccount(bankAccount2);
|
user.addBankAccount(bankAccount2);
|
||||||
user.addBankAccount(bankAccount1);
|
|
||||||
user.setAccountID(UUID.randomUUID().toString());
|
user.setAccountID(UUID.randomUUID().toString());
|
||||||
|
|
||||||
storage.write(user.getClass().getName(), user);
|
storage.write(user.getClass().getName(), user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,20 +42,23 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
|
||||||
walletFile = new File(".", "bitsquare_account_reg" + ".wallet");
|
walletFile = new File(".", "bitsquare_account_reg" + ".wallet");
|
||||||
if (walletFile.exists())
|
if (walletFile.exists())
|
||||||
{
|
{
|
||||||
|
FileInputStream walletStream = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FileInputStream walletStream = new FileInputStream(walletFile);
|
walletStream = new FileInputStream(walletFile);
|
||||||
new WalletProtobufSerializer().readWallet(WalletProtobufSerializer.parseToProto(walletStream), this);
|
|
||||||
} catch (FileNotFoundException e)
|
} catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (UnreadableWalletException e)
|
}
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
new WalletProtobufSerializer().readWallet(WalletProtobufSerializer.parseToProto(walletStream), this);
|
||||||
} catch (IOException e)
|
} catch (UnreadableWalletException | IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -69,7 +72,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
|
||||||
saveToFile(walletFile);
|
saveToFile(walletFile);
|
||||||
} catch (IOException e)
|
} catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
autosaveToFile(walletFile, 1, TimeUnit.SECONDS, null);
|
autosaveToFile(walletFile, 1, TimeUnit.SECONDS, null);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +84,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
|
||||||
saveToFile(walletFile);
|
saveToFile(walletFile);
|
||||||
} catch (IOException e)
|
} catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
package io.bitsquare.btc;
|
package io.bitsquare.btc;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.Utils;
|
||||||
|
import io.bitsquare.gui.util.Converter;
|
||||||
|
import io.bitsquare.gui.util.Formatter;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class BtcFormatter
|
public class BtcFormatter
|
||||||
{
|
{
|
||||||
|
@ -12,4 +18,31 @@ public class BtcFormatter
|
||||||
{
|
{
|
||||||
return satoshis.doubleValue() / BTC.doubleValue();
|
return satoshis.doubleValue() / BTC.doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BigInteger stringValueToSatoshis(String value)
|
||||||
|
{
|
||||||
|
return Utils.toNanoCoins(String.valueOf(Converter.stringToDouble(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigInteger doubleValueToSatoshis(double value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// only "." as decimal sep supported by Utils.toNanoCoins
|
||||||
|
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.ENGLISH);
|
||||||
|
String stringValue = decimalFormat.format(value);
|
||||||
|
return Utils.toNanoCoins(stringValue);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
return BigInteger.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatSatoshis(BigInteger satoshis, boolean useBTC)
|
||||||
|
{
|
||||||
|
if (useBTC)
|
||||||
|
return Formatter.formatDouble(satoshiToBTC(satoshis), 8) + " BTC";
|
||||||
|
else
|
||||||
|
return Formatter.formatDouble(satoshiToBTC(satoshis), 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
package io.bitsquare.btc;
|
package io.bitsquare.btc;
|
||||||
|
|
||||||
import com.google.bitcoin.core.Transaction;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
public class Fees
|
public class Fees
|
||||||
{
|
{
|
||||||
|
// min dust value lead to exception at for non standard to address pay scripts, so we use a value >= 7860 instead
|
||||||
public static BigInteger ACCOUNT_REGISTRATION_FEE = Transaction.MIN_NONDUST_OUTPUT;// Utils.toNanoCoins("0.001");
|
public static BigInteger ACCOUNT_REGISTRATION_FEE = BigInteger.valueOf(7860);// Utils.toNanoCoins("0.001");
|
||||||
public static BigInteger OFFER_CREATION_FEE = Transaction.MIN_NONDUST_OUTPUT; // Utils.toNanoCoins("0.001");
|
public static BigInteger OFFER_CREATION_FEE = BigInteger.valueOf(7860); // //Transaction.MIN_NONDUST_OUTPUT; // Utils.toNanoCoins("0.001");
|
||||||
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;
|
public static BigInteger OFFER_TAKER_FEE = BigInteger.valueOf(7860);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
package io.bitsquare.btc;
|
package io.bitsquare.btc;
|
||||||
|
|
||||||
import com.google.bitcoin.core.*;
|
import com.google.bitcoin.core.*;
|
||||||
|
import com.google.bitcoin.crypto.TransactionSignature;
|
||||||
import com.google.bitcoin.kits.WalletAppKit;
|
import com.google.bitcoin.kits.WalletAppKit;
|
||||||
import com.google.bitcoin.params.MainNetParams;
|
import com.google.bitcoin.params.MainNetParams;
|
||||||
import com.google.bitcoin.params.RegTestParams;
|
import com.google.bitcoin.params.RegTestParams;
|
||||||
import com.google.bitcoin.script.Script;
|
import com.google.bitcoin.script.Script;
|
||||||
import com.google.bitcoin.script.ScriptBuilder;
|
import com.google.bitcoin.script.ScriptBuilder;
|
||||||
import com.google.bitcoin.utils.Threading;
|
import com.google.bitcoin.utils.Threading;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
|
import io.bitsquare.gui.util.Popups;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -19,9 +23,7 @@ import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That facade delivers wallet functionality from the bitcoinJ library
|
* That facade delivers wallet functionality from the bitcoinJ library
|
||||||
|
@ -33,28 +35,44 @@ public class WalletFacade implements WalletEventListener
|
||||||
public static final String MAIN_NET = "MAIN_NET";
|
public static final String MAIN_NET = "MAIN_NET";
|
||||||
public static final String TEST_NET = "TEST_NET";
|
public static final String TEST_NET = "TEST_NET";
|
||||||
|
|
||||||
|
// for testing trade process between offerer and taker
|
||||||
|
//public static final String WALLET_PREFIX = "offerer"; // offerer
|
||||||
|
// public static final String WALLET_PREFIX = "taker"; // offerer
|
||||||
|
|
||||||
|
public static final String WALLET_PREFIX = "bitsquare";
|
||||||
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
|
private static final Logger log = LoggerFactory.getLogger(WalletFacade.class);
|
||||||
|
|
||||||
private NetworkParameters networkParameters;
|
private NetworkParameters params;
|
||||||
private WalletAppKit walletAppKit;
|
private WalletAppKit walletAppKit;
|
||||||
private CryptoFacade cryptoFacade;
|
private CryptoFacade cryptoFacade;
|
||||||
private BlockChainFacade blockChainFacade;
|
|
||||||
|
|
||||||
// that wallet is used only for the registration process
|
// that wallet is used only for the registration process
|
||||||
private AccountRegistrationWallet accountRegistrationWallet = null;
|
private AccountRegistrationWallet accountRegistrationWallet = null;
|
||||||
|
|
||||||
private List<DownloadListener> downloadListeners = new ArrayList<>();
|
private List<DownloadListener> downloadListeners = new ArrayList<>();
|
||||||
private List<WalletListener> walletListeners = new ArrayList<>();
|
private List<WalletListener> walletListeners = new ArrayList<>();
|
||||||
|
private Wallet wallet;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public WalletFacade(NetworkParameters networkParameters, WalletAppKit walletAppKit, CryptoFacade cryptoFacade, BlockChainFacade blockChainFacade)
|
public WalletFacade(NetworkParameters params, WalletAppKit walletAppKit, CryptoFacade cryptoFacade)
|
||||||
{
|
{
|
||||||
this.networkParameters = networkParameters;
|
this.params = params;
|
||||||
this.walletAppKit = walletAppKit;
|
this.walletAppKit = walletAppKit;
|
||||||
this.cryptoFacade = cryptoFacade;
|
this.cryptoFacade = cryptoFacade;
|
||||||
this.blockChainFacade = blockChainFacade;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public Methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void initWallet()
|
public void initWallet()
|
||||||
{
|
{
|
||||||
// Tell bitcoinj to run event handlers on the JavaFX UI thread. This keeps things simple and means
|
// Tell bitcoinj to run event handlers on the JavaFX UI thread. This keeps things simple and means
|
||||||
|
@ -63,11 +81,11 @@ public class WalletFacade implements WalletEventListener
|
||||||
// a future version.
|
// a future version.
|
||||||
Threading.USER_THREAD = Platform::runLater;
|
Threading.USER_THREAD = Platform::runLater;
|
||||||
|
|
||||||
if (networkParameters == RegTestParams.get())
|
if (params == RegTestParams.get())
|
||||||
{
|
{
|
||||||
walletAppKit.connectToLocalHost(); // You should run a regtest mode bitcoind locally.
|
walletAppKit.connectToLocalHost(); // You should run a regtest mode bitcoind locally.
|
||||||
}
|
}
|
||||||
else if (networkParameters == MainNetParams.get())
|
else if (params == MainNetParams.get())
|
||||||
{
|
{
|
||||||
// Checkpoints are block headers that ship inside our app: for a new user, we pick the last header
|
// Checkpoints are block headers that ship inside our app: for a new user, we pick the last header
|
||||||
// in the checkpoints file and then download the rest from the network. It makes things much faster.
|
// in the checkpoints file and then download the rest from the network. It makes things much faster.
|
||||||
|
@ -80,16 +98,214 @@ public class WalletFacade implements WalletEventListener
|
||||||
// or progress widget to keep the user engaged whilst we initialise, but we don't.
|
// or progress widget to keep the user engaged whilst we initialise, but we don't.
|
||||||
walletAppKit.setDownloadListener(new BlockChainDownloadListener())
|
walletAppKit.setDownloadListener(new BlockChainDownloadListener())
|
||||||
.setBlockingStartup(false)
|
.setBlockingStartup(false)
|
||||||
.setUserAgent("BitSquare", "1.0");
|
.setUserAgent("BitSquare", "0.1");
|
||||||
walletAppKit.startAsync();
|
walletAppKit.startAsync();
|
||||||
walletAppKit.awaitRunning();
|
walletAppKit.awaitRunning();
|
||||||
|
|
||||||
|
wallet = walletAppKit.wallet();
|
||||||
|
|
||||||
// Don't make the user wait for confirmations for now, as the intention is they're sending it their own money!
|
// Don't make the user wait for confirmations for now, as the intention is they're sending it their own money!
|
||||||
getWallet().allowSpendingUnconfirmedTransactions();
|
wallet.allowSpendingUnconfirmedTransactions();
|
||||||
walletAppKit.peerGroup().setMaxConnections(11);
|
walletAppKit.peerGroup().setMaxConnections(20);
|
||||||
|
|
||||||
getWallet().addEventListener(this);
|
wallet.addEventListener(this);
|
||||||
|
|
||||||
log.info(getWallet().toString());
|
log.info(wallet.toString());
|
||||||
|
|
||||||
|
// testTradeProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO only temp. for testing trade process between offerer and taker
|
||||||
|
private void testTradeProcess()
|
||||||
|
{
|
||||||
|
//wallet.allowSpendingUnconfirmedTransactions();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String tx1AsHex, tx2AsHex, tx2ScriptSigAsHex, tx2ConnOutAsHex;
|
||||||
|
|
||||||
|
BigInteger offererAmount = Utils.toNanoCoins("0.01");
|
||||||
|
BigInteger takerAmount = Utils.toNanoCoins("0.02");
|
||||||
|
|
||||||
|
String takerPubKey = "0207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||||
|
String offererPubKey = "0352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7";
|
||||||
|
String arbitratorPubKey = "";
|
||||||
|
|
||||||
|
// 1 offerer creates MS TX and pay in
|
||||||
|
/* Transaction tx1 = offererCreatesMSTxAndAddPayment(offererAmount, offererPubKey, takerPubKey, arbitratorPubKey);
|
||||||
|
tx1AsHex = Utils.bytesToHexString(tx1.bitcoinSerialize());
|
||||||
|
*/
|
||||||
|
|
||||||
|
tx1AsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffff0240420f00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac00000000";
|
||||||
|
|
||||||
|
// 2. taker pay in and sign
|
||||||
|
/* Transaction tx2 = takerAddPaymentAndSign(takerAmount, msOutputAmount, offererPubKey, takerPubKey, arbitratorPubKey, tx1AsHex);
|
||||||
|
tx2AsHex = Utils.bytesToHexString(tx2.bitcoinSerialize());
|
||||||
|
tx2ScriptSigAsHex = Utils.bytesToHexString(tx2.getInput(1).getScriptBytes());
|
||||||
|
tx2ConnOutAsHex = Utils.bytesToHexString(tx2.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize());
|
||||||
|
*/
|
||||||
|
|
||||||
|
tx2AsHex = "01000000024378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0000000006b4830450221008e599dd7bb7223c7b036869198b14f08009f9bc117709d23c249d0bdd6b483be022047be181f467782ea277b36890feb2f6de3ceddcedf8730a9f505bac36b3b015b01210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7ffffffffa58b22a93a0fcf99ba48aa3b96d842284b2b3d24f72d045cc192ea8a6b89435c010000006a47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568ffffffff03c0c62d00000000004852210352f2e34760514099f90b03aab91239466924c3b06047d3cf0e011f26ef96ceb7210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b65680053aeb077e605000000001976a9149fc3d8e0371b6eab89a8c3c015839f9e493ccf6588ac7035d705000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||||
|
tx2ScriptSigAsHex = "47304402207f4beeb1a86432be0b4c3d4f4db7416b52b66c84383d1980d39e21d547a1762f02200405d0d4b80d1094e3a08cb39ef6f1161be163026d417af08d54c5a1cfdbbbeb01210207cf5fb65d6923d5d41db21ceac9567a0fc3eb92c6137f274018381ced7b6568";
|
||||||
|
tx2ConnOutAsHex = "01000000014378dfcd19add18eb6f118a1e35ced127ff23c9dc5034eee1cda5b9caeb814f0010000006a473044022011431387fc19b093b26a6d2371995c828179aae68e94ad5804e5d0986a6b471302206abc2b698375620e65fc9970b7781da0af2179d1bdc4ebc82a13e285359a3ce7012103c7b9e9ef657705522c85b8429bb2b42c04f0fd4a09e0605cd7dd62ffecb57944ffffffff02c0ce823e000000001976a9142d1b4347ae850805f3badbb4b2949674f46c4ccd88ac00e1f505000000001976a914e5175c1f71c28218306d4a27c8cec0269dddbbde88ac00000000";
|
||||||
|
|
||||||
|
// 3. offerer sign and send
|
||||||
|
Transaction tx3 = offererSignAndSendTx(tx1AsHex, tx2AsHex, tx2ConnOutAsHex, tx2ScriptSigAsHex);
|
||||||
|
|
||||||
|
log.info(tx3.toString());
|
||||||
|
|
||||||
|
} catch (AddressFormatException | InsufficientMoneyException | InterruptedException | ExecutionException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. offerer
|
||||||
|
private Transaction offererCreatesMSTxAndAddPayment(BigInteger offererAmount, String offererPubKey, String takerPubKey, String arbitratorPubKey) throws InsufficientMoneyException
|
||||||
|
{
|
||||||
|
// use that to use the convenient api for getting the best coin selection and fee calculation
|
||||||
|
// TODO should be constructed manually
|
||||||
|
Transaction tx = new Transaction(params);
|
||||||
|
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||||
|
tx.addOutput(offererAmount, multiSigOutputScript);
|
||||||
|
Wallet.SendRequest request = Wallet.SendRequest.forTx(tx);
|
||||||
|
wallet.completeTx(request);
|
||||||
|
// TODO remove sig or use SigHash.NONE
|
||||||
|
//tx.getInput(0).setScriptSig(null);
|
||||||
|
|
||||||
|
/*
|
||||||
|
IN[0] offerer
|
||||||
|
OUT[0] MS
|
||||||
|
OUT[1] offerer change
|
||||||
|
*/
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. taker
|
||||||
|
public Transaction takerAddPaymentAndSign(BigInteger takerAmount,
|
||||||
|
BigInteger msOutputAmount,
|
||||||
|
String offererPubKey,
|
||||||
|
String takerPubKey,
|
||||||
|
String arbitratorPubKey,
|
||||||
|
String tx1AsHex
|
||||||
|
) throws InsufficientMoneyException, ExecutionException, InterruptedException, AddressFormatException
|
||||||
|
{
|
||||||
|
Script multiSigOutputScript = getMultiSigScript(offererPubKey, takerPubKey, arbitratorPubKey);
|
||||||
|
|
||||||
|
// use that to use the convenient api for getting the best coin selection and fee calculation
|
||||||
|
// TODO should be constructed manually
|
||||||
|
Transaction dummyTx = new Transaction(params);
|
||||||
|
dummyTx.addOutput(takerAmount, multiSigOutputScript);
|
||||||
|
wallet.completeTx(Wallet.SendRequest.forTx(dummyTx));
|
||||||
|
|
||||||
|
Transaction tx = new Transaction(params, Utils.parseAsHexOrBase58(tx1AsHex));
|
||||||
|
tx.addInput(dummyTx.getInput(0));
|
||||||
|
tx.addOutput(dummyTx.getOutput(1));
|
||||||
|
tx.getOutput(0).setValue(msOutputAmount);
|
||||||
|
|
||||||
|
TransactionInput input = tx.getInput(1);
|
||||||
|
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
|
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
||||||
|
Sha256Hash hash = tx.hashForSignature(1, scriptPubKey, Transaction.SigHash.ALL, false);
|
||||||
|
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
||||||
|
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
||||||
|
if (scriptPubKey.isSentToRawPubKey())
|
||||||
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
||||||
|
else if (scriptPubKey.isSentToAddress())
|
||||||
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
||||||
|
else
|
||||||
|
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
||||||
|
|
||||||
|
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
IN[0] offerer
|
||||||
|
IN[1] taker signed
|
||||||
|
OUT[0] MS
|
||||||
|
OUT[1] offerer change
|
||||||
|
OUT[2] taker change
|
||||||
|
*/
|
||||||
|
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction offererSignAndSendTx(String tx1AsHex,
|
||||||
|
String tx2AsHex,
|
||||||
|
String tx2ConnOutAsHex,
|
||||||
|
String tx2ScriptSigAsHex) throws Exception
|
||||||
|
{
|
||||||
|
Transaction tx = new Transaction(params);
|
||||||
|
|
||||||
|
Transaction tx1 = new Transaction(params, Utils.parseAsHexOrBase58(tx1AsHex));
|
||||||
|
Transaction tx1ConnOut = wallet.getTransaction(tx1.getInput(0).getOutpoint().getHash());
|
||||||
|
TransactionOutPoint tx1OutPoint = new TransactionOutPoint(params, 0, tx1ConnOut);
|
||||||
|
TransactionInput tx1Input = new TransactionInput(params, tx, tx1.getInput(0).getScriptBytes(), tx1OutPoint);
|
||||||
|
tx1Input.setParent(tx);
|
||||||
|
tx.addInput(tx1Input);
|
||||||
|
|
||||||
|
Transaction tx2 = new Transaction(params, Utils.parseAsHexOrBase58(tx2AsHex));
|
||||||
|
Transaction tx2ConnOut = new Transaction(params, Utils.parseAsHexOrBase58(tx2ConnOutAsHex));
|
||||||
|
TransactionOutPoint tx2OutPoint = new TransactionOutPoint(params, 1, tx2ConnOut);
|
||||||
|
TransactionInput tx2Input = new TransactionInput(params, tx, Utils.parseAsHexOrBase58(tx2ScriptSigAsHex), tx2OutPoint);
|
||||||
|
tx2Input.setParent(tx);
|
||||||
|
tx.addInput(tx2Input);
|
||||||
|
|
||||||
|
tx.addOutput(tx2.getOutput(0));
|
||||||
|
tx.addOutput(tx2.getOutput(1));
|
||||||
|
tx.addOutput(tx2.getOutput(2));
|
||||||
|
|
||||||
|
TransactionInput input = tx.getInput(0);
|
||||||
|
Script scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
|
ECKey sigKey = input.getOutpoint().getConnectedKey(wallet);
|
||||||
|
Sha256Hash hash = tx.hashForSignature(0, scriptPubKey, Transaction.SigHash.ALL, false);
|
||||||
|
ECKey.ECDSASignature ecSig = sigKey.sign(hash);
|
||||||
|
TransactionSignature txSig = new TransactionSignature(ecSig, Transaction.SigHash.ALL, false);
|
||||||
|
if (scriptPubKey.isSentToRawPubKey())
|
||||||
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig));
|
||||||
|
else if (scriptPubKey.isSentToAddress())
|
||||||
|
input.setScriptSig(ScriptBuilder.createInputScript(txSig, sigKey));
|
||||||
|
else
|
||||||
|
throw new ScriptException("Don't know how to sign for this kind of scriptPubKey: " + scriptPubKey);
|
||||||
|
|
||||||
|
input.getScriptSig().correctlySpends(tx, 0, scriptPubKey, false);
|
||||||
|
|
||||||
|
input = tx.getInput(1);
|
||||||
|
scriptPubKey = input.getConnectedOutput().getScriptPubKey();
|
||||||
|
input.getScriptSig().correctlySpends(tx, 1, scriptPubKey, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
IN[0] offerer signed
|
||||||
|
IN[1] taker signed
|
||||||
|
OUT[0] MS
|
||||||
|
OUT[1] offerer change
|
||||||
|
OUT[2] taker change
|
||||||
|
*/
|
||||||
|
|
||||||
|
tx.verify();
|
||||||
|
|
||||||
|
ListenableFuture<Transaction> broadcastComplete = walletAppKit.peerGroup().broadcastTransaction(tx);
|
||||||
|
|
||||||
|
FutureCallback callback = new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.info("sendResult onSuccess:" + transaction.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.warn("sendResult onFailure:" + t.toString());
|
||||||
|
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Futures.addCallback(broadcastComplete, callback);
|
||||||
|
|
||||||
|
return tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutDown()
|
public void shutDown()
|
||||||
|
@ -100,6 +316,10 @@ public class WalletFacade implements WalletEventListener
|
||||||
walletAppKit.awaitTerminated();
|
walletAppKit.awaitTerminated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Listener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void addDownloadListener(DownloadListener listener)
|
public void addDownloadListener(DownloadListener listener)
|
||||||
{
|
{
|
||||||
downloadListeners.add(listener);
|
downloadListeners.add(listener);
|
||||||
|
@ -131,23 +351,40 @@ public class WalletFacade implements WalletEventListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//MOCK
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
public KeyPair createNewAddress()
|
// Trading wallet
|
||||||
{
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
return new KeyPair(UUID.randomUUID().toString(), UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigInteger getBalance()
|
public BigInteger getBalance()
|
||||||
{
|
{
|
||||||
return getWallet().getBalance(Wallet.BalanceType.ESTIMATED);
|
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAddress()
|
public String getAddress()
|
||||||
{
|
{
|
||||||
return getWallet().getKeys().get(0).toAddress(networkParameters).toString();
|
return wallet.getKeys().get(0).toAddress(params).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// account registration
|
public String payFee(BigInteger fee, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||||
|
{
|
||||||
|
Transaction tx = new Transaction(params);
|
||||||
|
//TransactionOutput output = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
|
||||||
|
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT, WalletUtil.getEmptyOP_RETURNScript());
|
||||||
|
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(tx);
|
||||||
|
|
||||||
|
// give fee to miners yet. Later it could be spent to other traders via lottery...
|
||||||
|
sendRequest.fee = fee;
|
||||||
|
|
||||||
|
Wallet.SendResult sendResult = wallet.sendCoins(sendRequest);
|
||||||
|
Futures.addCallback(sendResult.broadcastComplete, callback);
|
||||||
|
|
||||||
|
return tx.getHashAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Account registration
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Address getAccountRegistrationAddress()
|
public Address getAccountRegistrationAddress()
|
||||||
{
|
{
|
||||||
return getAccountRegistrationWallet().getAddress();
|
return getAccountRegistrationWallet().getAddress();
|
||||||
|
@ -155,7 +392,6 @@ public class WalletFacade implements WalletEventListener
|
||||||
|
|
||||||
public String getAccountRegistrationPubKey()
|
public String getAccountRegistrationPubKey()
|
||||||
{
|
{
|
||||||
|
|
||||||
return Utils.bytesToHexString(getAccountRegistrationWallet().getKey().getPubKey());
|
return Utils.bytesToHexString(getAccountRegistrationWallet().getKey().getPubKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,14 +405,9 @@ public class WalletFacade implements WalletEventListener
|
||||||
getAccountRegistrationWallet().saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(getAccountRegistrationWallet().getKey(), stringifiedBankAccounts));
|
getAccountRegistrationWallet().saveToBlockchain(cryptoFacade.getEmbeddedAccountRegistrationData(getAccountRegistrationWallet().getKey(), stringifiedBankAccounts));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean verifyAccountRegistration(String address, String hashAsHexStringToVerify, byte[] pubKey, String bankAccountIDs, String signatureBankAccountIDs)
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
{
|
// Getter
|
||||||
return true;
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
/*
|
|
||||||
return cryptoFacade.verifySignature(pubKey, bankAccountIDs, signatureBankAccountIDs)
|
|
||||||
&& cryptoFacade.verifyHash(hashAsHexStringToVerify, bankAccountIDs, signatureBankAccountIDs)
|
|
||||||
&& blockChainFacade.verifyEmbeddedData(address); */
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRegConfNumBroadcastPeers()
|
public int getRegConfNumBroadcastPeers()
|
||||||
{
|
{
|
||||||
|
@ -188,7 +419,16 @@ public class WalletFacade implements WalletEventListener
|
||||||
return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet());
|
return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet());
|
||||||
}
|
}
|
||||||
|
|
||||||
// WalletEventListener
|
public ECKey getAccountKey()
|
||||||
|
{
|
||||||
|
return getAccountRegistrationWallet().getKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: WalletEventListener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
|
||||||
{
|
{
|
||||||
|
@ -202,7 +442,7 @@ public class WalletFacade implements WalletEventListener
|
||||||
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
|
||||||
{
|
{
|
||||||
for (WalletListener walletListener : walletListeners)
|
for (WalletListener walletListener : walletListeners)
|
||||||
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(getWallet()));
|
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(wallet));
|
||||||
|
|
||||||
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
|
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
|
||||||
}
|
}
|
||||||
|
@ -238,61 +478,33 @@ public class WalletFacade implements WalletEventListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private AccountRegistrationWallet getAccountRegistrationWallet()
|
private AccountRegistrationWallet getAccountRegistrationWallet()
|
||||||
{
|
{
|
||||||
if (accountRegistrationWallet == null)
|
if (accountRegistrationWallet == null)
|
||||||
accountRegistrationWallet = new AccountRegistrationWallet(networkParameters, walletAppKit.chain(), walletAppKit.peerGroup());
|
accountRegistrationWallet = new AccountRegistrationWallet(params, walletAppKit.chain(), walletAppKit.peerGroup());
|
||||||
|
|
||||||
return accountRegistrationWallet;
|
return accountRegistrationWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String payOfferFee() throws InsufficientMoneyException
|
private Script getMultiSigScript(String offererPubKey, String takerPubKey, String arbitratorPubKey)
|
||||||
{
|
{
|
||||||
getWallet();
|
ECKey offererKey = new ECKey(null, Utils.parseAsHexOrBase58(offererPubKey));
|
||||||
|
ECKey takerKey = new ECKey(null, Utils.parseAsHexOrBase58(takerPubKey));
|
||||||
|
ECKey arbitratorKey = new ECKey(null, Utils.parseAsHexOrBase58(arbitratorPubKey));
|
||||||
|
|
||||||
Script script = new ScriptBuilder()
|
List<ECKey> keys = ImmutableList.of(offererKey, takerKey, arbitratorKey);
|
||||||
.op(OP_RETURN)
|
return ScriptBuilder.createMultiSigOutputScript(2, keys);
|
||||||
.build();
|
|
||||||
Transaction transaction = new Transaction(networkParameters);
|
|
||||||
TransactionOutput dataOutput = new TransactionOutput(networkParameters,
|
|
||||||
transaction,
|
|
||||||
Transaction.MIN_NONDUST_OUTPUT,
|
|
||||||
script.getProgram());
|
|
||||||
transaction.addOutput(dataOutput);
|
|
||||||
Wallet.SendRequest sendRequest = Wallet.SendRequest.forTx(transaction);
|
|
||||||
|
|
||||||
// give fee to miners yet. Later it could be spent to other traders via lottery...
|
|
||||||
sendRequest.fee = Fees.OFFER_CREATION_FEE;
|
|
||||||
|
|
||||||
Wallet.SendResult sendResult = getWallet().sendCoins(sendRequest);
|
|
||||||
|
|
||||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Transaction result)
|
|
||||||
{
|
|
||||||
log.info("sendResult onSuccess:" + result.toString());
|
|
||||||
// Platform.runLater(overlayUi::done);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t)
|
|
||||||
{
|
|
||||||
log.warn("sendResult onFailure:" + t.toString());
|
|
||||||
// We died trying to empty the wallet.
|
|
||||||
// crashAlert(t);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return transaction.getHashAsString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Wallet getWallet()
|
|
||||||
{
|
|
||||||
return walletAppKit.wallet();
|
|
||||||
}
|
|
||||||
|
|
||||||
// inner classes
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Inner classes
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private class BlockChainDownloadListener extends com.google.bitcoin.core.DownloadListener
|
private class BlockChainDownloadListener extends com.google.bitcoin.core.DownloadListener
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -326,5 +538,4 @@ public class WalletFacade implements WalletEventListener
|
||||||
void onCoinsReceived(BigInteger newBalance);
|
void onCoinsReceived(BigInteger newBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,10 +3,14 @@ package io.bitsquare.btc;
|
||||||
import com.google.bitcoin.core.Transaction;
|
import com.google.bitcoin.core.Transaction;
|
||||||
import com.google.bitcoin.core.TransactionConfidence;
|
import com.google.bitcoin.core.TransactionConfidence;
|
||||||
import com.google.bitcoin.core.Wallet;
|
import com.google.bitcoin.core.Wallet;
|
||||||
|
import com.google.bitcoin.script.Script;
|
||||||
|
import com.google.bitcoin.script.ScriptBuilder;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
|
||||||
|
|
||||||
public class WalletUtil
|
public class WalletUtil
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -41,4 +45,11 @@ public class WalletUtil
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Script getEmptyOP_RETURNScript()
|
||||||
|
{
|
||||||
|
return new ScriptBuilder()
|
||||||
|
.op(OP_RETURN)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,9 @@ public class CryptoFacade
|
||||||
return Utils.sha256hash160(concatenateChunks(stringifiedBankAccounts, signedBankAccountIDs).getBytes(Charsets.UTF_8));
|
return Utils.sha256hash160(concatenateChunks(stringifiedBankAccounts, signedBankAccountIDs).getBytes(Charsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String signContract(ECKey key, String contractAsJson)
|
||||||
// TODO MOCK
|
|
||||||
public String signContract(String contractAsJson)
|
|
||||||
{
|
{
|
||||||
return contractAsJson;
|
return key.signMessage(contractAsJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
// registration
|
// registration
|
||||||
|
|
|
@ -62,7 +62,7 @@ class WalletAppKitProvider implements Provider<WalletAppKit>
|
||||||
|
|
||||||
public WalletAppKit get()
|
public WalletAppKit get()
|
||||||
{
|
{
|
||||||
return new WalletAppKit(networkParameters, new File("."), "bitsquare");
|
return new WalletAppKit(networkParameters, new File("."), WalletFacade.WALLET_PREFIX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,12 @@ package io.bitsquare.gui;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.di.GuiceFXMLLoader;
|
import io.bitsquare.di.GuiceFXMLLoader;
|
||||||
import io.bitsquare.gui.components.NetworkSyncPane;
|
import io.bitsquare.gui.components.NetworkSyncPane;
|
||||||
import io.bitsquare.gui.market.MarketController;
|
import io.bitsquare.gui.market.MarketController;
|
||||||
import io.bitsquare.gui.setup.SetupController;
|
import io.bitsquare.gui.setup.SetupController;
|
||||||
import io.bitsquare.gui.util.Formatter;
|
|
||||||
import io.bitsquare.gui.util.Icons;
|
import io.bitsquare.gui.util.Icons;
|
||||||
import io.bitsquare.gui.util.Localisation;
|
import io.bitsquare.gui.util.Localisation;
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
|
@ -251,7 +251,7 @@ public class MainController implements Initializable, NavigationController, Wall
|
||||||
balanceLabel.setMouseTransparent(true);
|
balanceLabel.setMouseTransparent(true);
|
||||||
balanceLabel.setPrefWidth(90);
|
balanceLabel.setPrefWidth(90);
|
||||||
balanceLabel.setId("nav-balance-label");
|
balanceLabel.setId("nav-balance-label");
|
||||||
balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getBalance(), false));
|
balanceLabel.setText(BtcFormatter.formatSatoshis(walletFacade.getBalance(), false));
|
||||||
|
|
||||||
Label balanceCurrencyLabel = new Label("BTC");
|
Label balanceCurrencyLabel = new Label("BTC");
|
||||||
balanceCurrencyLabel.setPadding(new Insets(6, 0, 0, 0));
|
balanceCurrencyLabel.setPadding(new Insets(6, 0, 0, 0));
|
||||||
|
|
|
@ -3,10 +3,10 @@ package io.bitsquare.gui.funds;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
import io.bitsquare.gui.util.Formatter;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
|
@ -63,7 +63,7 @@ public class FundsController implements Initializable, ChildController
|
||||||
this.navigationController = navigationController;
|
this.navigationController = navigationController;
|
||||||
|
|
||||||
addressLabel.setText(walletFacade.getAddress());
|
addressLabel.setText(walletFacade.getAddress());
|
||||||
balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getBalance(), false));
|
balanceLabel.setText(BtcFormatter.formatSatoshis(walletFacade.getBalance(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package io.bitsquare.gui.market.offer;
|
package io.bitsquare.gui.market.offer;
|
||||||
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.btc.Fees;
|
import io.bitsquare.btc.Fees;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
|
@ -13,6 +16,7 @@ import io.bitsquare.trade.Direction;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
import io.bitsquare.trade.Trading;
|
import io.bitsquare.trade.Trading;
|
||||||
import io.bitsquare.trade.orderbook.OrderBookFilter;
|
import io.bitsquare.trade.orderbook.OrderBookFilter;
|
||||||
|
import io.bitsquare.user.Arbitrator;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
@ -22,10 +26,8 @@ import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import org.controlsfx.dialog.Dialogs;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -43,9 +45,11 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
private User user;
|
private User user;
|
||||||
private Direction direction;
|
private Direction direction;
|
||||||
|
private Offer offer;
|
||||||
|
private int gridRow;
|
||||||
|
|
||||||
private Button placeOfferButton;
|
private Button placeOfferButton;
|
||||||
private int gridRow;
|
private TextField collateralTextField, minAmountTextField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane holderPane;
|
private AnchorPane holderPane;
|
||||||
|
@ -54,7 +58,12 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
@FXML
|
@FXML
|
||||||
public Label buyLabel;
|
public Label buyLabel;
|
||||||
@FXML
|
@FXML
|
||||||
public TextField volume, amount, price, minAmount;
|
public TextField volumeTextField, amountTextField, priceTextField;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateOfferController(Trading trading, WalletFacade walletFacade, Settings settings, User user)
|
public CreateOfferController(Trading trading, WalletFacade walletFacade, Settings settings, User user)
|
||||||
|
@ -65,86 +74,51 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
this.user = user;
|
this.user = user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void setOrderBookFilter(OrderBookFilter orderBookFilter)
|
||||||
|
{
|
||||||
|
direction = orderBookFilter.getDirection();
|
||||||
|
amountTextField.setText(Formatter.formatPrice(orderBookFilter.getAmount()));
|
||||||
|
minAmountTextField.setText(Formatter.formatPrice(orderBookFilter.getAmount()));
|
||||||
|
priceTextField.setText(Formatter.formatPrice(orderBookFilter.getPrice()));
|
||||||
|
buyLabel.setText(Formatter.formatDirection(direction, false) + ":");
|
||||||
|
collateralTextField.setText(Formatter.formatVolume(settings.getMinCollateral()));
|
||||||
|
updateVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: Initializable
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb)
|
public void initialize(URL url, ResourceBundle rb)
|
||||||
{
|
{
|
||||||
walletFacade.addRegistrationWalletListener(this);
|
walletFacade.addRegistrationWalletListener(this);
|
||||||
|
|
||||||
gridRow = 2;
|
buildScreen();
|
||||||
FormBuilder.addVSpacer(formGridPane, ++gridRow);
|
|
||||||
FormBuilder.addHeaderLabel(formGridPane, "Offer details:", ++gridRow);
|
|
||||||
FormBuilder.addTextField(formGridPane, "Bank account type:", Localisation.get(user.getCurrentBankAccount().getBankAccountType().getType().toString()), ++gridRow);
|
|
||||||
FormBuilder.addTextField(formGridPane, "Bank account currency:", user.getCurrentBankAccount().getCurrency().getCurrencyCode(), ++gridRow);
|
|
||||||
FormBuilder.addTextField(formGridPane, "Bank account county:", user.getCurrentBankAccount().getCountryLocale().getDisplayCountry(), ++gridRow);
|
|
||||||
FormBuilder.addTextField(formGridPane, "Accepted countries:", Formatter.countryLocalesToString(settings.getAcceptedCountryLocales()), ++gridRow);
|
|
||||||
FormBuilder.addTextField(formGridPane, "Accepted languages:", Formatter.languageLocalesToString(settings.getAcceptedLanguageLocales()), ++gridRow);
|
|
||||||
|
|
||||||
FormBuilder.addVSpacer(formGridPane, ++gridRow);
|
|
||||||
Label placeOfferTitle = FormBuilder.addHeaderLabel(formGridPane, "Place offer:", ++gridRow);
|
|
||||||
|
|
||||||
TextField feeLabel = FormBuilder.addTextField(formGridPane, "Offer fee:", Formatter.formatSatoshis(Fees.OFFER_CREATION_FEE, true), ++gridRow);
|
|
||||||
feeLabel.setMouseTransparent(true);
|
|
||||||
|
|
||||||
placeOfferButton = new Button("Place offer");
|
|
||||||
formGridPane.add(placeOfferButton, 1, ++gridRow);
|
|
||||||
placeOfferButton.setDefaultButton(true);
|
|
||||||
|
|
||||||
// handlers
|
|
||||||
amount.textProperty().addListener(new ChangeListener<String>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
||||||
{
|
|
||||||
updateVolume();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
price.textProperty().addListener(new ChangeListener<String>()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
|
||||||
{
|
|
||||||
updateVolume();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
placeOfferButton.setOnAction(e -> {
|
|
||||||
|
|
||||||
if (inputValid())
|
|
||||||
{
|
|
||||||
Offer offer = new Offer(user.getAccountID(),
|
|
||||||
user.getMessageID(),
|
|
||||||
direction,
|
|
||||||
Converter.stringToDouble(price.getText()),
|
|
||||||
Converter.stringToDouble(amount.getText()),
|
|
||||||
Converter.stringToDouble(minAmount.getText()),
|
|
||||||
user.getCurrentBankAccount().getBankAccountType().getType(),
|
|
||||||
user.getCurrentBankAccount().getCurrency(),
|
|
||||||
user.getCurrentBankAccount().getCountryLocale(),
|
|
||||||
settings.getRandomArbitrator(),
|
|
||||||
settings.getAcceptedCountryLocales(),
|
|
||||||
settings.getAcceptedLanguageLocales());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String txID = trading.placeNewOffer(offer);
|
|
||||||
formGridPane.getChildren().remove(placeOfferButton);
|
|
||||||
placeOfferTitle.setText("Transaction sent:");
|
|
||||||
buildConfirmationView(txID);
|
|
||||||
} catch (InsufficientMoneyException e1)
|
|
||||||
{
|
|
||||||
Dialogs.create()
|
|
||||||
.title("Not enough money available")
|
|
||||||
.message("There is not enough money available. Please pay in first to your wallet.")
|
|
||||||
.nativeTitleBar()
|
|
||||||
.lightweight()
|
|
||||||
.showError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: ChildController
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNavigationController(NavigationController navigationController)
|
||||||
|
{
|
||||||
|
this.navigationController = navigationController;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface implementation: WalletFacade.WalletListener
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
|
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
|
||||||
{
|
{
|
||||||
|
@ -157,11 +131,119 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
log.info("onCoinsReceived " + newBalance);
|
log.info("onCoinsReceived " + newBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Private methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
private void buildScreen()
|
||||||
|
{
|
||||||
|
gridRow = 1;
|
||||||
|
minAmountTextField = FormBuilder.addTextField(formGridPane, "Min. Amount:", String.valueOf(settings.getMaxCollateral()), ++gridRow, true, true);
|
||||||
|
collateralTextField = FormBuilder.addTextField(formGridPane, "Collateral (%):", String.valueOf(settings.getMaxCollateral() * 100), ++gridRow, true, true);
|
||||||
|
|
||||||
|
FormBuilder.addVSpacer(formGridPane, ++gridRow);
|
||||||
|
FormBuilder.addHeaderLabel(formGridPane, "Offer details:", ++gridRow);
|
||||||
|
FormBuilder.addTextField(formGridPane, "Bank account type:", Localisation.get(user.getCurrentBankAccount().getBankAccountType().getType().toString()), ++gridRow);
|
||||||
|
FormBuilder.addTextField(formGridPane, "Bank account currency:", user.getCurrentBankAccount().getCurrency().getCurrencyCode(), ++gridRow);
|
||||||
|
FormBuilder.addTextField(formGridPane, "Bank account county:", user.getCurrentBankAccount().getCountryLocale().getDisplayCountry(), ++gridRow);
|
||||||
|
FormBuilder.addTextField(formGridPane, "Accepted countries:", Formatter.countryLocalesToString(settings.getAcceptedCountryLocales()), ++gridRow);
|
||||||
|
FormBuilder.addTextField(formGridPane, "Accepted languages:", Formatter.languageLocalesToString(settings.getAcceptedLanguageLocales()), ++gridRow);
|
||||||
|
|
||||||
|
FormBuilder.addVSpacer(formGridPane, ++gridRow);
|
||||||
|
Label placeOfferTitle = FormBuilder.addHeaderLabel(formGridPane, "Place offer:", ++gridRow);
|
||||||
|
|
||||||
|
TextField feeLabel = FormBuilder.addTextField(formGridPane, "Offer fee:", BtcFormatter.formatSatoshis(Fees.OFFER_CREATION_FEE, true), ++gridRow);
|
||||||
|
feeLabel.setMouseTransparent(true);
|
||||||
|
|
||||||
|
placeOfferButton = new Button("Place offer");
|
||||||
|
formGridPane.add(placeOfferButton, 1, ++gridRow);
|
||||||
|
placeOfferButton.setDefaultButton(true);
|
||||||
|
|
||||||
|
// handlers
|
||||||
|
amountTextField.textProperty().addListener(new ChangeListener<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
||||||
|
{
|
||||||
|
updateVolume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
priceTextField.textProperty().addListener(new ChangeListener<String>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
|
||||||
|
{
|
||||||
|
updateVolume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
placeOfferButton.setOnAction(e -> {
|
||||||
|
if (!inputValid())
|
||||||
|
{
|
||||||
|
Popups.openWarningPopup("Invalid input", "Your input is invalid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double collateralAsDouble = Converter.stringToDouble(collateralTextField.getText()) / 100;
|
||||||
|
Arbitrator arbitrator = settings.getRandomArbitrator(collateralAsDouble, getAmountAsBI());
|
||||||
|
if (arbitrator == null)
|
||||||
|
{
|
||||||
|
Popups.openWarningPopup("No arbitrator available", "No arbitrator from your arbitrator list does match the collateral and amount value.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
offer = new Offer(user.getAccountID(),
|
||||||
|
user.getMessageID(),
|
||||||
|
direction,
|
||||||
|
Converter.stringToDouble(priceTextField.getText()),
|
||||||
|
BtcFormatter.stringValueToSatoshis(amountTextField.getText()),
|
||||||
|
BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()),
|
||||||
|
user.getCurrentBankAccount().getBankAccountType().getType(),
|
||||||
|
user.getCurrentBankAccount().getCurrency(),
|
||||||
|
user.getCurrentBankAccount().getCountryLocale(),
|
||||||
|
arbitrator,
|
||||||
|
collateralAsDouble,
|
||||||
|
settings.getAcceptedCountryLocales(),
|
||||||
|
settings.getAcceptedLanguageLocales());
|
||||||
|
|
||||||
|
FutureCallback callback = new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.info("sendResult onSuccess:" + transaction.toString());
|
||||||
|
offer.setOfferPaymentTxID(transaction.getHashAsString());
|
||||||
|
buildConfirmationView(transaction.getHashAsString());
|
||||||
|
placeOfferTitle.setText("Transaction sent:");
|
||||||
|
formGridPane.getChildren().remove(placeOfferButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.warn("sendResult onFailure:" + t.toString());
|
||||||
|
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
trading.placeNewOffer(offer, callback);
|
||||||
|
|
||||||
|
} catch (InsufficientMoneyException e1)
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void buildConfirmationView(String txID)
|
private void buildConfirmationView(String txID)
|
||||||
{
|
{
|
||||||
FormBuilder.addTextField(formGridPane, "Transaction ID:", txID, ++gridRow, false, true);
|
FormBuilder.addTextField(formGridPane, "Transaction ID:", txID, ++gridRow, false, true);
|
||||||
|
|
||||||
ConfirmationComponent confirmationComponent = new ConfirmationComponent(walletFacade, formGridPane, ++gridRow);
|
new ConfirmationComponent(walletFacade, formGridPane, ++gridRow);
|
||||||
|
|
||||||
Button closeButton = new Button("Close");
|
Button closeButton = new Button("Close");
|
||||||
formGridPane.add(closeButton, 1, ++gridRow);
|
formGridPane.add(closeButton, 1, ++gridRow);
|
||||||
|
@ -176,50 +258,36 @@ public class CreateOfferController implements Initializable, ChildController, Wa
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setNavigationController(NavigationController navigationController)
|
|
||||||
{
|
|
||||||
this.navigationController = navigationController;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderBookFilter(OrderBookFilter orderBookFilter)
|
|
||||||
{
|
|
||||||
direction = orderBookFilter.getDirection();
|
|
||||||
amount.setText(Formatter.formatPrice(orderBookFilter.getAmount()));
|
|
||||||
minAmount.setText(Formatter.formatPrice(orderBookFilter.getAmount()));
|
|
||||||
price.setText(Formatter.formatPrice(orderBookFilter.getPrice()));
|
|
||||||
|
|
||||||
String iconPath = (direction == Direction.BUY) ? Icons.BUY : Icons.SELL;
|
|
||||||
buyLabel.setText(Formatter.formatDirection(direction, false) + ":");
|
|
||||||
updateVolume();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO
|
|
||||||
private boolean inputValid()
|
private boolean inputValid()
|
||||||
{
|
{
|
||||||
return true;
|
double priceAsDouble = Converter.stringToDouble(priceTextField.getText());
|
||||||
|
double minAmountAsDouble = Converter.stringToDouble(minAmountTextField.getText());
|
||||||
|
double amountAsDouble = Converter.stringToDouble(amountTextField.getText());
|
||||||
|
double collateralAsDouble = Converter.stringToDouble(collateralTextField.getText());
|
||||||
|
|
||||||
|
return priceAsDouble > 0 &&
|
||||||
|
amountAsDouble > 0 &&
|
||||||
|
minAmountAsDouble > 0 &&
|
||||||
|
minAmountAsDouble <= amountAsDouble &&
|
||||||
|
collateralAsDouble >= settings.getMinCollateral() &&
|
||||||
|
collateralAsDouble <= settings.getMaxCollateral();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateVolume()
|
private void updateVolume()
|
||||||
{
|
{
|
||||||
double amountAsDouble = Converter.stringToDouble(amount.getText());
|
volumeTextField.setText(Formatter.formatVolume(getVolume()));
|
||||||
double priceAsDouble = Converter.stringToDouble(price.getText());
|
|
||||||
volume.setText(Formatter.formatPrice(amountAsDouble * priceAsDouble));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
|
private double getVolume()
|
||||||
{
|
{
|
||||||
if (depthInBlocks > 0)
|
double amountAsDouble = Converter.stringToDouble(amountTextField.getText());
|
||||||
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
|
double priceAsDouble = Converter.stringToDouble(priceTextField.getText());
|
||||||
else
|
return amountAsDouble * priceAsDouble;
|
||||||
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks)
|
private BigInteger getAmountAsBI()
|
||||||
{
|
{
|
||||||
return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)";
|
return BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,45 +6,34 @@
|
||||||
<AnchorPane fx:id="holderPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
<AnchorPane fx:id="holderPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns:fx="http://javafx.com/fxml/1"
|
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="io.bitsquare.gui.market.offer.CreateOfferController">
|
fx:controller="io.bitsquare.gui.market.offer.CreateOfferController">
|
||||||
<children>
|
<VBox spacing="10" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"
|
||||||
<VBox spacing="10" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"
|
AnchorPane.bottomAnchor="10.0">
|
||||||
AnchorPane.bottomAnchor="10.0">
|
<GridPane fx:id="formGridPane" vgap="5" hgap="5">
|
||||||
<GridPane fx:id="formGridPane" vgap="5" hgap="5">
|
<Label id="form-header-text" text="Create new offer:" GridPane.rowIndex="0"
|
||||||
<children>
|
GridPane.columnIndex="0"/>
|
||||||
<Label id="form-header-text" text="Create new offer:" GridPane.rowIndex="0"
|
|
||||||
GridPane.columnIndex="0"/>
|
|
||||||
|
|
||||||
<Label fx:id="buyLabel" text="Buy" GridPane.rowIndex="1" GridPane.columnIndex="0"/>
|
<Label fx:id="buyLabel" text="Buy" GridPane.rowIndex="1" GridPane.columnIndex="0"/>
|
||||||
|
|
||||||
<HBox GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.hgrow="NEVER" spacing="5"
|
<HBox GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.hgrow="NEVER" spacing="5"
|
||||||
alignment="CENTER_RIGHT">
|
alignment="CENTER_RIGHT">
|
||||||
<children>
|
<TextField fx:id="amountTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||||
<TextField fx:id="amount" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
<Label text="BTC for:"/>
|
||||||
<Label text="BTC for:"/>
|
<TextField fx:id="priceTextField" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
||||||
<TextField fx:id="price" prefWidth="70.0" alignment="CENTER_RIGHT"/>
|
<Label text="EUR ="/>
|
||||||
<Label text="EUR ="/>
|
<TextField fx:id="volumeTextField" prefWidth="70.0" alignment="CENTER_RIGHT" editable="false"
|
||||||
<TextField fx:id="volume" prefWidth="70.0" alignment="CENTER_RIGHT"
|
mouseTransparent="true"/>
|
||||||
mouseTransparent="true"/>
|
<Label text="EUR in total"/>
|
||||||
<Label text="EUR in total"/>
|
</HBox>
|
||||||
</children>
|
|
||||||
</HBox>
|
|
||||||
|
|
||||||
<Label text="Min. Amount:" GridPane.rowIndex="2" GridPane.columnIndex="0"/>
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||||
|
</padding>
|
||||||
|
|
||||||
<TextField fx:id="minAmount" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
|
<columnConstraints>
|
||||||
|
<ColumnConstraints halignment="RIGHT"/>
|
||||||
</children>
|
<ColumnConstraints halignment="LEFT"/>
|
||||||
|
<ColumnConstraints halignment="LEFT"/>
|
||||||
<padding>
|
</columnConstraints>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
</GridPane>
|
||||||
</padding>
|
</VBox>
|
||||||
|
|
||||||
<columnConstraints>
|
|
||||||
<ColumnConstraints halignment="RIGHT"/>
|
|
||||||
<ColumnConstraints halignment="LEFT"/>
|
|
||||||
<ColumnConstraints halignment="LEFT"/>
|
|
||||||
</columnConstraints>
|
|
||||||
</GridPane>
|
|
||||||
</VBox>
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
|
|
@ -2,6 +2,7 @@ package io.bitsquare.gui.market.orderbook;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.bank.BankAccountType;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
import io.bitsquare.gui.market.offer.CreateOfferController;
|
import io.bitsquare.gui.market.offer.CreateOfferController;
|
||||||
|
@ -30,6 +31,7 @@ import javafx.util.Callback;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
@ -155,9 +157,9 @@ public class OrderBookController implements Initializable, ChildController
|
||||||
String title = orderBookListItem.getOffer().getDirection() == Direction.BUY ? "Trade: Sell Bitcoin" : "Trade: Buy Bitcoin";
|
String title = orderBookListItem.getOffer().getDirection() == Direction.BUY ? "Trade: Sell Bitcoin" : "Trade: Buy Bitcoin";
|
||||||
TradeController tradeController = (TradeController) navigationController.navigateToView(NavigationController.TRADE, title);
|
TradeController tradeController = (TradeController) navigationController.navigateToView(NavigationController.TRADE, title);
|
||||||
|
|
||||||
double requestedAmount = orderBookListItem.getOffer().getAmount();
|
BigInteger requestedAmount = orderBookListItem.getOffer().getAmount();
|
||||||
if (!amount.getText().equals(""))
|
if (!amount.getText().equals(""))
|
||||||
requestedAmount = Converter.stringToDouble(amount.getText());
|
requestedAmount = BtcFormatter.stringValueToSatoshis(amount.getText());
|
||||||
|
|
||||||
tradeController.initWithData(orderBookListItem.getOffer(), requestedAmount);
|
tradeController.initWithData(orderBookListItem.getOffer(), requestedAmount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class OrderBookListItem
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
|
|
||||||
this.price.set(Formatter.formatPrice(offer.getPrice()));
|
this.price.set(Formatter.formatPrice(offer.getPrice()));
|
||||||
this.amount.set(Formatter.formatAmountWithMinAmount(offer.getAmount(), offer.getMinAmount()));
|
this.amount.set(Formatter.formatAmountWithMinAmount(offer.getAmount().doubleValue(), offer.getMinAmount().doubleValue()));
|
||||||
this.volume.set(Formatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume()));
|
this.volume.set(Formatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package io.bitsquare.gui.market.trade;
|
package io.bitsquare.gui.market.trade;
|
||||||
|
|
||||||
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
|
@ -23,7 +26,6 @@ import javafx.scene.control.*;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import org.controlsfx.dialog.Dialogs;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -36,7 +38,7 @@ import java.util.ResourceBundle;
|
||||||
public class TradeController implements Initializable, ChildController, WalletFacade.WalletListener
|
public class TradeController implements Initializable, ChildController, WalletFacade.WalletListener
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(TradeController.class);
|
private static final Logger log = LoggerFactory.getLogger(TradeController.class);
|
||||||
private static final int SIM_DELAY = 1000;
|
private static final int SIM_DELAY = 2000;
|
||||||
|
|
||||||
private Trading trading;
|
private Trading trading;
|
||||||
private WalletFacade walletFacade;
|
private WalletFacade walletFacade;
|
||||||
|
@ -44,14 +46,14 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
private Offer offer;
|
private Offer offer;
|
||||||
private Trade trade;
|
private Trade trade;
|
||||||
private Contract contract;
|
private Contract contract;
|
||||||
private double requestedAmount;
|
private BigInteger requestedAmount;
|
||||||
private boolean offererIsOnline;
|
private boolean offererIsOnline;
|
||||||
private int row;
|
private int row;
|
||||||
|
|
||||||
private List<ProcessStepItem> processStepItems = new ArrayList();
|
private List<ProcessStepItem> processStepItems = new ArrayList();
|
||||||
|
|
||||||
private NavigationController navigationController;
|
private NavigationController navigationController;
|
||||||
private TextField amountTextField, totalToPayLabel, totalLabel;
|
private TextField amountTextField, totalToPayLabel, totalLabel, collateralTextField;
|
||||||
private Label statusTextField, infoLabel;
|
private Label statusTextField, infoLabel;
|
||||||
private Button nextButton;
|
private Button nextButton;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
|
@ -81,14 +83,14 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
// Public methods
|
// Public methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public void initWithData(Offer offer, double requestedAmount)
|
public void initWithData(Offer offer, BigInteger requestedAmount)
|
||||||
{
|
{
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
this.requestedAmount = requestedAmount > 0 ? requestedAmount : offer.getAmount();
|
this.requestedAmount = requestedAmount.compareTo(BigInteger.ZERO) > 0 ? requestedAmount : offer.getAmount();
|
||||||
|
|
||||||
trade = trading.createNewTrade(offer);
|
trade = trading.createTrade(offer);
|
||||||
trade.setTradeAmount(requestedAmount);
|
trade.setTradeAmount(requestedAmount);
|
||||||
contract = trading.createNewContract(trade);
|
contract = trading.createContract(trade);
|
||||||
|
|
||||||
processStepItems.add(new ProcessStepItem(takerIsSelling() ? "Sell BTC" : "Buy BTC"));
|
processStepItems.add(new ProcessStepItem(takerIsSelling() ? "Sell BTC" : "Buy BTC"));
|
||||||
processStepItems.add(new ProcessStepItem("Bank transfer"));
|
processStepItems.add(new ProcessStepItem("Bank transfer"));
|
||||||
|
@ -148,19 +150,22 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
row = -1;
|
row = -1;
|
||||||
|
|
||||||
FormBuilder.addHeaderLabel(gridPane, "Take offer:", ++row);
|
FormBuilder.addHeaderLabel(gridPane, "Take offer:", ++row);
|
||||||
amountTextField = FormBuilder.addTextField(gridPane, "Amount BTC:", Formatter.formatAmount(requestedAmount), ++row, true, true);
|
amountTextField = FormBuilder.addTextField(gridPane, "Amount (BTC):", BtcFormatter.formatSatoshis(requestedAmount, false), ++row, true, true);
|
||||||
amountTextField.textProperty().addListener(e -> {
|
amountTextField.textProperty().addListener(e -> {
|
||||||
applyVolume();
|
applyVolume();
|
||||||
|
applyCollateral();
|
||||||
totalToPayLabel.setText(getTotalToPay());
|
totalToPayLabel.setText(getTotalToPay());
|
||||||
|
|
||||||
});
|
});
|
||||||
Label amountRangeLabel = new Label("(" + Formatter.formatAmount(offer.getMinAmount()) + " - " + Formatter.formatAmount(offer.getAmount()) + ")");
|
Label amountRangeLabel = new Label("(" + BtcFormatter.formatSatoshis(offer.getMinAmount(), false) + " - " + BtcFormatter.formatSatoshis(offer.getAmount(), false) + ")");
|
||||||
gridPane.add(amountRangeLabel, 2, row);
|
gridPane.add(amountRangeLabel, 2, row);
|
||||||
|
|
||||||
FormBuilder.addTextField(gridPane, "Price:", Formatter.formatPriceWithCurrencyPair(offer.getPrice(), offer.getCurrency()), ++row);
|
FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", Formatter.formatPrice(offer.getPrice()), ++row);
|
||||||
totalLabel = FormBuilder.addTextField(gridPane, "Total:", Formatter.formatVolume(getVolume(), offer.getCurrency()), ++row);
|
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "Offer fee:", Formatter.formatSatoshis(Fees.OFFER_TAKER_FEE, true), ++row);
|
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
|
||||||
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay:", getTotalToPay(), ++row);
|
applyCollateral();
|
||||||
|
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE, false), ++row);
|
||||||
|
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row);
|
||||||
|
|
||||||
nextButton = FormBuilder.addButton(gridPane, "Take offer and pay", ++row);
|
nextButton = FormBuilder.addButton(gridPane, "Take offer and pay", ++row);
|
||||||
nextButton.setDefaultButton(true);
|
nextButton.setDefaultButton(true);
|
||||||
|
@ -247,9 +252,9 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
progressIndicatorHolder.getChildren().addAll(progressIndicator);
|
||||||
gridPane.add(progressIndicatorHolder, 1, row);
|
gridPane.add(progressIndicatorHolder, 1, row);
|
||||||
|
|
||||||
trade.setTradeAmount(Converter.stringToDouble(amountTextField.getText()));
|
trade.setTradeAmount(BtcFormatter.stringValueToSatoshis(amountTextField.getText()));
|
||||||
trading.sendTakeOfferRequest(trade);
|
|
||||||
|
|
||||||
|
trading.sendTakeOfferRequest(trade);
|
||||||
Utils.setTimeout(SIM_DELAY, (AnimationTimer animationTimer) -> {
|
Utils.setTimeout(SIM_DELAY, (AnimationTimer animationTimer) -> {
|
||||||
onTakeOfferRequestConfirmed();
|
onTakeOfferRequestConfirmed();
|
||||||
progressBar.setProgress(1.0 / 3.0);
|
progressBar.setProgress(1.0 / 3.0);
|
||||||
|
@ -259,14 +264,37 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
private void onTakeOfferRequestConfirmed()
|
private void onTakeOfferRequestConfirmed()
|
||||||
{
|
{
|
||||||
trading.payOfferFee(trade);
|
FutureCallback callback = new FutureCallback<Transaction>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Transaction transaction)
|
||||||
|
{
|
||||||
|
log.info("sendResult onSuccess:" + transaction.toString());
|
||||||
|
trade.setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||||
|
|
||||||
statusTextField.setText("Offer fee payed. Send offerer payment transaction ID for confirmation.");
|
statusTextField.setText("Offer fee payed. Send offerer payment transaction ID for confirmation.");
|
||||||
Utils.setTimeout(SIM_DELAY, (AnimationTimer animationTimer) -> {
|
Utils.setTimeout(SIM_DELAY, (AnimationTimer animationTimer) -> {
|
||||||
onOfferFeePaymentConfirmed();
|
onOfferFeePaymentConfirmed();
|
||||||
progressBar.setProgress(2.0 / 3.0);
|
progressBar.setProgress(2.0 / 3.0);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t)
|
||||||
|
{
|
||||||
|
log.warn("sendResult onFailure:" + t.toString());
|
||||||
|
Popups.openErrorPopup("Fee payment failed", "Fee payment failed. " + t.toString());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
trading.payOfferFee(trade, callback);
|
||||||
|
} catch (InsufficientMoneyException e)
|
||||||
|
{
|
||||||
|
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onOfferFeePaymentConfirmed()
|
private void onOfferFeePaymentConfirmed()
|
||||||
|
@ -282,14 +310,10 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
private void onUserDetailsReceived()
|
private void onUserDetailsReceived()
|
||||||
{
|
{
|
||||||
if (!walletFacade.verifyAccountRegistration(offer.getAccountID(), null, null, null, null))
|
if (!blockChainFacade.verifyEmbeddedData(offer.getAccountID()))
|
||||||
{
|
{
|
||||||
Dialogs.create()
|
Popups.openErrorPopup("Offerers bank account is blacklisted", "Offerers bank account is blacklisted.");
|
||||||
.title("Offerers bank account is blacklisted")
|
return;
|
||||||
.message("Offerers bank account is blacklisted.")
|
|
||||||
.nativeTitleBar()
|
|
||||||
.lightweight()
|
|
||||||
.showError();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trading.signContract(contract);
|
trading.signContract(contract);
|
||||||
|
@ -337,8 +361,19 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
gridPane.getChildren().clear();
|
gridPane.getChildren().clear();
|
||||||
row = -1;
|
row = -1;
|
||||||
FormBuilder.addHeaderLabel(gridPane, "Trade successfully completed", ++row);
|
FormBuilder.addHeaderLabel(gridPane, "Trade successfully completed", ++row);
|
||||||
FormBuilder.addTextField(gridPane, "You have payed:", getTotalToPay(), ++row);
|
FormBuilder.addTextField(gridPane, "You have payed in total (BTC):", getTotalToPay(), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "You have received:", getTotalToReceive(), ++row);
|
if (takerIsSelling())
|
||||||
|
{
|
||||||
|
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row);
|
||||||
|
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row);
|
||||||
|
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row);
|
||||||
|
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount(), false), ++row);
|
||||||
|
}
|
||||||
|
|
||||||
gridPane.add(nextButton, 1, ++row);
|
gridPane.add(nextButton, 1, ++row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,8 +390,8 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
// Other Private methods
|
// Other Private methods
|
||||||
private boolean tradeAmountValid()
|
private boolean tradeAmountValid()
|
||||||
{
|
{
|
||||||
double tradeAmount = Converter.stringToDouble(amountTextField.getText());
|
BigInteger tradeAmount = BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||||
return tradeAmount <= offer.getAmount() && tradeAmount >= offer.getMinAmount();
|
return tradeAmount.compareTo(offer.getAmount()) <= 0 && tradeAmount.compareTo(offer.getMinAmount()) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean takerIsSelling()
|
private boolean takerIsSelling()
|
||||||
|
@ -388,28 +423,31 @@ public class TradeController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
private String getTotalToPay()
|
private String getTotalToPay()
|
||||||
{
|
{
|
||||||
String result = "";
|
|
||||||
if (takerIsSelling())
|
if (takerIsSelling())
|
||||||
{
|
{
|
||||||
double btcValue = Converter.stringToDouble(amountTextField.getText()) + BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE)/* +
|
return BtcFormatter.formatSatoshis(getAmountInSatoshis().add(Fees.OFFER_TAKER_FEE).add(getCollateralInSatoshis()), false);
|
||||||
offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText())*/;
|
|
||||||
result = Formatter.formatAmount(btcValue, true, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double btcValue = BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE) /*+ offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText())*/;
|
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(getCollateralInSatoshis()), false) + "\n" +
|
||||||
result = Formatter.formatAmount(btcValue, true, true) + "\n" + Formatter.formatVolume(getVolume(), offer.getCurrency());
|
Formatter.formatVolume(getVolume(), offer.getCurrency());
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTotalToReceive()
|
|
||||||
|
private void applyCollateral()
|
||||||
{
|
{
|
||||||
if (takerIsSelling())
|
collateralTextField.setText(BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false));
|
||||||
return Formatter.formatVolume(getVolume(), offer.getCurrency());
|
|
||||||
else
|
|
||||||
return Formatter.formatAmount(offer.getAmount(), true, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigInteger getCollateralInSatoshis()
|
||||||
|
{
|
||||||
|
return BtcFormatter.doubleValueToSatoshis(Converter.stringToDouble(amountTextField.getText()) * offer.getCollateral());
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigInteger getAmountInSatoshis()
|
||||||
|
{
|
||||||
|
return BtcFormatter.stringValueToSatoshis(amountTextField.getText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,24 +9,14 @@ public class MockDelay
|
||||||
{
|
{
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
Future<String> future = executor.submit(new Task(expectedMsg));
|
Future<String> future = executor.submit(new Task(expectedMsg));
|
||||||
|
// max timeout 5 sec
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
try
|
return future.get(5, TimeUnit.SECONDS);
|
||||||
{
|
} catch (InterruptedException | TimeoutException | ExecutionException e)
|
||||||
// max timeout 5 sec
|
|
||||||
return future.get(5, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (ExecutionException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
} catch (TimeoutException e)
|
|
||||||
{
|
{
|
||||||
System.out.println("Terminated!");
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import de.jensd.fx.fontawesome.AwesomeDude;
|
||||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||||
import io.bitsquare.bank.BankAccount;
|
import io.bitsquare.bank.BankAccount;
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.bank.BankAccountType;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.gui.ChildController;
|
import io.bitsquare.gui.ChildController;
|
||||||
import io.bitsquare.gui.NavigationController;
|
import io.bitsquare.gui.NavigationController;
|
||||||
|
@ -14,8 +15,8 @@ import io.bitsquare.gui.components.NetworkSyncPane;
|
||||||
import io.bitsquare.gui.components.processbar.ProcessStepBar;
|
import io.bitsquare.gui.components.processbar.ProcessStepBar;
|
||||||
import io.bitsquare.gui.components.processbar.ProcessStepItem;
|
import io.bitsquare.gui.components.processbar.ProcessStepItem;
|
||||||
import io.bitsquare.gui.util.FormBuilder;
|
import io.bitsquare.gui.util.FormBuilder;
|
||||||
import io.bitsquare.gui.util.Formatter;
|
|
||||||
import io.bitsquare.gui.util.Localisation;
|
import io.bitsquare.gui.util.Localisation;
|
||||||
|
import io.bitsquare.gui.util.Popups;
|
||||||
import io.bitsquare.gui.util.Verification;
|
import io.bitsquare.gui.util.Verification;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
|
@ -29,7 +30,6 @@ import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
import org.controlsfx.dialog.Dialogs;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -41,13 +41,15 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(SetupController.class);
|
private static final Logger log = LoggerFactory.getLogger(SetupController.class);
|
||||||
|
|
||||||
private User user;
|
private final User user;
|
||||||
private final WalletFacade walletFacade;
|
private final WalletFacade walletFacade;
|
||||||
private Storage storage;
|
private final Storage storage;
|
||||||
private List<ProcessStepItem> processStepItems = new ArrayList();
|
private final List<ProcessStepItem> processStepItems = new ArrayList<>();
|
||||||
private NavigationController navigationController;
|
private NavigationController navigationController;
|
||||||
private TextField balanceLabel, accountTitle, accountHolderName, accountPrimaryID, accountSecondaryID;
|
private TextField balanceLabel, accountTitle, accountHolderName, accountPrimaryID, accountSecondaryID;
|
||||||
private ComboBox countryComboBox, bankTransferTypeComboBox, currencyComboBox;
|
private ComboBox<Locale> countryComboBox;
|
||||||
|
private ComboBox<BankAccountType> bankTransferTypeComboBox;
|
||||||
|
private ComboBox<Currency> currencyComboBox;
|
||||||
private Button addBankAccountButton;
|
private Button addBankAccountButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -133,7 +135,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
public void onCoinsReceived(BigInteger newBalance)
|
public void onCoinsReceived(BigInteger newBalance)
|
||||||
{
|
{
|
||||||
updateCreateAccountButton();
|
updateCreateAccountButton();
|
||||||
balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true));
|
balanceLabel.setText(BtcFormatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true));
|
||||||
log.info("onCoinsReceived " + newBalance);
|
log.info("onCoinsReceived " + newBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +163,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
|
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
|
||||||
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
|
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
|
||||||
|
|
||||||
balanceLabel = FormBuilder.addTextField(gridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row);
|
balanceLabel = FormBuilder.addTextField(gridPane, "Balance:", BtcFormatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row);
|
||||||
|
|
||||||
new ConfirmationComponent(walletFacade, gridPane, ++row);
|
new ConfirmationComponent(walletFacade, gridPane, ++row);
|
||||||
|
|
||||||
|
@ -194,7 +196,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
gridPane.getChildren().clear();
|
gridPane.getChildren().clear();
|
||||||
int row = -1;
|
int row = -1;
|
||||||
bankTransferTypeComboBox = FormBuilder.addComboBox(gridPane, "Bank account type:", Utils.getAllBankAccountTypes(), ++row);
|
bankTransferTypeComboBox = FormBuilder.addBankAccountComboBox(gridPane, "Bank account type:", Utils.getAllBankAccountTypes(), ++row);
|
||||||
bankTransferTypeComboBox.setConverter(new StringConverter<BankAccountType>()
|
bankTransferTypeComboBox.setConverter(new StringConverter<BankAccountType>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -216,7 +218,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
accountPrimaryID = FormBuilder.addInputField(gridPane, "Bank account primary ID", "", ++row);
|
accountPrimaryID = FormBuilder.addInputField(gridPane, "Bank account primary ID", "", ++row);
|
||||||
accountSecondaryID = FormBuilder.addInputField(gridPane, "Bank account secondary ID:", "", ++row);
|
accountSecondaryID = FormBuilder.addInputField(gridPane, "Bank account secondary ID:", "", ++row);
|
||||||
|
|
||||||
currencyComboBox = FormBuilder.addComboBox(gridPane, "Currency used for bank account:", Utils.getAllCurrencies(), ++row);
|
currencyComboBox = FormBuilder.addCurrencyComboBox(gridPane, "Currency used for bank account:", Utils.getAllCurrencies(), ++row);
|
||||||
currencyComboBox.setPromptText("Select currency");
|
currencyComboBox.setPromptText("Select currency");
|
||||||
currencyComboBox.setConverter(new StringConverter<Currency>()
|
currencyComboBox.setConverter(new StringConverter<Currency>()
|
||||||
{
|
{
|
||||||
|
@ -233,7 +235,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
countryComboBox = FormBuilder.addComboBox(gridPane, "Country of bank account:", Utils.getAllLocales(), ++row);
|
countryComboBox = FormBuilder.addLocalesComboBox(gridPane, "Country of bank account:", Utils.getAllLocales(), ++row);
|
||||||
countryComboBox.setPromptText("Select country");
|
countryComboBox.setPromptText("Select country");
|
||||||
countryComboBox.setConverter(new StringConverter<Locale>()
|
countryComboBox.setConverter(new StringConverter<Locale>()
|
||||||
{
|
{
|
||||||
|
@ -267,11 +269,10 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
bankTransferTypeComboBox.valueProperty().addListener((ov, oldValue, newValue) -> {
|
bankTransferTypeComboBox.valueProperty().addListener((ov, oldValue, newValue) -> {
|
||||||
if (newValue != null && newValue instanceof BankAccountType)
|
if (newValue != null && newValue instanceof BankAccountType)
|
||||||
{
|
{
|
||||||
BankAccountType bankAccountType = (BankAccountType) newValue;
|
|
||||||
accountPrimaryID.setText("");
|
accountPrimaryID.setText("");
|
||||||
accountPrimaryID.setPromptText(bankAccountType.getPrimaryIDName());
|
accountPrimaryID.setPromptText(newValue.getPrimaryIDName());
|
||||||
accountSecondaryID.setText("");
|
accountSecondaryID.setText("");
|
||||||
accountSecondaryID.setPromptText(bankAccountType.getSecondaryIDName());
|
accountSecondaryID.setPromptText(newValue.getSecondaryIDName());
|
||||||
|
|
||||||
checkCreateAccountButtonState();
|
checkCreateAccountButtonState();
|
||||||
}
|
}
|
||||||
|
@ -303,19 +304,14 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
{
|
{
|
||||||
walletFacade.sendRegistrationTx(user.getStringifiedBankAccounts());
|
walletFacade.sendRegistrationTx(user.getStringifiedBankAccounts());
|
||||||
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
|
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
|
||||||
user.setMessageID(walletFacade.getAccountRegistrationPubKey().toString());
|
user.setMessageID(walletFacade.getAccountRegistrationPubKey());
|
||||||
|
|
||||||
storage.write(user.getClass().getName(), user);
|
storage.write(user.getClass().getName(), user);
|
||||||
processStepBar.next();
|
processStepBar.next();
|
||||||
buildStep2();
|
buildStep2();
|
||||||
} catch (InsufficientMoneyException e1)
|
} catch (InsufficientMoneyException e1)
|
||||||
{
|
{
|
||||||
Dialogs.create()
|
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
|
||||||
.title("Not enough money available")
|
|
||||||
.message("There is not enough money available. Please pay in first to your wallet.")
|
|
||||||
.nativeTitleBar()
|
|
||||||
.lightweight()
|
|
||||||
.showError();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -334,7 +330,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
|
|
||||||
FormBuilder.addHeaderLabel(gridPane, "Registration complete", ++row);
|
FormBuilder.addHeaderLabel(gridPane, "Registration complete", ++row);
|
||||||
FormBuilder.addTextField(gridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++row);
|
FormBuilder.addTextField(gridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++row);
|
||||||
FormBuilder.addTextField(gridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row);
|
FormBuilder.addTextField(gridPane, "Balance:", BtcFormatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++row);
|
||||||
|
|
||||||
Button closeButton = FormBuilder.addButton(gridPane, "Close", ++row);
|
Button closeButton = FormBuilder.addButton(gridPane, "Close", ++row);
|
||||||
closeButton.setDefaultButton(true);
|
closeButton.setDefaultButton(true);
|
||||||
|
@ -409,9 +405,9 @@ public class SetupController implements Initializable, ChildController, WalletFa
|
||||||
if (verifyBankAccountData())
|
if (verifyBankAccountData())
|
||||||
{
|
{
|
||||||
BankAccount bankAccount = new BankAccount(
|
BankAccount bankAccount = new BankAccount(
|
||||||
(BankAccountType) bankTransferTypeComboBox.getSelectionModel().getSelectedItem(),
|
bankTransferTypeComboBox.getSelectionModel().getSelectedItem(),
|
||||||
(Currency) currencyComboBox.getSelectionModel().getSelectedItem(),
|
currencyComboBox.getSelectionModel().getSelectedItem(),
|
||||||
(Locale) countryComboBox.getSelectionModel().getSelectedItem(),
|
countryComboBox.getSelectionModel().getSelectedItem(),
|
||||||
accountTitle.getText(),
|
accountTitle.getText(),
|
||||||
accountHolderName.getText(),
|
accountHolderName.getText(),
|
||||||
accountPrimaryID.getText(),
|
accountPrimaryID.getText(),
|
||||||
|
|
|
@ -7,25 +7,23 @@
|
||||||
xmlns:fx="http://javafx.com/fxml">
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
<ScrollPane fitToWidth="true" AnchorPane.leftAnchor="10" AnchorPane.rightAnchor="10" AnchorPane.topAnchor="10"
|
<ScrollPane fitToWidth="true" AnchorPane.leftAnchor="10" AnchorPane.rightAnchor="10" AnchorPane.topAnchor="10"
|
||||||
AnchorPane.bottomAnchor="30">
|
AnchorPane.bottomAnchor="30">
|
||||||
<content>
|
<VBox fx:id="vBox" spacing="10">
|
||||||
<VBox fx:id="vBox" spacing="10">
|
<Label text="Setup trading account" id="headline-label"/>
|
||||||
<Label text="Setup trading account" id="headline-label"/>
|
<ProcessStepBar fx:id="processStepBar"/>
|
||||||
<ProcessStepBar fx:id="processStepBar"/>
|
<VSpacer prefHeight="10"/>
|
||||||
<VSpacer prefHeight="10"/>
|
<Label fx:id="infoLabel"/>
|
||||||
<Label fx:id="infoLabel"/>
|
<GridPane fx:id="gridPane" vgap="5" hgap="5">
|
||||||
<GridPane fx:id="gridPane" vgap="5" hgap="5">
|
<padding>
|
||||||
<padding>
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
|
</padding>
|
||||||
</padding>
|
<columnConstraints>
|
||||||
<columnConstraints>
|
<ColumnConstraints halignment="RIGHT"/>
|
||||||
<ColumnConstraints halignment="RIGHT"/>
|
<ColumnConstraints halignment="LEFT" prefWidth="320"/>
|
||||||
<ColumnConstraints halignment="LEFT" prefWidth="320"/>
|
<ColumnConstraints halignment="LEFT"/>
|
||||||
<ColumnConstraints halignment="LEFT"/>
|
</columnConstraints>
|
||||||
</columnConstraints>
|
</GridPane>
|
||||||
</GridPane>
|
<Button fx:id="nextButton" defaultButton="true"/>
|
||||||
<Button fx:id="nextButton" defaultButton="true"/>
|
<Button fx:id="skipButton"/>
|
||||||
<Button fx:id="skipButton"/>
|
</VBox>
|
||||||
</VBox>
|
|
||||||
</content>
|
|
||||||
</ScrollPane>
|
</ScrollPane>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
|
@ -20,9 +20,8 @@ public class Converter
|
||||||
} catch (ParseException e)
|
} catch (ParseException e)
|
||||||
{
|
{
|
||||||
log.warn(e.toString());
|
log.warn(e.toString());
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.bitsquare.gui.util;
|
package io.bitsquare.gui.util;
|
||||||
|
|
||||||
|
import io.bitsquare.bank.BankAccountType;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.gui.components.VSpacer;
|
import io.bitsquare.gui.components.VSpacer;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
@ -8,7 +9,9 @@ import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
import java.util.Currency;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class FormBuilder
|
public class FormBuilder
|
||||||
{
|
{
|
||||||
|
@ -67,14 +70,38 @@ public class FormBuilder
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ComboBox addComboBox(GridPane gridPane, String title, List<?> list, int row)
|
public static ComboBox<Locale> addLocalesComboBox(GridPane gridPane, String title, List<Locale> list, int row)
|
||||||
{
|
{
|
||||||
gridPane.add(new Label(title), 0, row);
|
gridPane.add(new Label(title), 0, row);
|
||||||
ComboBox comboBox = new ComboBox(FXCollections.observableArrayList(list));
|
ComboBox<Locale> comboBox = new ComboBox<>(FXCollections.observableArrayList(list));
|
||||||
gridPane.add(comboBox, 1, row);
|
gridPane.add(comboBox, 1, row);
|
||||||
return comboBox;
|
return comboBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ComboBox<Currency> addCurrencyComboBox(GridPane gridPane, String title, List<Currency> list, int row)
|
||||||
|
{
|
||||||
|
gridPane.add(new Label(title), 0, row);
|
||||||
|
ComboBox<Currency> comboBox = new ComboBox<>(FXCollections.observableArrayList(list));
|
||||||
|
gridPane.add(comboBox, 1, row);
|
||||||
|
return comboBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ComboBox<BankAccountType> addBankAccountComboBox(GridPane gridPane, String title, List<BankAccountType> list, int row)
|
||||||
|
{
|
||||||
|
gridPane.add(new Label(title), 0, row);
|
||||||
|
ComboBox<BankAccountType> comboBox = new ComboBox<>(FXCollections.observableArrayList(list));
|
||||||
|
gridPane.add(comboBox, 1, row);
|
||||||
|
return comboBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public static ComboBox addLocalesComboBox(GridPane gridPane, String title, List<?> list, int row)
|
||||||
|
{
|
||||||
|
gridPane.add(new Label(title), 0, row);
|
||||||
|
ComboBox<?> comboBox = new ComboBox<>(FXCollections.observableArrayList(list));
|
||||||
|
gridPane.add(comboBox, 1, row);
|
||||||
|
return comboBox;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
public static TextField addConfirmationsLabel(GridPane gridPane, WalletFacade walletFacade, int row)
|
public static TextField addConfirmationsLabel(GridPane gridPane, WalletFacade walletFacade, int row)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package io.bitsquare.gui.util;
|
package io.bitsquare.gui.util;
|
||||||
|
|
||||||
import io.bitsquare.btc.BtcFormatter;
|
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -88,14 +86,6 @@ public class Formatter
|
||||||
return s.substring(1, s.length() - 1);
|
return s.substring(1, s.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String formatSatoshis(BigInteger satoshis, boolean useBTC)
|
|
||||||
{
|
|
||||||
if (useBTC)
|
|
||||||
return formatDouble(BtcFormatter.satoshiToBTC(satoshis), 4) + " BTC";
|
|
||||||
else
|
|
||||||
return formatDouble(BtcFormatter.satoshiToBTC(satoshis), 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String formatDouble(double value)
|
public static String formatDouble(double value)
|
||||||
{
|
{
|
||||||
return formatDouble(value, 2);
|
return formatDouble(value, 2);
|
||||||
|
|
|
@ -13,4 +13,14 @@ public class Popups
|
||||||
.lightweight()
|
.lightweight()
|
||||||
.showError();
|
.showError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void openWarningPopup(String title, String message)
|
||||||
|
{
|
||||||
|
Dialogs.create()
|
||||||
|
.title(title)
|
||||||
|
.message(message)
|
||||||
|
.nativeTitleBar()
|
||||||
|
.lightweight()
|
||||||
|
.showWarning();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,16 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
public class Transitions
|
public class Transitions
|
||||||
{
|
{
|
||||||
|
|
||||||
public static final int UI_ANIMATION_TIME_MSEC = 350;
|
public static final int UI_ANIMATION_TIME = 350;
|
||||||
|
|
||||||
public static void fadeIn(Node ui)
|
public static void fadeIn(Node ui)
|
||||||
{
|
{
|
||||||
fadeIn(ui, UI_ANIMATION_TIME_MSEC);
|
fadeIn(ui, UI_ANIMATION_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void fadeIn(Node ui, int time)
|
public static void fadeIn(Node ui, int time)
|
||||||
{
|
{
|
||||||
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME_MSEC), ui);
|
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME), ui);
|
||||||
ft.setFromValue(0.0);
|
ft.setFromValue(0.0);
|
||||||
ft.setToValue(1.0);
|
ft.setToValue(1.0);
|
||||||
ft.play();
|
ft.play();
|
||||||
|
@ -29,7 +29,7 @@ public class Transitions
|
||||||
|
|
||||||
public static Animation fadeOut(Node ui)
|
public static Animation fadeOut(Node ui)
|
||||||
{
|
{
|
||||||
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME_MSEC), ui);
|
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME), ui);
|
||||||
ft.setFromValue(ui.getOpacity());
|
ft.setFromValue(ui.getOpacity());
|
||||||
ft.setToValue(0.0);
|
ft.setToValue(0.0);
|
||||||
ft.play();
|
ft.play();
|
||||||
|
@ -45,7 +45,7 @@ public class Transitions
|
||||||
|
|
||||||
public static void blurOut(Node node)
|
public static void blurOut(Node node)
|
||||||
{
|
{
|
||||||
blurOut(node, UI_ANIMATION_TIME_MSEC);
|
blurOut(node, UI_ANIMATION_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void blurOut(Node node, int time)
|
public static void blurOut(Node node, int time)
|
||||||
|
@ -64,7 +64,7 @@ public class Transitions
|
||||||
GaussianBlur blur = (GaussianBlur) node.getEffect();
|
GaussianBlur blur = (GaussianBlur) node.getEffect();
|
||||||
Timeline timeline = new Timeline();
|
Timeline timeline = new Timeline();
|
||||||
KeyValue kv = new KeyValue(blur.radiusProperty(), 0.0);
|
KeyValue kv = new KeyValue(blur.radiusProperty(), 0.0);
|
||||||
KeyFrame kf = new KeyFrame(Duration.millis(UI_ANIMATION_TIME_MSEC), kv);
|
KeyFrame kf = new KeyFrame(Duration.millis(UI_ANIMATION_TIME), kv);
|
||||||
timeline.getKeyFrames().add(kf);
|
timeline.getKeyFrames().add(kf);
|
||||||
timeline.setOnFinished(actionEvent -> node.setEffect(null));
|
timeline.setOnFinished(actionEvent -> node.setEffect(null));
|
||||||
timeline.play();
|
timeline.play();
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class Message
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return type + ": " + Utils.convertToJson(payload);
|
return type + ": " + Utils.objectToJson(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.google.inject.Inject;
|
||||||
import io.bitsquare.user.Arbitrator;
|
import io.bitsquare.user.Arbitrator;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -14,8 +15,9 @@ public class Settings implements Serializable
|
||||||
|
|
||||||
private List<Locale> acceptedLanguageLocales = new ArrayList<>();
|
private List<Locale> acceptedLanguageLocales = new ArrayList<>();
|
||||||
private List<Locale> acceptedCountryLocales = new ArrayList<>();
|
private List<Locale> acceptedCountryLocales = new ArrayList<>();
|
||||||
private List<Arbitrator> arbitrators = new ArrayList<>();
|
private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
|
||||||
|
private double maxCollateral;
|
||||||
|
private double minCollateral;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Constructor
|
// Constructor
|
||||||
|
@ -37,7 +39,9 @@ public class Settings implements Serializable
|
||||||
{
|
{
|
||||||
acceptedLanguageLocales = savedSettings.getAcceptedLanguageLocales();
|
acceptedLanguageLocales = savedSettings.getAcceptedLanguageLocales();
|
||||||
acceptedCountryLocales = savedSettings.getAcceptedCountryLocales();
|
acceptedCountryLocales = savedSettings.getAcceptedCountryLocales();
|
||||||
arbitrators = savedSettings.getArbitrators();
|
acceptedArbitrators = savedSettings.getAcceptedArbitrators();
|
||||||
|
maxCollateral = savedSettings.getMaxCollateral();
|
||||||
|
minCollateral = savedSettings.getMinCollateral();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,20 +57,29 @@ public class Settings implements Serializable
|
||||||
acceptedCountryLocales.add(locale);
|
acceptedCountryLocales.add(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addArbitrator(Arbitrator arbitrator)
|
public void addAcceptedArbitrator(Arbitrator arbitrator)
|
||||||
{
|
{
|
||||||
if (!arbitrators.contains(arbitrator))
|
if (!acceptedArbitrators.contains(arbitrator))
|
||||||
arbitrators.add(arbitrator);
|
acceptedArbitrators.add(arbitrator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMaxCollateral(double maxCollateral)
|
||||||
|
{
|
||||||
|
this.maxCollateral = maxCollateral;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinCollateral(double minCollateral)
|
||||||
|
{
|
||||||
|
this.minCollateral = minCollateral;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Getters
|
// Getters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public List<Arbitrator> getArbitrators()
|
public List<Arbitrator> getAcceptedArbitrators()
|
||||||
{
|
{
|
||||||
return arbitrators;
|
return acceptedArbitrators;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Locale> getAcceptedLanguageLocales()
|
public List<Locale> getAcceptedLanguageLocales()
|
||||||
|
@ -79,8 +92,28 @@ public class Settings implements Serializable
|
||||||
return acceptedCountryLocales;
|
return acceptedCountryLocales;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Arbitrator getRandomArbitrator()
|
public Arbitrator getRandomArbitrator(double collateral, BigInteger amount)
|
||||||
{
|
{
|
||||||
return arbitrators.size() > 0 ? arbitrators.get((int) (Math.random() * arbitrators.size())) : null;
|
List<Arbitrator> candidates = new ArrayList<>();
|
||||||
|
for (Arbitrator arbitrator : acceptedArbitrators)
|
||||||
|
{
|
||||||
|
if (arbitrator.getArbitrationFeePercent() >= collateral &&
|
||||||
|
arbitrator.getMinArbitrationFee().compareTo(amount) < 0)
|
||||||
|
{
|
||||||
|
candidates.add(arbitrator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return candidates.size() > 0 ? candidates.get((int) (Math.random() * candidates.size())) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getMaxCollateral()
|
||||||
|
{
|
||||||
|
return maxCollateral;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMinCollateral()
|
||||||
|
{
|
||||||
|
return minCollateral;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.bitsquare.trade;
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.bank.BankAccountType;
|
||||||
import io.bitsquare.user.Arbitrator;
|
import io.bitsquare.user.Arbitrator;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.Currency;
|
import java.util.Currency;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -12,29 +13,37 @@ public class Offer
|
||||||
{
|
{
|
||||||
private UUID uid;
|
private UUID uid;
|
||||||
private double price;
|
private double price;
|
||||||
private double amount;
|
private BigInteger amount;
|
||||||
private double minAmount;
|
private BigInteger minAmount;
|
||||||
private String accountID;
|
private String accountID;
|
||||||
private String messageID;
|
private String messageID;
|
||||||
private Direction direction;
|
private Direction direction;
|
||||||
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum;
|
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum;
|
||||||
private Currency currency;
|
private Currency currency;
|
||||||
private Locale bankAccountCountryLocale;
|
private Locale bankAccountCountryLocale;
|
||||||
|
|
||||||
|
private double collateral;
|
||||||
private List<Locale> acceptedCountryLocales;
|
private List<Locale> acceptedCountryLocales;
|
||||||
private List<Locale> acceptedLanguageLocales;
|
private List<Locale> acceptedLanguageLocales;
|
||||||
private String offerPaymentTxID;
|
private String offerPaymentTxID;
|
||||||
private Arbitrator arbitrator;
|
private Arbitrator arbitrator;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Offer(String accountID,
|
public Offer(String accountID,
|
||||||
String messageID,
|
String messageID,
|
||||||
Direction direction,
|
Direction direction,
|
||||||
double price,
|
double price,
|
||||||
double amount,
|
BigInteger amount,
|
||||||
double minAmount,
|
BigInteger minAmount,
|
||||||
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum,
|
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum,
|
||||||
Currency currency,
|
Currency currency,
|
||||||
Locale bankAccountCountryLocale,
|
Locale bankAccountCountryLocale,
|
||||||
Arbitrator arbitrator,
|
Arbitrator arbitrator,
|
||||||
|
double collateral,
|
||||||
List<Locale> acceptedCountryLocales,
|
List<Locale> acceptedCountryLocales,
|
||||||
List<Locale> acceptedLanguageLocales)
|
List<Locale> acceptedLanguageLocales)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +57,7 @@ public class Offer
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.bankAccountCountryLocale = bankAccountCountryLocale;
|
this.bankAccountCountryLocale = bankAccountCountryLocale;
|
||||||
this.arbitrator = arbitrator;
|
this.arbitrator = arbitrator;
|
||||||
|
this.collateral = collateral;
|
||||||
this.acceptedCountryLocales = acceptedCountryLocales;
|
this.acceptedCountryLocales = acceptedCountryLocales;
|
||||||
this.acceptedLanguageLocales = acceptedLanguageLocales;
|
this.acceptedLanguageLocales = acceptedLanguageLocales;
|
||||||
|
|
||||||
|
@ -89,12 +99,12 @@ public class Offer
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getAmount()
|
public BigInteger getAmount()
|
||||||
{
|
{
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getMinAmount()
|
public BigInteger getMinAmount()
|
||||||
{
|
{
|
||||||
return minAmount;
|
return minAmount;
|
||||||
}
|
}
|
||||||
|
@ -131,12 +141,12 @@ public class Offer
|
||||||
|
|
||||||
public double getVolume()
|
public double getVolume()
|
||||||
{
|
{
|
||||||
return price * amount;
|
return price * amount.doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getMinVolume()
|
public double getMinVolume()
|
||||||
{
|
{
|
||||||
return price * minAmount;
|
return price * minAmount.doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOfferPaymentTxID()
|
public String getOfferPaymentTxID()
|
||||||
|
@ -148,4 +158,9 @@ public class Offer
|
||||||
{
|
{
|
||||||
return arbitrator;
|
return arbitrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getCollateral()
|
||||||
|
{
|
||||||
|
return collateral;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.bitsquare.trade;
|
package io.bitsquare.trade;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class Trade
|
public class Trade
|
||||||
|
@ -7,8 +8,7 @@ public class Trade
|
||||||
private Offer offer;
|
private Offer offer;
|
||||||
private boolean takeOfferRequested;
|
private boolean takeOfferRequested;
|
||||||
private boolean takeOfferAccepted;
|
private boolean takeOfferAccepted;
|
||||||
private double requestedAmount;
|
private BigInteger requestedAmount;
|
||||||
private boolean takeOfferFeePayed;
|
|
||||||
private boolean takeOfferFeePaymentConfirmed;
|
private boolean takeOfferFeePaymentConfirmed;
|
||||||
private String jsonRepresentation;
|
private String jsonRepresentation;
|
||||||
private String signature;
|
private String signature;
|
||||||
|
@ -59,21 +59,16 @@ public class Trade
|
||||||
this.takeOfferAccepted = takeOfferAccepted;
|
this.takeOfferAccepted = takeOfferAccepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getRequestedAmount()
|
public BigInteger getRequestedAmount()
|
||||||
{
|
{
|
||||||
return requestedAmount;
|
return requestedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTradeAmount(double requestedAmount)
|
public void setTradeAmount(BigInteger requestedAmount)
|
||||||
{
|
{
|
||||||
this.requestedAmount = requestedAmount;
|
this.requestedAmount = requestedAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTakeOfferFeePayed(boolean takeOfferFeePayed)
|
|
||||||
{
|
|
||||||
this.takeOfferFeePayed = takeOfferFeePayed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTakeOfferFeePaymentConfirmed(boolean takeOfferFeePaymentConfirmed)
|
public void setTakeOfferFeePaymentConfirmed(boolean takeOfferFeePaymentConfirmed)
|
||||||
{
|
{
|
||||||
this.takeOfferFeePaymentConfirmed = takeOfferFeePaymentConfirmed;
|
this.takeOfferFeePaymentConfirmed = takeOfferFeePaymentConfirmed;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package io.bitsquare.trade;
|
package io.bitsquare.trade;
|
||||||
|
|
||||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||||
|
import com.google.bitcoin.core.Transaction;
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.btc.BlockChainFacade;
|
import io.bitsquare.btc.BlockChainFacade;
|
||||||
|
import io.bitsquare.btc.Fees;
|
||||||
import io.bitsquare.btc.KeyPair;
|
import io.bitsquare.btc.KeyPair;
|
||||||
import io.bitsquare.btc.WalletFacade;
|
import io.bitsquare.btc.WalletFacade;
|
||||||
import io.bitsquare.crypto.CryptoFacade;
|
import io.bitsquare.crypto.CryptoFacade;
|
||||||
|
@ -18,8 +21,9 @@ import java.util.HashMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main facade for operating with trade domain between GUI and services (msg, btc)
|
* Represents trade domain. Keeps complexity of process apart from view controller
|
||||||
*/
|
*/
|
||||||
|
//TODO use scheduler/process pattern with tasks for every async job
|
||||||
public class Trading
|
public class Trading
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
||||||
|
@ -34,6 +38,11 @@ public class Trading
|
||||||
private CryptoFacade cryptoFacade;
|
private CryptoFacade cryptoFacade;
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Trading(User user,
|
public Trading(User user,
|
||||||
Settings settings,
|
Settings settings,
|
||||||
|
@ -50,64 +59,21 @@ public class Trading
|
||||||
this.cryptoFacade = cryptoFacade;
|
this.cryptoFacade = cryptoFacade;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param offer
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
*/
|
// Public Methods
|
||||||
public String placeNewOffer(Offer offer) throws InsufficientMoneyException
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void placeNewOffer(Offer offer, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||||
{
|
{
|
||||||
log.info("place New Offer");
|
log.info("place New Offer");
|
||||||
offers.put(offer.getUid().toString(), offer);
|
offers.put(offer.getUid().toString(), offer);
|
||||||
String txID = walletFacade.payOfferFee();
|
walletFacade.payFee(Fees.OFFER_CREATION_FEE, callback);
|
||||||
offer.setOfferPaymentTxID(txID);
|
|
||||||
|
|
||||||
messageFacade.broadcast(new Message(Message.BROADCAST_NEW_OFFER, offer));
|
messageFacade.broadcast(new Message(Message.BROADCAST_NEW_OFFER, offer));
|
||||||
return txID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Trade createTrade(Offer offer)
|
||||||
* Taker requests offerer to take the offer
|
|
||||||
*
|
|
||||||
* @param trade
|
|
||||||
*/
|
|
||||||
public void sendTakeOfferRequest(Trade trade)
|
|
||||||
{
|
|
||||||
log.info("Taker asks offerer to take his offer");
|
|
||||||
//messageFacade.send(new Message(Message.REQUEST_TAKE_OFFER, trade), trade.getOffer().getOfferer().getMessageID());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param trade
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Contract createNewContract(Trade trade)
|
|
||||||
{
|
|
||||||
log.info("create new contract");
|
|
||||||
KeyPair address = walletFacade.createNewAddress();
|
|
||||||
|
|
||||||
Contract contract = new Contract(user, trade, address.getPubKey());
|
|
||||||
contracts.put(trade.getUid().toString(), contract);
|
|
||||||
return contract;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param contract
|
|
||||||
*/
|
|
||||||
public void signContract(Contract contract)
|
|
||||||
{
|
|
||||||
log.info("sign Contract");
|
|
||||||
|
|
||||||
String contractAsJson = Utils.convertToJson(contract);
|
|
||||||
|
|
||||||
contract.getTrade().setJsonRepresentation(contractAsJson);
|
|
||||||
contract.getTrade().setSignature(cryptoFacade.signContract(contractAsJson));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param offer
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Trade createNewTrade(Offer offer)
|
|
||||||
{
|
{
|
||||||
log.info("create New Trade");
|
log.info("create New Trade");
|
||||||
Trade trade = new Trade(offer);
|
Trade trade = new Trade(offer);
|
||||||
|
@ -115,55 +81,63 @@ public class Trading
|
||||||
return trade;
|
return trade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Contract createContract(Trade trade)
|
||||||
public HashMap<String, Trade> getTrades()
|
|
||||||
{
|
{
|
||||||
return trades;
|
log.info("create new contract");
|
||||||
|
KeyPair address = new KeyPair(UUID.randomUUID().toString(), UUID.randomUUID().toString());
|
||||||
|
//TODO
|
||||||
|
Contract contract = new Contract(user, trade, address.getPubKey());
|
||||||
|
contracts.put(trade.getUid().toString(), contract);
|
||||||
|
return contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param trade
|
// trade process
|
||||||
*/
|
// 1
|
||||||
public void payOfferFee(Trade trade)
|
public void sendTakeOfferRequest(Trade trade)
|
||||||
|
{
|
||||||
|
log.info("Taker asks offerer to take his offer");
|
||||||
|
//messageFacade.send(new Message(Message.REQUEST_TAKE_OFFER, trade), trade.getOffer().getOfferer().getMessageID());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2
|
||||||
|
public void payOfferFee(Trade trade, FutureCallback<Transaction> callback) throws InsufficientMoneyException
|
||||||
{
|
{
|
||||||
log.info("Pay offer fee");
|
log.info("Pay offer fee");
|
||||||
|
|
||||||
trade.setTakeOfferFeePayed(true);
|
walletFacade.payFee(Fees.OFFER_TAKER_FEE, callback);
|
||||||
|
|
||||||
String txID = UUID.randomUUID().toString();
|
|
||||||
trade.setTakeOfferFeePayed(true);
|
|
||||||
trade.setTakeOfferFeeTxID(txID);
|
|
||||||
|
|
||||||
log.info("Taker asks offerer for confirmation for his fee payment. txID=" + txID);
|
log.info("Taker asks offerer for confirmation for his fee payment.");
|
||||||
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3
|
||||||
public void requestOffererDetailData()
|
public void requestOffererDetailData()
|
||||||
{
|
{
|
||||||
log.info("Request offerer detail data");
|
log.info("Request offerer detail data");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 4
|
||||||
* @param trade
|
public void signContract(Contract contract)
|
||||||
*/
|
{
|
||||||
|
log.info("sign Contract");
|
||||||
|
|
||||||
|
String contractAsJson = Utils.objectToJson(contract);
|
||||||
|
|
||||||
|
contract.getTrade().setJsonRepresentation(contractAsJson);
|
||||||
|
contract.getTrade().setSignature(cryptoFacade.signContract(walletFacade.getAccountKey(), contractAsJson));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5
|
||||||
public void payToDepositTx(Trade trade)
|
public void payToDepositTx(Trade trade)
|
||||||
{
|
{
|
||||||
log.info("create MultiSig address");
|
//walletFacade.takerAddPaymentAndSign();
|
||||||
|
|
||||||
log.info("Create deposit tx");
|
|
||||||
|
|
||||||
log.info("Sign deposit tx");
|
|
||||||
|
|
||||||
log.info("Send deposit Tx");
|
|
||||||
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 6
|
||||||
/**
|
|
||||||
* @param trade
|
|
||||||
*/
|
|
||||||
public void releaseBTC(Trade trade)
|
public void releaseBTC(Trade trade)
|
||||||
{
|
{
|
||||||
log.info("Sign payment tx");
|
log.info("Sign payment tx");
|
||||||
|
@ -174,5 +148,13 @@ public class Trading
|
||||||
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
// messageFacade.send(new Message(Message.REQUEST_OFFER_FEE_PAYMENT_CONFIRM, trade), trade.getOffer().getOfferer().getMessageID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Getters
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public HashMap<String, Trade> getTrades()
|
||||||
|
{
|
||||||
|
return trades;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.bitsquare.trade.orderbook;
|
package io.bitsquare.trade.orderbook;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.BtcFormatter;
|
||||||
import io.bitsquare.gui.market.orderbook.OrderBookListItem;
|
import io.bitsquare.gui.market.orderbook.OrderBookListItem;
|
||||||
import io.bitsquare.gui.util.Converter;
|
import io.bitsquare.gui.util.Converter;
|
||||||
import io.bitsquare.gui.util.Formatter;
|
import io.bitsquare.gui.util.Formatter;
|
||||||
|
@ -42,19 +43,20 @@ public class MockOrderBook extends OrderBook
|
||||||
direction = Direction.SELL;
|
direction = Direction.SELL;
|
||||||
price = 500 - Math.random() * 50;
|
price = 500 - Math.random() * 50;
|
||||||
}
|
}
|
||||||
|
double collateral = 0.1;// Math.random() * 20 + 0.1;
|
||||||
Offer offer = new Offer("mjbxLbuVpU1cNXLJbrJZyirYwweoRPVVTj",
|
Offer offer = new Offer("mjbxLbuVpU1cNXLJbrJZyirYwweoRPVVTj",
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
direction,
|
direction,
|
||||||
price,
|
price,
|
||||||
amount,
|
BtcFormatter.doubleValueToSatoshis(amount),
|
||||||
minAmount,
|
BtcFormatter.doubleValueToSatoshis(minAmount),
|
||||||
MockData.getBankTransferTypeEnums().get(0),
|
MockData.getRandomBankTransferTypeEnums().get(0),
|
||||||
MockData.getCurrencies().get(0),
|
MockData.getRandomCurrencies().get(0),
|
||||||
MockData.getLocales().get(0),
|
MockData.getRandomLocales().get(0),
|
||||||
MockData.getArbitrators().get(0),
|
MockData.getRandomArbitrators().get(0),
|
||||||
MockData.getLocales(),
|
collateral,
|
||||||
MockData.getLocales());
|
MockData.getRandomLocales(),
|
||||||
|
MockData.getRandomLocales());
|
||||||
|
|
||||||
return offer;
|
return offer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import io.bitsquare.gui.market.orderbook.OrderBookListItem;
|
||||||
import io.bitsquare.settings.Settings;
|
import io.bitsquare.settings.Settings;
|
||||||
import io.bitsquare.trade.Direction;
|
import io.bitsquare.trade.Direction;
|
||||||
import io.bitsquare.trade.Offer;
|
import io.bitsquare.trade.Offer;
|
||||||
|
import io.bitsquare.user.Arbitrator;
|
||||||
import io.bitsquare.user.User;
|
import io.bitsquare.user.User;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
@ -76,7 +77,7 @@ public class OrderBook
|
||||||
// The requested amount must be lower or equal then the offer amount
|
// The requested amount must be lower or equal then the offer amount
|
||||||
boolean amountResult = true;
|
boolean amountResult = true;
|
||||||
if (orderBookFilter.getAmount() > 0)
|
if (orderBookFilter.getAmount() > 0)
|
||||||
amountResult = orderBookFilter.getAmount() <= offer.getAmount();
|
amountResult = orderBookFilter.getAmount() <= offer.getAmount().doubleValue();
|
||||||
|
|
||||||
// The requested trade direction must be opposite of the offerList trade direction
|
// The requested trade direction must be opposite of the offerList trade direction
|
||||||
boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection());
|
boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection());
|
||||||
|
@ -91,40 +92,46 @@ public class OrderBook
|
||||||
priceResult = orderBookFilter.getPrice() <= offer.getPrice();
|
priceResult = orderBookFilter.getPrice() <= offer.getPrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The arbitrator defined in the offer must match one of the accepted arbitrators defined in the settings (1 to n)
|
||||||
|
boolean arbitratorResult = arbitratorInList(offer.getArbitrator(), settings.getAcceptedArbitrators());
|
||||||
|
|
||||||
|
|
||||||
boolean result = currencyResult
|
boolean result = currencyResult
|
||||||
&& countryResult
|
&& countryResult
|
||||||
&& languageResult
|
&& languageResult
|
||||||
&& amountResult
|
&& amountResult
|
||||||
&& directionResult
|
&& directionResult
|
||||||
&& priceResult;
|
&& priceResult
|
||||||
|
&& arbitratorResult;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
log.debug("result = " + result +
|
log.debug("result = " + result +
|
||||||
", currencyResult = " + currencyResult +
|
", currencyResult = " + currencyResult +
|
||||||
", countryResult = " + countryResult +
|
", countryResult = " + countryResult +
|
||||||
", languageResult = " + languageResult +
|
", languageResult = " + languageResult +
|
||||||
", bankAccountTypeEnumResult = " + bankAccountTypeEnumResult +
|
|
||||||
", amountResult = " + amountResult +
|
", amountResult = " + amountResult +
|
||||||
", directionResult = " + directionResult +
|
", directionResult = " + directionResult +
|
||||||
", priceResult = " + priceResult
|
", priceResult = " + priceResult +
|
||||||
|
", arbitratorResult = " + arbitratorResult
|
||||||
);
|
);
|
||||||
|
|
||||||
log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() +
|
log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() +
|
||||||
", offer.getCurrency() = " + offer.getCurrency());
|
", offer.getCurrency() = " + offer.getCurrency());
|
||||||
log.debug("offer.getCountryLocale() = " + offer.getCountryLocale() +
|
log.debug("offer.getCountryLocale() = " + offer.getBankAccountCountryLocale() +
|
||||||
", settings.getAcceptedCountryLocales() = " + settings.getAcceptedCountryLocales().toString());
|
", settings.getAcceptedCountryLocales() = " + settings.getAcceptedCountryLocales().toString());
|
||||||
log.debug("settings.getAcceptedLanguageLocales() = " + settings.getAcceptedLanguageLocales() +
|
log.debug("settings.getAcceptedLanguageLocales() = " + settings.getAcceptedLanguageLocales() +
|
||||||
", constraints.getAcceptedLanguageLocales() = " + constraints.getLanguageLocales());
|
", offer.getAcceptedLanguageLocales() = " + offer.getAcceptedLanguageLocales());
|
||||||
log.debug("currentBankAccount.getBankAccountType().getType() = " + currentBankAccount.getBankAccountType().getType() +
|
log.debug("currentBankAccount.getBankAccountType().getType() = " + currentBankAccount.getBankAccountType().getType() +
|
||||||
", constraints.getBankAccountTypes() = " + constraints.getBankAccountTypes());
|
", offer.getBankAccountTypeEnum() = " + offer.getBankAccountTypeEnum());
|
||||||
log.debug("orderBookFilter.getAmount() = " + orderBookFilter.getAmount() +
|
log.debug("orderBookFilter.getAmount() = " + orderBookFilter.getAmount() +
|
||||||
", offer.getAmount() = " + offer.getAmount());
|
", offer.getAmount() = " + offer.getAmount());
|
||||||
log.debug("orderBookFilter.getDirection() = " + orderBookFilter.getDirection() +
|
log.debug("orderBookFilter.getDirection() = " + orderBookFilter.getDirection() +
|
||||||
", offer.getDirection() = " + offer.getDirection());
|
", offer.getDirection() = " + offer.getDirection());
|
||||||
log.debug("orderBookFilter.getPrice() = " + orderBookFilter.getPrice() +
|
log.debug("orderBookFilter.getPrice() = " + orderBookFilter.getPrice() +
|
||||||
", offer.getPrice() = " + offer.getPrice());
|
", offer.getPrice() = " + offer.getPrice());
|
||||||
*/
|
log.debug("offer.getArbitrator() = " + offer.getArbitrator() +
|
||||||
|
", settings.getAcceptedArbitrators() = " + settings.getAcceptedArbitrators());
|
||||||
|
*/
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -144,26 +151,45 @@ public class OrderBook
|
||||||
// Private Methods
|
// Private Methods
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private boolean countryInList(Locale orderBookFilterLocale, List<Locale> offerConstraintsLocales)
|
private boolean countryInList(Locale localeToMatch, List<Locale> list)
|
||||||
{
|
{
|
||||||
for (Locale locale : offerConstraintsLocales)
|
for (Locale locale : list)
|
||||||
{
|
{
|
||||||
if (locale.getCountry().equals(orderBookFilterLocale.getCountry()))
|
if (locale.getCountry().equals(localeToMatch.getCountry()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean languagesInList(List<Locale> orderBookFilterLocales, List<Locale> offerConstraintsLocales)
|
private boolean languagesInList(List<Locale> list1, List<Locale> list2)
|
||||||
{
|
{
|
||||||
for (Locale offerConstraintsLocale : offerConstraintsLocales)
|
for (Locale locale1 : list2)
|
||||||
{
|
{
|
||||||
for (Locale orderBookFilterLocale : orderBookFilterLocales)
|
for (Locale locale2 : list1)
|
||||||
{
|
{
|
||||||
if (offerConstraintsLocale.getLanguage().equals(orderBookFilterLocale.getLanguage()))
|
if (locale1.getLanguage().equals(locale2.getLanguage()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean arbitratorInList(Arbitrator arbitratorToMatch, List<Arbitrator> list)
|
||||||
|
{
|
||||||
|
if (arbitratorToMatch != null)
|
||||||
|
{
|
||||||
|
for (Arbitrator arbitrator : list)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (arbitrator.getUID().equals(arbitratorToMatch.getUID()))
|
||||||
|
return true;
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
log.error(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package io.bitsquare.user;
|
package io.bitsquare.user;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
public class Arbitrator implements Serializable
|
public class Arbitrator implements Serializable
|
||||||
{
|
{
|
||||||
|
@ -11,13 +12,22 @@ public class Arbitrator implements Serializable
|
||||||
private String messageID;
|
private String messageID;
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
public Arbitrator(String name, String pubKey, String messageID, String url)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
private double baseFeePercent;
|
||||||
|
private double arbitrationFeePercent;
|
||||||
|
private BigInteger minArbitrationFee;
|
||||||
|
private String uid;
|
||||||
|
|
||||||
|
public Arbitrator(String uid, String name, String pubKey, String messageID, String url, double baseFeePercent, double arbitrationFeePercent, BigInteger minArbitrationFee)
|
||||||
|
{
|
||||||
|
this.uid = uid;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.pubKey = pubKey;
|
this.pubKey = pubKey;
|
||||||
this.messageID = messageID;
|
this.messageID = messageID;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.baseFeePercent = baseFeePercent;
|
||||||
|
this.arbitrationFeePercent = arbitrationFeePercent;
|
||||||
|
this.minArbitrationFee = minArbitrationFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,4 +55,23 @@ public class Arbitrator implements Serializable
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigInteger getMinArbitrationFee()
|
||||||
|
{
|
||||||
|
return minArbitrationFee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getBaseFeePercent()
|
||||||
|
{
|
||||||
|
return baseFeePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getArbitrationFeePercent()
|
||||||
|
{
|
||||||
|
return arbitrationFeePercent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getUID()
|
||||||
|
{
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class User implements Serializable
|
||||||
private List<BankAccount> bankAccounts = new ArrayList<>();
|
private List<BankAccount> bankAccounts = new ArrayList<>();
|
||||||
private BankAccount currentBankAccount = null;
|
private BankAccount currentBankAccount = null;
|
||||||
|
|
||||||
|
|
||||||
public User()
|
public User()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,12 @@ public class MockData
|
||||||
list.add(Currency.getInstance("JPY"));
|
list.add(Currency.getInstance("JPY"));
|
||||||
list.add(Currency.getInstance("CNY"));
|
list.add(Currency.getInstance("CNY"));
|
||||||
list.add(Currency.getInstance("CHF"));
|
list.add(Currency.getInstance("CHF"));
|
||||||
return randomizeList(list);
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Currency> getRandomCurrencies()
|
||||||
|
{
|
||||||
|
return randomizeList(getCurrencies());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Locale> getLocales()
|
public static List<Locale> getLocales()
|
||||||
|
@ -36,20 +41,40 @@ public class MockData
|
||||||
list.add(new Locale("en", "AU"));
|
list.add(new Locale("en", "AU"));
|
||||||
list.add(new Locale("it", "IT"));
|
list.add(new Locale("it", "IT"));
|
||||||
list.add(new Locale("en", "CA"));
|
list.add(new Locale("en", "CA"));
|
||||||
return randomizeList(list);
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Locale> getRandomLocales()
|
||||||
|
{
|
||||||
|
return randomizeList(getLocales());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Arbitrator> getArbitrators()
|
public static List<Arbitrator> getArbitrators()
|
||||||
{
|
{
|
||||||
List<Arbitrator> list = new ArrayList<>();
|
List<Arbitrator> list = new ArrayList<>();
|
||||||
list.add(new Arbitrator("Charly Shen", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Charly_Shen"));
|
list.add(new Arbitrator("uid_1", "Charlie Boom", UUID.randomUUID().toString(),
|
||||||
list.add(new Arbitrator("Tom Shang", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Tom_Shang"));
|
UUID.randomUUID().toString(), "http://www.arbit.io/Charly_Boom", 0.1, 10, com.google.bitcoin.core.Utils.toNanoCoins("0.01")));
|
||||||
list.add(new Arbitrator("Edward Swow", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Edward_Swow"));
|
list.add(new Arbitrator("uid_2", "Tom Shang", UUID.randomUUID().toString(),
|
||||||
list.add(new Arbitrator("Julian Sangre", UUID.randomUUID().toString(), UUID.randomUUID().toString(), "http://www.arbit.io/Julian_Sangre"));
|
UUID.randomUUID().toString(), "http://www.arbit.io/Tom_Shang", 0, 1, com.google.bitcoin.core.Utils.toNanoCoins("0.001")));
|
||||||
return randomizeList(list);
|
list.add(new Arbitrator("uid_3", "Edward Snow", UUID.randomUUID().toString(),
|
||||||
|
UUID.randomUUID().toString(), "http://www.arbit.io/Edward_Swow", 0.2, 5, com.google.bitcoin.core.Utils.toNanoCoins("0.05")));
|
||||||
|
list.add(new Arbitrator("uid_4", "Julian Sander", UUID.randomUUID().toString(),
|
||||||
|
UUID.randomUUID().toString(), "http://www.arbit.io/Julian_Sander", 0, 20, com.google.bitcoin.core.Utils.toNanoCoins("0.1")));
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Arbitrator> getRandomArbitrators()
|
||||||
|
{
|
||||||
|
return randomizeList(getArbitrators());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<BankAccountType.BankAccountTypeEnum> getBankTransferTypeEnums()
|
public static List<BankAccountType.BankAccountTypeEnum> getBankTransferTypeEnums()
|
||||||
|
{
|
||||||
|
return Utils.getAllBankAccountTypeEnums();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<BankAccountType.BankAccountTypeEnum> getRandomBankTransferTypeEnums()
|
||||||
{
|
{
|
||||||
return randomizeList(Utils.getAllBankAccountTypeEnums());
|
return randomizeList(Utils.getAllBankAccountTypeEnums());
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.bitsquare.util;
|
||||||
import com.google.gson.FieldNamingPolicy;
|
import com.google.gson.FieldNamingPolicy;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
|
||||||
import io.bitsquare.bank.BankAccountType;
|
import io.bitsquare.bank.BankAccountType;
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.AnimationTimer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -20,12 +21,66 @@ public class Utils
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(Utils.class);
|
private static final Logger log = LoggerFactory.getLogger(Utils.class);
|
||||||
|
|
||||||
public static String convertToJson(Object object)
|
public static String objectToJson(Object object)
|
||||||
{
|
{
|
||||||
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
||||||
return gson.toJson(object);
|
return gson.toJson(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> T jsonToObject(String jsonString, Class<T> classOfT)
|
||||||
|
{
|
||||||
|
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
||||||
|
return gson.fromJson(jsonString, classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object deserializeHexStringToObject(String serializedHexString)
|
||||||
|
{
|
||||||
|
Object result = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ByteInputStream byteInputStream = new ByteInputStream();
|
||||||
|
byteInputStream.setBuf(com.google.bitcoin.core.Utils.parseAsHexOrBase58(serializedHexString));
|
||||||
|
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = objectInputStream.readObject();
|
||||||
|
} catch (ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
byteInputStream.close();
|
||||||
|
objectInputStream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException i)
|
||||||
|
{
|
||||||
|
i.printStackTrace();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String serializeObjectToHexString(Object serializable)
|
||||||
|
{
|
||||||
|
String result = null;
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
|
||||||
|
objectOutputStream.writeObject(serializable);
|
||||||
|
|
||||||
|
result = com.google.bitcoin.core.Utils.bytesToHexString(byteArrayOutputStream.toByteArray());
|
||||||
|
byteArrayOutputStream.close();
|
||||||
|
objectOutputStream.close();
|
||||||
|
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static long lastTimeStamp = System.currentTimeMillis();
|
private static long lastTimeStamp = System.currentTimeMillis();
|
||||||
|
|
||||||
public static void printElapsedTime(String msg)
|
public static void printElapsedTime(String msg)
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
|
|
||||||
<logger name="io.bitsquare" level="DEBUG"/>
|
<logger name="io.bitsquare" level="DEBUG"/>
|
||||||
|
|
||||||
<logger name="com.google.bitcoin" level="WARN"/>
|
<logger name="com.google.bitcoin" level="INFO"/>
|
||||||
|
|
||||||
|
<logger name="com.google.bitcoin.core.Peer" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.core.PeerGroup" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.core.PeerGroup" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.net.NioClientManager" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.net.NioClientManager" level="ERROR" additivity="false"/>
|
||||||
<logger name="com.google.bitcoin.net.ConnectionHandler" level="ERROR" additivity="false"/>
|
<logger name="com.google.bitcoin.net.ConnectionHandler" level="ERROR" additivity="false"/>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue