offer creation screen, model updates, confirm comp.

This commit is contained in:
Manfred Karrer 2014-04-30 02:19:36 +02:00
parent a3bee7652b
commit 3f398755ad
53 changed files with 1261 additions and 1297 deletions

View File

@ -12,15 +12,15 @@ We use bitcoinj library as a submodule. To get the project with the submodule in
git clone --recursive git://github.com/bitsquare/bitsquare
### Implemented (prototype level):
* Screen for orderbook with filtering mock offers by amount, price and order type (buy, sell), other filters not impl. yet
* Screen for creating an offer (needs update)
* Screen for offer taking and payment process
* Simple storage for some filter attributes
* bitcoinj/wallet integration (basic)
* Screen for orderbook with filtering mock offers by amount, price and order type (buy, sell)
* Screen for creating an offer
* Screen for offer taking and payment process (needs update)
* Simple persistence
* bitcoinj integration
* 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
### Next steps:
* Setup with account registration
* Other trade variants (Buy BTC taker, Sell BTC offerer, Sell BTC offerer)
* Arbitrator integration
* Messaging system
@ -28,7 +28,14 @@ git clone --recursive git://github.com/bitsquare/bitsquare
### Screenshots of basic screens:
* [Registration screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg1.png)
* [Registration screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg2.png)
* [Registration screen 3](https://github.com/bitsquare/bitsquare/tree/master/screenshots/reg3.png)
* [Orderbook screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook1.png)
* [Orderbook screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook2.png)
* [Orderbook screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/orderbook.png)
* [Create Offer screen 1](https://github.com/bitsquare/bitsquare/tree/master/screenshots/newOffer1.png)
* [Create Offer screen 2](https://github.com/bitsquare/bitsquare/tree/master/screenshots/newOffer2.png)
* [Trade screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/trade.png)
* [Bank transfer screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/bank_transfer.png)
* [Trade completed screen](https://github.com/bitsquare/bitsquare/tree/master/screenshots/completed.png)

13
TODO.txt Normal file
View File

@ -0,0 +1,13 @@
- payment process update with new models
- btc payments in payment process
- arbitration integration
Messaging!
low prio:
- add settings after setup
- settings screen
- return to setup when unregistered, change/add bank accounts from settings

BIN
screenshots/newOffer1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
screenshots/newOffer2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

BIN
screenshots/orderbook1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
screenshots/orderbook2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
screenshots/reg1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
screenshots/reg2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
screenshots/reg3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
screenshots/reg4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -6,7 +6,7 @@ import io.bitsquare.btc.WalletFacade;
import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.settings.Startup;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.User;
import javafx.application.Application;
@ -16,6 +16,8 @@ import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
public class BitSquare extends Application
{
private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
@ -34,24 +36,30 @@ public class BitSquare extends Application
// apply stored data
final User user = injector.getInstance(User.class);
final Settings settings = injector.getInstance(Settings.class);
final Storage storage = injector.getInstance(Storage.class);
user.updateFromStorage((User) storage.read(user.getClass().getName()));
//TODO remove
final Startup setup = injector.getInstance(Startup.class);
setup.applyPersistedData();
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
initSettings(settings, storage);
stage.setTitle("BitSquare");
GuiceFXMLLoader.setInjector(injector);
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource("/io/bitsquare/gui/MainView.fxml"), Localisation.getResourceBundle());
final Parent mainView = loader.load();
final Scene scene = new Scene(mainView, 800, 600);
stage.setScene(scene);
final String global = getClass().getResource("/io/bitsquare/gui/global.css").toExternalForm();
scene.getStylesheets().setAll(global);
stage.setMinWidth(740);
stage.setMinHeight(400);
stage.setWidth(800);
stage.setHeight(600);
stage.show();
}
@ -62,4 +70,31 @@ public class BitSquare extends Application
super.stop();
}
private void initSettings(Settings settings, Storage storage)
{
Settings savedSettings = (Settings) storage.read(settings.getClass().getName());
if (savedSettings == null)
{
settings.getAcceptedCountryLocales().clear();
settings.getAcceptedLanguageLocales().clear();
settings.addAcceptedLanguageLocale(Locale.getDefault());
settings.addAcceptedCountryLocale(Locale.getDefault());
//TODO mock
settings.addAcceptedLanguageLocale(new Locale("en", "US"));
settings.addAcceptedLanguageLocale(new Locale("es", "ES"));
settings.addAcceptedCountryLocale(new Locale("de", "AT"));
settings.addAcceptedCountryLocale(new Locale("en", "US"));
settings.addAcceptedCountryLocale(new Locale("es", "ES"));
storage.write(settings.getClass().getName(), settings);
}
else
{
settings.updateFromStorage(savedSettings);
}
}
}

View File

@ -18,23 +18,26 @@ public class BankAccount implements Serializable
private Currency currency;
private String uid;
// TODO just for mock yet
public BankAccount(BankAccountType bankAccountType)
{
this.bankAccountType = bankAccountType;
}
public BankAccount(BankAccountType bankAccountType, String accountPrimaryID, String accountSecondaryID, String accountHolderName, Locale countryLocale, Currency currency)
private String accountTitle;
public BankAccount(BankAccountType bankAccountType,
Currency currency,
Locale countryLocale,
String accountTitle,
String accountHolderName,
String accountPrimaryID,
String accountSecondaryID)
{
this.bankAccountType = bankAccountType;
this.currency = currency;
this.countryLocale = countryLocale;
this.accountTitle = accountTitle;
this.accountHolderName = accountHolderName;
this.accountPrimaryID = accountPrimaryID;
this.accountSecondaryID = accountSecondaryID;
this.accountHolderName = accountHolderName;
this.countryLocale = countryLocale;
this.currency = currency;
uid = bankAccountType + "_" + accountPrimaryID + "_" + accountSecondaryID + "_" + accountHolderName + "_" + countryLocale.getISO3Country();
uid = bankAccountType + "_" + accountPrimaryID + "_" + accountSecondaryID + "_" + accountHolderName + "_" + countryLocale.getCountry();
}
public String getAccountPrimaryID()
@ -72,6 +75,11 @@ public class BankAccount implements Serializable
return uid;
}
public String getAccountTitle()
{
return accountTitle;
}
// Changes of that structure must be reflected in VERSION updates
public String getStringifiedBankAccount()
{
@ -81,15 +89,9 @@ public class BankAccount implements Serializable
", secondaryID='" + accountSecondaryID + '\'' +
", holderName='" + accountHolderName + '\'' +
", currency='" + currency.getCurrencyCode() + '\'' +
", country='" + countryLocale.getISO3Country() + '\'' +
", country='" + countryLocale.getCountry() + '\'' +
", v='" + VERSION + '\'' +
'}';
}
public String getShortName()
{
return bankAccountType + " " + accountPrimaryID + " / " + accountSecondaryID + " / " + currency.getCurrencyCode();
}
}

View File

@ -170,7 +170,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
for (WalletFacade.WalletListener walletListener : walletListeners)
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfirmationDepthInBlocks(this));
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(this));
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
}
@ -205,7 +205,7 @@ public class AccountRegistrationWallet extends Wallet implements WalletEventList
log.info("onScriptsAdded");
}
int getConfirmationNumBroadcastPeers()
int getConfNumBroadcastPeers()
{
Transaction transaction = WalletUtil.getTransaction(this);
return (transaction == null || transaction.getConfidence() == null) ? 0 : transaction.getConfidence().numBroadcastPeers();

View File

@ -8,7 +8,6 @@ public class Fees
{
public static BigInteger ACCOUNT_REGISTRATION_FEE = Transaction.MIN_NONDUST_OUTPUT;// Utils.toNanoCoins("0.001");
public static BigInteger OFFER_CREATION_FEE = new BigInteger("500000");
public static BigInteger OFFER_CREATION_FEE = Transaction.MIN_NONDUST_OUTPUT; // Utils.toNanoCoins("0.001");
public static BigInteger OFFER_TAKER_FEE = OFFER_CREATION_FEE;
public static BigInteger BTC_NETWORK_FEE = new BigInteger("10000");
}

View File

@ -5,7 +5,10 @@ import com.google.bitcoin.kits.WalletAppKit;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.script.Script;
import com.google.bitcoin.script.ScriptBuilder;
import com.google.bitcoin.utils.Threading;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.inject.Inject;
import io.bitsquare.crypto.CryptoFacade;
import javafx.application.Platform;
@ -18,6 +21,8 @@ import java.util.Date;
import java.util.List;
import java.util.UUID;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
/**
* That facade delivers wallet functionality from the bitcoinJ library
* Code from BitcoinJ must not be used outside that facade.
@ -79,12 +84,12 @@ public class WalletFacade implements WalletEventListener
walletAppKit.startAsync();
walletAppKit.awaitRunning();
// Don't make the user wait for confirmations for now, as the intention is they're sending it their own money!
walletAppKit.wallet().allowSpendingUnconfirmedTransactions();
getWallet().allowSpendingUnconfirmedTransactions();
walletAppKit.peerGroup().setMaxConnections(11);
walletAppKit.wallet().addEventListener(this);
getWallet().addEventListener(this);
log.info(walletAppKit.wallet().toString());
log.info(getWallet().toString());
}
public void shutDown()
@ -134,12 +139,12 @@ public class WalletFacade implements WalletEventListener
public BigInteger getBalance()
{
return walletAppKit.wallet().getBalance(Wallet.BalanceType.ESTIMATED);
return getWallet().getBalance(Wallet.BalanceType.ESTIMATED);
}
public String getAddress()
{
return walletAppKit.wallet().getKeys().get(0).toAddress(networkParameters).toString();
return getWallet().getKeys().get(0).toAddress(networkParameters).toString();
}
// account registration
@ -171,14 +176,14 @@ public class WalletFacade implements WalletEventListener
&& blockChainFacade.verifyAddressInBlockChain(hashAsHexStringToVerify, address);
}
public int getRegistrationConfirmationNumBroadcastPeers()
public int getRegConfNumBroadcastPeers()
{
return getAccountRegistrationWallet().getConfirmationNumBroadcastPeers();
return getAccountRegistrationWallet().getConfNumBroadcastPeers();
}
public int getRegistrationConfirmationDepthInBlocks()
public int getRegConfDepthInBlocks()
{
return WalletUtil.getConfirmationDepthInBlocks(getAccountRegistrationWallet());
return WalletUtil.getConfDepthInBlocks(getAccountRegistrationWallet());
}
// WalletEventListener
@ -195,7 +200,7 @@ public class WalletFacade implements WalletEventListener
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
for (WalletListener walletListener : walletListeners)
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfirmationDepthInBlocks(walletAppKit.wallet()));
walletListener.onConfidenceChanged(tx.getConfidence().numBroadcastPeers(), WalletUtil.getConfDepthInBlocks(getWallet()));
log.info("onTransactionConfidenceChanged " + tx.getConfidence().toString());
}
@ -239,6 +244,51 @@ public class WalletFacade implements WalletEventListener
return accountRegistrationWallet;
}
public String payOfferFee() throws InsufficientMoneyException
{
getWallet();
Script script = new ScriptBuilder()
.op(OP_RETURN)
.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
private class BlockChainDownloadListener extends com.google.bitcoin.core.DownloadListener

View File

@ -11,7 +11,7 @@ public class WalletUtil
{
// TODO check if that is correct and safe
public static int getConfirmationDepthInBlocks(Wallet wallet)
public static int getConfDepthInBlocks(Wallet wallet)
{
Transaction transaction = WalletUtil.getTransaction(wallet);
if (transaction != null && transaction.getConfidence() != null)

View File

@ -16,9 +16,9 @@ import io.bitsquare.crypto.CryptoFacade;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.settings.OrderBookFilterSettings;
import io.bitsquare.settings.Settings;
import io.bitsquare.settings.Startup;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.Trading;
import io.bitsquare.trade.orderbook.MockOrderBook;
import io.bitsquare.trade.orderbook.OrderBook;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
@ -31,9 +31,8 @@ public class BitSquareModule extends AbstractModule
@Override
protected void configure()
{
bind(Startup.class).asEagerSingleton();
bind(User.class).asEagerSingleton();
bind(OrderBook.class).asEagerSingleton();
bind(OrderBook.class).to(MockOrderBook.class).asEagerSingleton();
bind(Storage.class).asEagerSingleton();
bind(Settings.class).asEagerSingleton();
bind(OrderBookFilter.class).asEagerSingleton();

View File

@ -3,4 +3,5 @@ package io.bitsquare.gui;
public interface ChildController
{
void setNavigationController(NavigationController navigationController);
}

View File

@ -10,9 +10,7 @@ import io.bitsquare.gui.trade.TradeController;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
@ -39,9 +37,7 @@ public class MainController implements Initializable, NavigationController, Wall
{
private static final Logger log = LoggerFactory.getLogger(MainController.class);
private Settings settings;
private User user;
private OrderBookFilter orderBookFilter;
private WalletFacade walletFacade;
private ChildController childController;
private ToggleGroup toggleGroup;
@ -61,11 +57,9 @@ public class MainController implements Initializable, NavigationController, Wall
public AnchorPane anchorPane;
@Inject
public MainController(Settings settings, User user, OrderBookFilter orderBookFilter, WalletFacade walletFacade)
public MainController(User user, WalletFacade walletFacade)
{
this.settings = settings;
this.user = user;
this.orderBookFilter = orderBookFilter;
this.walletFacade = walletFacade;
}
@ -78,6 +72,7 @@ public class MainController implements Initializable, NavigationController, Wall
walletFacade.addDownloadListener(this);
walletFacade.initWallet();
buildNavigation();
if (user.getAccountID() == null)
{
@ -107,6 +102,11 @@ public class MainController implements Initializable, NavigationController, Wall
return null;
}
if (childController instanceof TradeController)
{
((TradeController) childController).cleanup();
}
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
try
{
@ -172,7 +172,7 @@ public class MainController implements Initializable, NavigationController, Wall
addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS, NavigationController.FUNDS);
addNavButton(leftNavPane, "Message", Icons.MSG, Icons.MSG, NavigationController.MSG);
addBalanceInfo(rightNavPane);
addAccountComboBox();
addAccountComboBox(rightNavPane);
addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS, NavigationController.SETTINGS);
@ -226,15 +226,12 @@ public class MainController implements Initializable, NavigationController, Wall
private TextField addBalanceInfo(Pane parent)
{
Pane holder = new Pane();
TextField balanceLabel = new TextField();
balanceLabel.setEditable(false);
balanceLabel.setMouseTransparent(true);
balanceLabel.setPrefWidth(90);
balanceLabel.setId("nav-balance-label");
balanceLabel.setText(Formatter.formatSatoshis(walletFacade.getBalance(), false));
holder.getChildren().add(balanceLabel);
rightNavPane.getChildren().add(holder);
Label balanceCurrencyLabel = new Label("BTC");
balanceCurrencyLabel.setPadding(new Insets(6, 0, 0, 0));
@ -256,7 +253,7 @@ public class MainController implements Initializable, NavigationController, Wall
return balanceLabel;
}
private void addAccountComboBox()
private void addAccountComboBox(Pane parent)
{
if (user.getBankAccounts().size() > 1)
{
@ -268,7 +265,7 @@ public class MainController implements Initializable, NavigationController, Wall
@Override
public String toString(BankAccount bankAccount)
{
return bankAccount.getShortName();
return bankAccount.getAccountTitle();
}
@Override
@ -278,6 +275,16 @@ public class MainController implements Initializable, NavigationController, Wall
}
});
VBox vBox = new VBox();
vBox.setPadding(new Insets(12, 0, 0, 0));
vBox.setSpacing(2);
Label titleLabel = new Label("Bank account");
titleLabel.setMouseTransparent(true);
titleLabel.setPrefWidth(90);
titleLabel.setId("nav-button-label");
vBox.getChildren().setAll(accountComboBox, titleLabel);
parent.getChildren().add(vBox);
accountComboBox.valueProperty().addListener(new ChangeListener<BankAccount>()
{
@ -285,16 +292,10 @@ public class MainController implements Initializable, NavigationController, Wall
public void changed(ObservableValue ov, BankAccount oldValue, BankAccount newValue)
{
user.setCurrentBankAccount(newValue);
orderBookFilter.setCurrency(newValue.getCurrency());
orderBookFilter.setCountryLocale(newValue.getCountryLocale());
}
});
Pane holder = new Pane();
holder.getChildren().add(accountComboBox);
rightNavPane.getChildren().add(holder);
}
}
}

View File

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<StackPane fx:id="rootContainer" minHeight="300" minWidth="400" prefHeight="600" prefWidth="800"
stylesheets="/io/bitsquare/gui/global.css" xmlns:fx="http://javafx.com/fxml/1"
<StackPane fx:id="rootContainer" stylesheets="/io/bitsquare/gui/global.css" xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/8" fx:controller="io.bitsquare.gui.MainController">
<AnchorPane fx:id="anchorPane" id="root-pane" minHeight="300" minWidth="400" prefHeight="600" prefWidth="800">
<AnchorPane fx:id="anchorPane" id="root-pane">
<HBox fx:id="leftNavPane" spacing="10" AnchorPane.leftAnchor="0" AnchorPane.topAnchor="0"/>
<HBox fx:id="rightNavPane" spacing="10" AnchorPane.rightAnchor="10" AnchorPane.topAnchor="0"/>
<AnchorPane fx:id="contentPane" id="content-pane" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="0"

View File

@ -0,0 +1,67 @@
package io.bitsquare.gui.components;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.util.FormBuilder;
import io.bitsquare.gui.util.Icons;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
public class ConfirmationComponent implements WalletFacade.WalletListener
{
private static final Logger log = LoggerFactory.getLogger(ConfirmationComponent.class);
private ImageView confirmIconImageView;
private TextField confirmationsLabel;
private ProgressIndicator confirmSpinner;
public ConfirmationComponent(WalletFacade walletFacade, GridPane gridPane, int row)
{
confirmationsLabel = FormBuilder.addConfirmationsLabel(gridPane, walletFacade, row);
confirmIconImageView = FormBuilder.addConfirmationsIcon(gridPane, walletFacade, row);
confirmSpinner = FormBuilder.addConfirmationsSpinner(gridPane, walletFacade, row);
}
@Override
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
confirmIconImageView.setImage(getConfirmIconImage(numBroadcastPeers, depthInBlocks));
confirmationsLabel.setText(getConfirmationsText(numBroadcastPeers, depthInBlocks));
if (depthInBlocks == 0)
confirmSpinner.setProgress(-1);
else
confirmSpinner.setOpacity(0);
log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@Override
public void onCoinsReceived(BigInteger newBalance)
{
log.info("onCoinsReceived " + newBalance);
}
private String getConfirmationsText(int numBroadcastPeers, int depthInBlocks)
{
depthInBlocks = 0;
return depthInBlocks + " confirmation(s) / " + "Seen by " + numBroadcastPeers + " peer(s)";
}
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
{
depthInBlocks = 0;
if (depthInBlocks > 0)
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
}
}

View File

@ -1,6 +1,6 @@
package io.bitsquare.gui.components.processbar;
import io.bitsquare.gui.util.Utils;
import io.bitsquare.gui.util.GUIUtils;
import javafx.animation.AnimationTimer;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
@ -65,7 +65,7 @@ public class ProcessStepsBuilder
// TODO
// mock simulate network delay
Utils.setTimeout(100, (AnimationTimer animationTimer) -> {
GUIUtils.setTimeout(100, (AnimationTimer animationTimer) -> {
next();
return null;
});

View File

@ -1,7 +1,11 @@
package io.bitsquare.gui.settings;
import com.google.inject.Inject;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.User;
import javafx.fxml.Initializable;
import java.net.URL;
@ -9,15 +13,24 @@ import java.util.ResourceBundle;
public class SettingsController implements Initializable, ChildController
{
private User user;
private Settings settings;
private Storage storage;
private NavigationController navigationController;
@Inject
public SettingsController(User user, Settings settings, Storage storage)
{
this.user = user;
this.settings = settings;
this.storage = storage;
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
}
@Override

View File

@ -10,6 +10,7 @@ import io.bitsquare.btc.WalletFacade;
import io.bitsquare.crypto.CryptoFacade;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.components.ConfirmationComponent;
import io.bitsquare.gui.components.NetworkSyncPane;
import io.bitsquare.gui.components.processbar.ProcessStepBar;
import io.bitsquare.gui.components.processbar.ProcessStepItem;
@ -18,11 +19,10 @@ import io.bitsquare.gui.util.Formatter;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.User;
import io.bitsquare.util.Utils;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.AnchorPane;
@ -48,8 +48,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
private List<ProcessStepItem> processStepItems = new ArrayList();
private NavigationController navigationController;
private ImageView confirmIconImageView;
private TextField balanceLabel, confirmationsLabel, accountHolderName, accountPrimaryID, accountSecondaryID;
private TextField balanceLabel, accountTitle, accountHolderName, accountPrimaryID, accountSecondaryID;
private ComboBox countryComboBox, bankTransferTypeComboBox, currencyComboBox;
private Button addBankAccountButton;
@ -103,8 +102,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
updateCreateAccountButton();
confirmIconImageView.setImage(getConfirmIconImage(numBroadcastPeers, depthInBlocks));
confirmationsLabel.setText(getConfirmationsText(numBroadcastPeers, depthInBlocks));
log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@ -133,24 +131,18 @@ public class SetupController implements Initializable, ChildController, WalletFa
return bankTransferTypeComboBox.getSelectionModel().getSelectedItem() != null
&& countryComboBox.getSelectionModel().getSelectedItem() != null
&& currencyComboBox.getSelectionModel().getSelectedItem() != null
&& accountTitle.getText().length() > 0
&& accountHolderName.getText().length() > 0
&& accountPrimaryID.getText().length() > 0
&& accountSecondaryID.getText().length() > 0
&& accountHolderName.getText().length() > 0
&& accountIDsByBankTransferTypeValid;
}
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
{
if (depthInBlocks > 0)
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
}
private void updateCreateAccountButton()
{
boolean funded = walletFacade.getAccountRegistrationBalance().compareTo(BigInteger.ZERO) > 0;
nextButton.setDisable(!funded || walletFacade.getRegistrationConfirmationDepthInBlocks() == 0);
nextButton.setDisable(!funded || walletFacade.getRegConfDepthInBlocks() == 0);
}
@ -158,11 +150,6 @@ public class SetupController implements Initializable, ChildController, WalletFa
// GUI BUILDER
///////////////////////////////////////////////////////////////////////////////////
private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks)
{
return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)";
}
private void buildStep0()
{
infoLabel.setText("You need to pay 0.01 BTC to the registration address.\n\n" +
@ -174,8 +161,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
int gridRow = -1;
TextField addressLabel = FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow);
addressLabel.setEditable(false);
TextField addressLabel = FormBuilder.addTextField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow, false, true);
Label copyIcon = new Label("");
formGridPane.add(copyIcon, 2, gridRow);
@ -183,14 +169,9 @@ public class SetupController implements Initializable, ChildController, WalletFa
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
balanceLabel = FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow);
balanceLabel.setEditable(false);
balanceLabel = FormBuilder.addTextField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow);
confirmationsLabel = FormBuilder.addInputField(formGridPane, "Confirmations:", getConfirmationsText(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks()), ++gridRow);
confirmationsLabel.setEditable(false);
confirmIconImageView = new ImageView(getConfirmIconImage(walletFacade.getRegistrationConfirmationNumBroadcastPeers(), walletFacade.getRegistrationConfirmationDepthInBlocks()));
formGridPane.add(confirmIconImageView, 2, gridRow);
ConfirmationComponent confirmationComponent = new ConfirmationComponent(walletFacade, formGridPane, ++gridRow);
nextButton.setText("Payment done");
updateCreateAccountButton();
@ -221,13 +202,29 @@ public class SetupController implements Initializable, ChildController, WalletFa
formGridPane.getChildren().clear();
int gridRow = -1;
bankTransferTypeComboBox = FormBuilder.addComboBox(formGridPane, "Bank account type:", settings.getAllBankAccountTypes(), ++gridRow);
bankTransferTypeComboBox = FormBuilder.addComboBox(formGridPane, "Bank account type:", Utils.getAllBankAccountTypes(), ++gridRow);
bankTransferTypeComboBox.setConverter(new StringConverter<BankAccountType>()
{
@Override
public String toString(BankAccountType bankAccountType)
{
return Localisation.get(bankAccountType.toString());
}
@Override
public BankAccountType fromString(String s)
{
return null;
}
});
bankTransferTypeComboBox.setPromptText("Select bank account type");
accountTitle = FormBuilder.addInputField(formGridPane, "Bank account title:", "", ++gridRow);
accountHolderName = FormBuilder.addInputField(formGridPane, "Bank account holder name:", "", ++gridRow);
accountPrimaryID = FormBuilder.addInputField(formGridPane, "Bank account primary ID", "", ++gridRow);
accountSecondaryID = FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", "", ++gridRow);
currencyComboBox = FormBuilder.addComboBox(formGridPane, "Currency used for bank account:", settings.getAllCurrencies(), ++gridRow);
currencyComboBox = FormBuilder.addComboBox(formGridPane, "Currency used for bank account:", Utils.getAllCurrencies(), ++gridRow);
currencyComboBox.setPromptText("Select currency");
currencyComboBox.setConverter(new StringConverter<Currency>()
{
@ -244,7 +241,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
}
});
countryComboBox = FormBuilder.addComboBox(formGridPane, "Country of bank account:", settings.getAllLocales(), ++gridRow);
countryComboBox = FormBuilder.addComboBox(formGridPane, "Country of bank account:", Utils.getAllLocales(), ++gridRow);
countryComboBox.setPromptText("Select country");
countryComboBox.setConverter(new StringConverter<Locale>()
{
@ -270,6 +267,7 @@ public class SetupController implements Initializable, ChildController, WalletFa
skipButton.setText("Register later");
// handlers
accountTitle.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
accountHolderName.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
accountPrimaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
accountSecondaryID.textProperty().addListener((ov, oldValue, newValue) -> checkCreateAccountButtonState());
@ -292,6 +290,8 @@ public class SetupController implements Initializable, ChildController, WalletFa
addBankAccountButton.setOnAction(e -> {
addBankAccount();
storage.write(user.getClass().getName(), user);
if (verifyBankAccountData())
{
bankTransferTypeComboBox.getSelectionModel().clearSelection();
@ -313,13 +313,15 @@ public class SetupController implements Initializable, ChildController, WalletFa
user.setAccountID(walletFacade.getAccountRegistrationAddress().toString());
user.setMessageID(walletFacade.getAccountRegistrationPubKey().toString());
storage.saveUser(user);
storage.write(user.getClass().getName(), user);
processStepBar.next();
buildStep2();
} catch (InsufficientMoneyException e1)
{
log.warn(e1.toString());
// TODO
processStepBar.next();
buildStep2();
}
}
else
@ -336,12 +338,14 @@ public class SetupController implements Initializable, ChildController, WalletFa
{
if (verifyBankAccountData())
{
BankAccount bankAccount = new BankAccount((BankAccountType) bankTransferTypeComboBox.getSelectionModel().getSelectedItem(),
accountPrimaryID.getText(),
accountSecondaryID.getText(),
accountHolderName.getText(),
BankAccount bankAccount = new BankAccount(
(BankAccountType) bankTransferTypeComboBox.getSelectionModel().getSelectedItem(),
(Currency) currencyComboBox.getSelectionModel().getSelectedItem(),
(Locale) countryComboBox.getSelectionModel().getSelectedItem(),
(Currency) currencyComboBox.getSelectionModel().getSelectedItem());
accountTitle.getText(),
accountHolderName.getText(),
accountPrimaryID.getText(),
accountSecondaryID.getText());
user.addBankAccount(bankAccount);
}
}
@ -360,20 +364,20 @@ public class SetupController implements Initializable, ChildController, WalletFa
formGridPane.getChildren().clear();
int gridRow = -1;
List<BankAccount> bankAccounts = user.getBankAccounts();
Iterator iterator = bankAccounts.iterator();
Iterator<BankAccount> iterator = bankAccounts.iterator();
int index = 0;
while (iterator.hasNext())
{
FormBuilder.addHeaderLabel(formGridPane, "Bank account " + (index + 1), ++gridRow);
Map.Entry<String, BankAccount> entry = (Map.Entry) iterator.next();
BankAccount bankAccount = iterator.next();
// need to get updated gridRow from subroutine
gridRow = buildBankAccountDetails(entry.getValue(), ++gridRow);
gridRow = buildBankAccountDetails(bankAccount, ++gridRow);
FormBuilder.addVSpacer(formGridPane, ++gridRow);
index++;
}
FormBuilder.addVSpacer(formGridPane, ++gridRow);
FormBuilder.addInputField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow).setMouseTransparent(true);
FormBuilder.addTextField(formGridPane, "Registration address:", walletFacade.getAccountRegistrationAddress().toString(), ++gridRow);
FormBuilder.addTextField(formGridPane, "Balance:", Formatter.formatSatoshis(walletFacade.getAccountRegistrationBalance(), true), ++gridRow);
nextButton.setText("Done");
skipButton.setOpacity(0);
@ -385,11 +389,13 @@ public class SetupController implements Initializable, ChildController, WalletFa
// util
private int buildBankAccountDetails(BankAccount bankAccount, int row)
{
FormBuilder.addInputField(formGridPane, "Bank account holder name:", bankAccount.getAccountHolderName(), ++row).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Bank account type", bankAccount.getBankAccountType().toString(), ++row).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Bank account primary ID", bankAccount.getAccountPrimaryID(), ++row).setMouseTransparent(true);
FormBuilder.addInputField(formGridPane, "Bank account secondary ID:", bankAccount.getAccountSecondaryID(), ++row).setMouseTransparent(true);
FormBuilder.addTextField(formGridPane, "Bank account holder name:", bankAccount.getAccountHolderName(), ++row);
FormBuilder.addTextField(formGridPane, "Bank account type", bankAccount.getBankAccountType().toString(), ++row);
FormBuilder.addTextField(formGridPane, "Bank account primary ID", bankAccount.getAccountPrimaryID(), ++row);
FormBuilder.addTextField(formGridPane, "Bank account secondary ID:", bankAccount.getAccountSecondaryID(), ++row);
return row;
}
}

View File

@ -4,7 +4,7 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="rootContainer" fx:controller="io.bitsquare.gui.setup.SetupController"
xmlns:fx="http://javafx.com/fxml" minHeight="300" minWidth="400" prefHeight="600" prefWidth="800">
xmlns:fx="http://javafx.com/fxml">
<ScrollPane fitToWidth="true" AnchorPane.leftAnchor="10" AnchorPane.rightAnchor="10" AnchorPane.topAnchor="10"
AnchorPane.bottomAnchor="30">
<content>

View File

@ -84,5 +84,14 @@ public class TradeController implements Initializable, NavigationController, Chi
orderBookController.setDirection(direction);
}
public void cleanup()
{
if (orderBookController != null)
{
orderBookController.cleanup();
orderBookController = null;
}
}
}

View File

@ -1,77 +1,65 @@
package io.bitsquare.gui.trade.offer;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.inject.Inject;
import io.bitsquare.btc.Fees;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.Converter;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.settings.OrderBookFilterSettings;
import io.bitsquare.gui.components.ConfirmationComponent;
import io.bitsquare.gui.util.*;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.OfferConstraints;
import io.bitsquare.trade.Trading;
import io.bitsquare.trade.orderbook.OrderBook;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.GridPane;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.net.URL;
import java.util.ArrayList;
import java.util.Currency;
import java.util.ResourceBundle;
import java.util.UUID;
public class CreateOfferController implements Initializable, ChildController
public class CreateOfferController implements Initializable, ChildController, WalletFacade.WalletListener
{
private static final Logger log = LoggerFactory.getLogger(CreateOfferController.class);
private NavigationController navigationController;
private Trading trading;
private OrderBookFilterSettings orderBookFilterSettings;
private WalletFacade walletFacade;
private Settings settings;
private User user;
private double filterPaneItemOffset;
private Direction direction;
@FXML
public AnchorPane holderPane;
@FXML
public Pane detailsPane;
private Button placeOfferButton;
private int gridRow;
@FXML
private AnchorPane holderPane;
@FXML
private GridPane formGridPane;
@FXML
public Label buyLabel;
@FXML
public TextField volume;
@FXML
public ImageView directionImageView;
@FXML
public TextField amount;
@FXML
public TextField price;
@FXML
public TextField minAmount;
@FXML
public Button placeOfferButton;
public TextField volume, amount, price, minAmount;
@Inject
public CreateOfferController(Trading trading, OrderBookFilterSettings orderBookFilterSettings, Settings settings, User user)
public CreateOfferController(Trading trading, WalletFacade walletFacade, Settings settings, User user)
{
this.trading = trading;
this.orderBookFilterSettings = orderBookFilterSettings;
this.walletFacade = walletFacade;
this.settings = settings;
this.user = user;
}
@ -79,14 +67,34 @@ public class CreateOfferController implements Initializable, ChildController
@Override
public void initialize(URL url, ResourceBundle rb)
{
createFilterPane();
walletFacade.addRegistrationWalletListener(this);
gridRow = 2;
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)
{
setVolume();
updateVolume();
}
});
@ -95,23 +103,66 @@ public class CreateOfferController implements Initializable, ChildController
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue)
{
setVolume();
updateVolume();
}
});
placeOfferButton.setOnAction(e -> {
// TODO not impl yet. use mocks
OfferConstraints offerConstraints = new OrderBook(settings).getRandomOfferConstraints();
Offer offer = new Offer(UUID.randomUUID(),
direction,
Converter.convertToDouble(price.getText()),
Converter.convertToDouble(amount.getText()),
Converter.convertToDouble(minAmount.getText()),
settings.getCurrency(),
user,
offerConstraints);
trading.placeNewOffer(offer);
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.getAcceptedCountryLocales(),
settings.getAcceptedLanguageLocales());
try
{
String txID = trading.placeNewOffer(offer);
formGridPane.getChildren().remove(placeOfferButton);
placeOfferTitle.setText("Transaction sent:");
buildConfirmationView(txID);
} catch (InsufficientMoneyException e1)
{
//TODO popup
log.error(e.toString());
}
}
});
}
@Override
public void onConfidenceChanged(int numBroadcastPeers, int depthInBlocks)
{
log.info("onConfidenceChanged " + numBroadcastPeers + " / " + depthInBlocks);
}
@Override
public void onCoinsReceived(BigInteger newBalance)
{
log.info("onCoinsReceived " + newBalance);
}
private void buildConfirmationView(String txID)
{
FormBuilder.addTextField(formGridPane, "Transaction ID:", txID, ++gridRow, false, true);
ConfirmationComponent confirmationComponent = new ConfirmationComponent(walletFacade, formGridPane, ++gridRow);
Button closeButton = new Button("Close");
formGridPane.add(closeButton, 1, ++gridRow);
closeButton.setDefaultButton(true);
closeButton.setOnAction(e -> {
TabPane tabPane = ((TabPane) (holderPane.getParent().getParent()));
tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
@ -119,6 +170,7 @@ public class CreateOfferController implements Initializable, ChildController
});
}
@Override
public void setNavigationController(NavigationController navigationController)
{
@ -132,140 +184,36 @@ public class CreateOfferController implements Initializable, ChildController
minAmount.setText(Formatter.formatPrice(orderBookFilter.getAmount()));
price.setText(Formatter.formatPrice(orderBookFilter.getPrice()));
configDirection();
String iconPath = (direction == Direction.BUY) ? Icons.BUY : Icons.SELL;
buyLabel.setText(Formatter.formatDirection(direction, false) + ":");
updateVolume();
}
private void configDirection()
//TODO
private boolean inputValid()
{
String iconPath;
String buyLabelText;
if (direction == Direction.BUY)
{
iconPath = "/images/buy.png";
buyLabelText = "BUY";
}
return true;
}
private void updateVolume()
{
double amountAsDouble = Converter.stringToDouble(amount.getText());
double priceAsDouble = Converter.stringToDouble(price.getText());
volume.setText(Formatter.formatPrice(amountAsDouble * priceAsDouble));
}
private Image getConfirmIconImage(int numBroadcastPeers, int depthInBlocks)
{
if (depthInBlocks > 0)
return Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
{
iconPath = "/images/sell.png";
buyLabelText = "SELL";
}
Image icon = new Image(getClass().getResourceAsStream(iconPath));
directionImageView.setImage(icon);
buyLabel.setText(buyLabelText);
return Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
}
private void createFilterPane()
private String getConfirmationsText(int registrationConfirmationNumBroadcastPeers, int registrationConfirmationDepthInBlocks)
{
filterPaneItemOffset = 30;
ArrayList<Currency> currencies = orderBookFilterSettings.getCurrencies();
Currency currency = orderBookFilterSettings.getCurrency();
ComboBox currencyComboBox = createCurrencyItem("Currency: ", currency, currencies);
currencyComboBox.valueProperty().addListener(new ChangeListener<Currency>()
{
@Override
public void changed(ObservableValue ov, Currency oldValue, Currency newValue)
{
orderBookFilterSettings.setCurrency(newValue);
}
});
Label bankLabel = createFilterItem("Bank transfer types: ", "SEPA, OKPAY");
Label countriesLabel = createFilterItem("Countries: ", "DE, GB, AT");
Label languagesLabel = createFilterItem("Languages: ", "DE, EN");
Label arbitratorsLabel = createFilterItem("Arbitrators: ", "Paysty, BitRated");
Label identityLabel = createFilterItem("Identity verifications: ", "Passport, Google+, Facebook, Skype");
TextField collateralLabel = createCollateralItem("Collateral (%): ", 10);
return registrationConfirmationDepthInBlocks + " confirmation(s) / " + "Seen by " + registrationConfirmationNumBroadcastPeers + " peer(s)";
}
private ComboBox createCurrencyItem(String labelText, Currency currency, ArrayList<Currency> currencies)
{
final Separator separator = new Separator();
separator.setPrefWidth(380);
separator.setLayoutY(0 + filterPaneItemOffset);
separator.setLayoutX(0);
final Label label = new Label(labelText);
label.setLayoutY(10 + filterPaneItemOffset);
ObservableList<Currency> options = FXCollections.observableArrayList(currencies);
final ComboBox comboBox = new ComboBox(options);
comboBox.setLayoutX(70);
comboBox.setLayoutY(5 + filterPaneItemOffset);
comboBox.setValue(currency);
detailsPane.getChildren().addAll(separator, label, comboBox);
filterPaneItemOffset += 40;
return comboBox;
}
private Label createFilterItem(String labelText, String valueText)
{
final Separator separator = new Separator();
separator.setPrefWidth(380);
separator.setLayoutY(0 + filterPaneItemOffset);
separator.setLayoutX(0);
final Label label = new Label(labelText + valueText);
label.setLayoutY(10 + filterPaneItemOffset);
label.setPrefWidth(310);
Tooltip tooltip = new Tooltip(valueText);
label.setTooltip(tooltip);
final Button edit = new Button("Edit");
edit.setPrefWidth(50);
edit.setLayoutX(330);
edit.setLayoutY(5 + filterPaneItemOffset);
detailsPane.getChildren().addAll(separator, label, edit);
filterPaneItemOffset += 40;
return label;
}
private TextField createCollateralItem(String labelText, double collateral)
{
final Separator separator = new Separator();
separator.setPrefWidth(380);
separator.setLayoutY(0 + filterPaneItemOffset);
separator.setLayoutX(0);
final Label label = new Label(labelText);
label.setLayoutY(10 + filterPaneItemOffset);
label.setPrefWidth(310);
final TextField collateralValue = new TextField(Double.toString(collateral));
collateralValue.setLayoutX(90);
collateralValue.setLayoutY(5 + filterPaneItemOffset);
collateralValue.setPrefWidth(50);
detailsPane.getChildren().addAll(separator, label, collateralValue);
filterPaneItemOffset += 40;
return collateralValue;
}
private double textInputToNumber(String oldValue, String newValue)
{
//TODO use regex.... or better custom textfield component
double d = 0.0;
if (!newValue.equals(""))
{
d = Converter.convertToDouble(newValue);
if (d == Double.NEGATIVE_INFINITY)
{
amount.setText(oldValue);
d = Converter.convertToDouble(oldValue);
}
}
return d;
}
private void setVolume()
{
double a = textInputToNumber(amount.getText(), amount.getText());
double p = textInputToNumber(price.getText(), price.getText());
volume.setText(Formatter.formatPrice(a * p));
}
}

View File

@ -1,78 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<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"
fx:controller="io.bitsquare.gui.trade.offer.CreateOfferController">
<children>
<HBox prefHeight="22.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
<children>
<ImageView fx:id="directionImageView"/>
<VBox spacing="10" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"
AnchorPane.bottomAnchor="10.0">
<GridPane fx:id="formGridPane" vgap="5" hgap="5">
<children>
<Label id="form-header-text" text="Create new offer:" GridPane.rowIndex="0"
GridPane.columnIndex="0"/>
<Label fx:id="buyLabel" text="Buy">
<padding>
<Insets left="4.0" right="4.0" top="5.0"/>
</padding>
</Label>
<Label fx:id="buyLabel" text="Buy" GridPane.rowIndex="1" GridPane.columnIndex="0"/>
<TextField fx:id="amount" prefHeight="26.0" prefWidth="70.0" alignment="CENTER_RIGHT">
<HBox.margin>
<Insets left="0.0"/>
</HBox.margin>
</TextField>
<Label text="BTC for">
<padding>
<Insets left="4.0" right="4.0" top="5.0"/>
</padding>
</Label>
<TextField fx:id="price" prefHeight="26.0" prefWidth="70.0" alignment="CENTER_RIGHT"/>
<Label text="EUR =">
<padding>
<Insets left="4.0" right="4.0" top="5.0"/>
</padding>
</Label>
<TextField fx:id="volume" prefHeight="26.0" prefWidth="70.0" alignment="CENTER_RIGHT" editable="false"/>
<Label prefHeight="21.0" text="EUR in total (Min. Amount:">
<padding>
<Insets left="4.0" right="4.0" top="5.0"/>
</padding>
<HBox.margin>
<Insets/>
</HBox.margin>
</Label>
<TextField fx:id="minAmount" prefHeight="26.0" prefWidth="70.0" alignment="CENTER_RIGHT"/>
<Label text="BTC)">
<padding>
<Insets left="4.0" right="4.0" top="5.0"/>
</padding>
</Label>
<HBox GridPane.rowIndex="1" GridPane.columnIndex="1" GridPane.hgrow="NEVER" spacing="5"
alignment="CENTER_RIGHT">
<children>
<TextField fx:id="amount" prefWidth="70.0" alignment="CENTER_RIGHT"/>
<Label text="BTC for:"/>
<TextField fx:id="price" prefWidth="70.0" alignment="CENTER_RIGHT"/>
<Label text="EUR ="/>
<TextField fx:id="volume" prefWidth="70.0" alignment="CENTER_RIGHT"
mouseTransparent="true"/>
<Label text="EUR in total"/>
</children>
</HBox>
</children>
</HBox>
<Label text="Min. Amount:" GridPane.rowIndex="2" GridPane.columnIndex="0"/>
<Pane fx:id="detailsPane" AnchorPane.topAnchor="50.0"
AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0">
<TextField fx:id="minAmount" GridPane.rowIndex="2" GridPane.columnIndex="1"/>
<Label text="Offer details:">
<font>
<Font size="18.0"/>
</font>
</Label>
</Pane>
</children>
<Label text="Place offer" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="380.0">
<font>
<Font size="18.0"/>
</font>
</Label>
<Separator AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="405.0"/>
<Label text="Offer fee: 0.01 BTC" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="415.0"/>
<Button fx:id="placeOfferButton" text="Place offer" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="440.0"/>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/>
</padding>
<columnConstraints>
<ColumnConstraints halignment="RIGHT"/>
<ColumnConstraints halignment="LEFT"/>
<ColumnConstraints halignment="LEFT"/>
</columnConstraints>
</GridPane>
</VBox>
</children>
</AnchorPane>

View File

@ -10,14 +10,14 @@ import io.bitsquare.gui.util.Converter;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.orderbook.OrderBook;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Pos;
@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
@ -43,10 +42,11 @@ public class OrderBookController implements Initializable, ChildController
private NavigationController navigationController;
private OrderBook orderBook;
private OrderBookListItem selectedOrderBookListItem;
private SortedList<OrderBookListItem> offerList;
private final OrderBookFilter orderBookFilter;
private User user;
private Button createOfferButton;
private Image buyIcon = Icons.getIconImage(Icons.BUY);
private Image sellIcon = Icons.getIconImage(Icons.SELL);
@ -61,22 +61,32 @@ public class OrderBookController implements Initializable, ChildController
@FXML
public TableColumn priceColumn, amountColumn, volumeColumn;
@FXML
private TableColumn<OrderBookListItem, OrderBookListItem> directionColumn, countryColumn, bankAccountTypeColumn;
private TableColumn<String, OrderBookListItem> directionColumn, countryColumn, bankAccountTypeColumn;
@FXML
public Button createOfferButton;
@Inject
public OrderBookController(OrderBook orderBook, OrderBookFilter orderBookFilter)
public OrderBookController(OrderBook orderBook, OrderBookFilter orderBookFilter, User user)
{
this.orderBook = orderBook;
this.orderBookFilter = orderBookFilter;
this.user = user;
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
// setup table
setCountryColumnCellFactory();
setBankAccountTypeColumnCellFactory();
setDirectionColumnCellFactory();
offerList = orderBook.getOfferList();
offerList.comparatorProperty().bind(orderBookTable.comparatorProperty());
orderBookTable.setItems(offerList);
orderBookTable.getSortOrder().add(priceColumn);
orderBookTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
// handlers
amount.textProperty().addListener(new ChangeListener<String>()
{
@Override
@ -97,10 +107,6 @@ public class OrderBookController implements Initializable, ChildController
}
});
orderBookTable.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
selectedOrderBookListItem = orderBookTable.getSelectionModel().getSelectedItem();
});
orderBookFilter.getChangedProperty().addListener(new ChangeListener<Boolean>()
{
@Override
@ -109,8 +115,19 @@ public class OrderBookController implements Initializable, ChildController
updateOfferList();
}
});
user.getChangedProperty().addListener(new ChangeListener<Boolean>()
{
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue)
{
updateOfferList();
}
});
updateOfferList();
createOfferButton.setOnAction(e -> {
ChildController nextController = navigationController.navigateToView(NavigationController.TRADE__CREATE_OFFER, "Create offer");
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
});
}
@Override
@ -126,6 +143,13 @@ public class OrderBookController implements Initializable, ChildController
orderBookFilter.setDirection(direction);
}
public void cleanup()
{
orderBookTable.setItems(null);
orderBookTable.getSortOrder().clear();
offerList.comparatorProperty().unbind();
}
private void openTradeTab(OrderBookListItem orderBookListItem)
{
String title = orderBookListItem.getOffer().getDirection() == Direction.BUY ? "Trade: Sell Bitcoin" : "Trade: Buy Bitcoin";
@ -133,57 +157,31 @@ public class OrderBookController implements Initializable, ChildController
double requestedAmount = orderBookListItem.getOffer().getAmount();
if (!amount.getText().equals(""))
requestedAmount = Converter.convertToDouble(amount.getText());
requestedAmount = Converter.stringToDouble(amount.getText());
tradeProcessController.initView(orderBookListItem.getOffer(), requestedAmount);
}
private void displayCreateOfferButton()
{
if (createOfferButton == null)
{
createOfferButton = new Button("Create new offer");
holderPane.setBottomAnchor(createOfferButton, 360.0);
holderPane.setLeftAnchor(createOfferButton, 10.0);
holderPane.getChildren().add(createOfferButton);
createOfferButton.setOnAction(e -> {
ChildController nextController = navigationController.navigateToView(NavigationController.TRADE__CREATE_OFFER, "Create offer");
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
});
}
createOfferButton.setVisible(true);
holderPane.setBottomAnchor(orderBookTable, 390.0);
}
private void updateOfferList()
{
ObservableList offers = orderBook.getFilteredList(orderBookFilter);
orderBookTable.setItems(offers);
orderBookTable.getSortOrder().add(priceColumn);
priceColumn.setSortType((orderBookFilter.getDirection() == Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
orderBook.updateFilter(orderBookFilter);
if (offers.size() == 0)
{
displayCreateOfferButton();
}
else if (createOfferButton != null)
{
createOfferButton.setVisible(false);
holderPane.setBottomAnchor(orderBookTable, 10.0);
}
priceColumn.setSortType((orderBookFilter.getDirection() == Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
orderBookTable.sort();
if (orderBookTable.getItems() != null)
createOfferButton.setDefaultButton(orderBookTable.getItems().size() == 0);
}
private void setDirectionColumnCellFactory()
{
directionColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
directionColumn.setCellFactory(new Callback<TableColumn<OrderBookListItem, OrderBookListItem>, TableCell<OrderBookListItem, OrderBookListItem>>()
directionColumn.setCellFactory(new Callback<TableColumn<String, OrderBookListItem>, TableCell<String, OrderBookListItem>>()
{
@Override
public TableCell<OrderBookListItem, OrderBookListItem> call(TableColumn<OrderBookListItem, OrderBookListItem> directionColumn)
public TableCell<String, OrderBookListItem> call(TableColumn<String, OrderBookListItem> directionColumn)
{
return new TableCell<OrderBookListItem, OrderBookListItem>()
return new TableCell<String, OrderBookListItem>()
{
final ImageView iconView = new ImageView();
final Button button = new Button();
@ -216,6 +214,7 @@ public class OrderBookController implements Initializable, ChildController
button.setText(title);
setGraphic(button);
button.setDefaultButton(getIndex() == 0);
button.setOnAction(event -> openTradeTab(orderBookListItem));
}
else
@ -231,12 +230,12 @@ public class OrderBookController implements Initializable, ChildController
private void setCountryColumnCellFactory()
{
countryColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
countryColumn.setCellFactory(new Callback<TableColumn<OrderBookListItem, OrderBookListItem>, TableCell<OrderBookListItem, OrderBookListItem>>()
countryColumn.setCellFactory(new Callback<TableColumn<String, OrderBookListItem>, TableCell<String, OrderBookListItem>>()
{
@Override
public TableCell<OrderBookListItem, OrderBookListItem> call(TableColumn<OrderBookListItem, OrderBookListItem> directionColumn)
public TableCell<String, OrderBookListItem> call(TableColumn<String, OrderBookListItem> directionColumn)
{
return new TableCell<OrderBookListItem, OrderBookListItem>()
return new TableCell<String, OrderBookListItem>()
{
final HBox hBox = new HBox();
@ -251,44 +250,19 @@ public class OrderBookController implements Initializable, ChildController
{
super.updateItem(orderBookListItem, empty);
hBox.getChildren().clear();
if (orderBookListItem != null)
{
hBox.getChildren().clear();
setText("");
List<Locale> countryLocales = orderBookListItem.getOffer().getOfferConstraints().getCountryLocales();
int i = 0;
String countries = "";
for (Locale countryLocale : countryLocales)
Locale countryLocale = orderBookListItem.getOffer().getBankAccountCountryLocale();
try
{
countries += countryLocale.getDisplayCountry();
if (i < countryLocales.size() - 1)
countries += ", ";
hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png"));
if (i < 4)
{
try
{
ImageView imageView = Icons.getIconImageView("/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png");
hBox.getChildren().add(imageView);
} catch (Exception e)
{
log.warn("Country icon not found: " + "/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png country name: " + countryLocale.getDisplayCountry());
}
}
else
{
setText("...");
}
i++;
} catch (Exception e)
{
log.warn("Country icon not found: " + "/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png country name: " + countryLocale.getDisplayCountry());
}
Tooltip.install(this, new Tooltip(countries));
}
else
{
setText("");
hBox.getChildren().clear();
Tooltip.install(this, new Tooltip(countryLocale.getDisplayCountry()));
}
}
};
@ -299,12 +273,12 @@ public class OrderBookController implements Initializable, ChildController
private void setBankAccountTypeColumnCellFactory()
{
bankAccountTypeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
bankAccountTypeColumn.setCellFactory(new Callback<TableColumn<OrderBookListItem, OrderBookListItem>, TableCell<OrderBookListItem, OrderBookListItem>>()
bankAccountTypeColumn.setCellFactory(new Callback<TableColumn<String, OrderBookListItem>, TableCell<String, OrderBookListItem>>()
{
@Override
public TableCell<OrderBookListItem, OrderBookListItem> call(TableColumn<OrderBookListItem, OrderBookListItem> directionColumn)
public TableCell<String, OrderBookListItem> call(TableColumn<String, OrderBookListItem> directionColumn)
{
return new TableCell<OrderBookListItem, OrderBookListItem>()
return new TableCell<String, OrderBookListItem>()
{
@Override
public void updateItem(final OrderBookListItem orderBookListItem, boolean empty)
@ -313,19 +287,8 @@ public class OrderBookController implements Initializable, ChildController
if (orderBookListItem != null)
{
List<BankAccountType.BankAccountTypeEnum> bankAccountTypeEnums = orderBookListItem.getOffer().getOfferConstraints().getBankAccountTypes();
String text = "";
int i = 0;
for (BankAccountType.BankAccountTypeEnum bankAccountTypeEnum : bankAccountTypeEnums)
{
text += Localisation.get(bankAccountTypeEnum.toString());
i++;
if (i < bankAccountTypeEnums.size())
text += ", ";
}
setText(text);
if (text.length() > 20)
Tooltip.install(this, new Tooltip(text));
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum = orderBookListItem.getOffer().getBankAccountTypeEnum();
setText(Localisation.get(bankAccountTypeEnum.toString()));
}
else
{
@ -345,12 +308,12 @@ public class OrderBookController implements Initializable, ChildController
{
try
{
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Settings.getLocale());
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
d = decimalFormat.parse(newValue).doubleValue();
} catch (ParseException e)
{
amount.setText(oldValue);
d = Converter.convertToDouble(oldValue);
d = Converter.stringToDouble(oldValue);
}
}
return d;
@ -363,5 +326,23 @@ public class OrderBookController implements Initializable, ChildController
volume.setText(Formatter.formatPrice(a * p));
}
// the scrollbar width is not handled correctly from the layout initially
/* private void forceTableLayoutUpdate()
{
final List<OrderBookListItem> items = orderBookTable.getItems();
if (items == null || items.size() == 0) return;
final OrderBookListItem item = orderBookTable.getItems().get(0);
items.remove(0);
Platform.runLater(new Runnable()
{
@Override
public void run()
{
items.add(0, item);
}
});
} */
}

View File

@ -1,134 +0,0 @@
package io.bitsquare.gui.trade.orderbook;
import io.bitsquare.gui.components.VSpacer;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.settings.Settings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Pane;
import java.util.*;
public class OrderBookFilterTextItemBuilder
{
public static void build(Pane parent, String title, List<String> values, List<String> allValues)
{
final Pane pane = new Pane();
pane.setPrefHeight(23);
final Label titleLabel = new Label(title);
titleLabel.setLayoutY(4);
titleLabel.setId("form-title");
FlowPane flowPane = new FlowPane();
double xPos = 170.0;
double yPos = 5.0;
List<String> openValues = new ArrayList<>(allValues);
openValues.removeAll(values);
ObservableList<String> observableList = FXCollections.observableArrayList(openValues);
Collections.sort(observableList);
ComboBox comboBox = new ComboBox(observableList);
comboBox.setLayoutX(xPos);
comboBox.setLayoutY(yPos);
comboBox.setClip(Icons.getIconImageView(Icons.ADD));
comboBox.setValue(Settings.getCurrency());
comboBox.valueProperty().addListener(new ChangeListener<Object>()
{
@Override
public void changed(ObservableValue ov, Object oldValue, Object newValue)
{
if (newValue != null)
{
String value;
if (newValue instanceof Currency)
value = ((Currency) newValue).getCurrencyCode();
else
value = (String) newValue;
if (flowPane.getChildren().size() > 0)
{
Pane lastItem = (Pane) flowPane.getChildren().get(flowPane.getChildren().size() - 1);
Button button = (Button) lastItem.getChildren().get(0);
button.setText(button.getText().substring(0, button.getText().length() - 2) + ", ");
}
addRemovableItem(flowPane, value + " ", observableList);
comboBox.getSelectionModel().clearSelection();
observableList.remove(newValue);
}
}
});
// combobox does not support icon (mask background with icon), so we need a graphic here
ImageView addImageView = Icons.getIconImageView(Icons.ADD);
addImageView.setLayoutX(xPos);
addImageView.setLayoutY(yPos);
addImageView.setMouseTransparent(true);
pane.getChildren().addAll(titleLabel, comboBox, addImageView);
Iterator<String> iterator = values.iterator();
for (Iterator<String> stringIterator = iterator; stringIterator.hasNext(); )
{
String value = stringIterator.next();
if (stringIterator.hasNext())
addRemovableItem(flowPane, value + ", ", observableList);
else
addRemovableItem(flowPane, value + " ", observableList);
}
parent.getChildren().addAll(pane, flowPane, new VSpacer(3), new Separator(), new VSpacer(10));
}
private static void addRemovableItem(FlowPane flowPane, String text, ObservableList<String> observableList)
{
Pane pane = new Pane();
Button icon = new Button("", Icons.getIconImageView(Icons.REMOVE));
icon.setStyle("-fx-background-color: transparent;");
icon.setPadding(new Insets(-5.0, 0.0, 0.0, 0.0));
icon.setVisible(false);
Button button = new Button(text);
button.setStyle("-fx-background-color: transparent;");
button.setPadding(new Insets(0.0, 0.0, 0.0, 0.0));
pane.setOnMouseEntered(e -> {
icon.setVisible(true);
icon.setLayoutX(button.getWidth() - 7);
});
pane.setOnMouseExited(e -> {
icon.setVisible(false);
icon.setLayoutX(0);
});
icon.setOnAction(e -> {
flowPane.getChildren().remove(button.getParent());
observableList.add(text);
Collections.sort(observableList);
if (flowPane.getChildren().size() > 0)
{
Pane lastItem = (Pane) flowPane.getChildren().get(flowPane.getChildren().size() - 1);
Button lastButton = (Button) lastItem.getChildren().get(0);
lastButton.setText(lastButton.getText().substring(0, lastButton.getText().length() - 2) + " ");
}
});
pane.getChildren().addAll(button, icon);
flowPane.getChildren().add(pane);
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.*?>
<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"
@ -40,27 +40,31 @@
</children>
</HBox>
<Button fx:id="createOfferButton" text="Create new offer" AnchorPane.topAnchor="10.0"
AnchorPane.rightAnchor="10.0"/>
<TableView fx:id="orderBookTable" id="orderbook-table" AnchorPane.leftAnchor="10.0"
AnchorPane.topAnchor="40.0" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0">
AnchorPane.topAnchor="45.0" AnchorPane.bottomAnchor="10.0" AnchorPane.rightAnchor="10.0">
<columns>
<TableColumn text="Amount (Min.)" fx:id="amountColumn" prefWidth="120">
<TableColumn text="Amount (Min.)" fx:id="amountColumn" minWidth="120">
<cellValueFactory>
<PropertyValueFactory property="amount"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Price" fx:id="priceColumn" prefWidth="100">
<TableColumn text="Price" fx:id="priceColumn" minWidth="70">
<cellValueFactory>
<PropertyValueFactory property="price"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Volume (Min.)" fx:id="volumeColumn" prefWidth="160">
<TableColumn text="Volume (Min.)" fx:id="volumeColumn" minWidth="130">
<cellValueFactory>
<PropertyValueFactory property="volume"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Country" fx:id="countryColumn" prefWidth="100" sortable="false"/>
<TableColumn text="Bank transfer type" fx:id="bankAccountTypeColumn" prefWidth="180"/>
<TableColumn text="" fx:id="directionColumn" prefWidth="100" sortable="false"/>
<TableColumn text="Country" fx:id="countryColumn" minWidth="60"/>
<TableColumn text="Bank transfer type" fx:id="bankAccountTypeColumn" minWidth="140"/>
<TableColumn text="" fx:id="directionColumn" minWidth="80" sortable="false"/>
</columns>
</TableView>

View File

@ -45,7 +45,7 @@ public class TradeProcessController implements Initializable, ChildController
private TextField amountTextField;
private Label offererPubKeyLabel, offererAccountPrimaryID, offererAccountSecondaryIDLabel,
offererAccountHolderNameLabel, feedbackLabel, infoLabel, totalLabel, volumeLabel, totalToPayLabel,
totalToReceiveLabel, collateralLabel1, collateralLabel2, amountLabel;
/*totalToReceiveLabel,*/ amountLabel;
private Pane progressPane;
private ProgressBar progressBar;
private ProgressIndicator progressIndicator;
@ -90,7 +90,7 @@ public class TradeProcessController implements Initializable, ChildController
private void trade()
{
double requestedAmount = Converter.convertToDouble(amountTextField.getText());
double requestedAmount = Converter.stringToDouble(amountTextField.getText());
if (requestedAmount <= offer.getAmount() && requestedAmount >= offer.getMinAmount())
{
amountTextField.setEditable(false);
@ -137,7 +137,7 @@ public class TradeProcessController implements Initializable, ChildController
{
trading.sendTakeOfferRequest(trade);
feedbackLabel.setText("Request take offer confirmation from peer.");
Utils.setTimeout(500, (AnimationTimer animationTimer) -> {
GUIUtils.setTimeout(500, (AnimationTimer animationTimer) -> {
onTakeOfferRequestConfirmed();
progressBar.setProgress(1.0 / 3.0);
return null;
@ -149,7 +149,7 @@ public class TradeProcessController implements Initializable, ChildController
trading.payOfferFee(trade);
feedbackLabel.setText("Request offer fee payment confirmation from peer.");
Utils.setTimeout(500, (AnimationTimer animationTimer) -> {
GUIUtils.setTimeout(500, (AnimationTimer animationTimer) -> {
onOfferFeePaymentConfirmed();
progressBar.setProgress(2.0 / 3.0);
return null;
@ -160,7 +160,7 @@ public class TradeProcessController implements Initializable, ChildController
{
trading.requestOffererDetailData();
feedbackLabel.setText("Request detail data from peer.");
Utils.setTimeout(500, (AnimationTimer animationTimer) -> {
GUIUtils.setTimeout(500, (AnimationTimer animationTimer) -> {
onUserDetailsReceived();
progressBar.setProgress(1.0);
return null;
@ -187,7 +187,7 @@ public class TradeProcessController implements Initializable, ChildController
infoLabel = new Label("Wait for Bank transfer.");
vBox.getChildren().addAll(infoLabel);
Utils.setTimeout(2000, (AnimationTimer animationTimer) -> {
GUIUtils.setTimeout(2000, (AnimationTimer animationTimer) -> {
onBankTransferInited();
return null;
});
@ -218,7 +218,7 @@ public class TradeProcessController implements Initializable, ChildController
summaryGridPane.setPadding(new Insets(5, 5, 5, 5));
FormBuilder.addLabel(summaryGridPane, "You have payed:", getTotalToPay(), ++row);
FormBuilder.addLabel(summaryGridPane, "You have received:\n ", getTotalToReceive(), ++row);
// FormBuilder.addLabel(summaryGridPane, "You have received:\n ", getTotalToReceive(), ++row);
TitledPane summaryTitlePane = new TitledPane("Trade summary:", summaryGridPane);
summaryTitlePane.setCollapsible(false);
@ -235,7 +235,6 @@ public class TradeProcessController implements Initializable, ChildController
private void buildStep1()
{
OfferConstraints offerConstraints = offer.getOfferConstraints();
User taker = contract.getTaker();
User offerer = contract.getOfferer();
@ -245,13 +244,13 @@ public class TradeProcessController implements Initializable, ChildController
offerDetailsGridPane.setHgap(5);
offerDetailsGridPane.setPadding(new Insets(5, 5, 5, 5));
amountTextField = FormBuilder.addInputField(offerDetailsGridPane, "Amount (BTC):", Formatter.formatAmount(getAmount()), ++row);
amountTextField = FormBuilder.addTextField(offerDetailsGridPane, "Amount (BTC):", Formatter.formatAmount(getAmount()), ++row);
amountTextField.textProperty().addListener(e -> {
setTotal();
setVolume();
setCollateral();
//setCollateral();
totalToPayLabel.setText(getTotalToPay());
totalToReceiveLabel.setText(getTotalToReceive());
// totalToReceiveLabel.setText(getTotalToReceive());
amountLabel.setText(amountTextField.getText());
});
@ -261,11 +260,10 @@ public class TradeProcessController implements Initializable, ChildController
FormBuilder.addLabel(offerDetailsGridPane, "Price:", Formatter.formatPriceWithCurrencyPair(offer.getPrice(), offer.getCurrency()), ++row);
totalLabel = FormBuilder.addLabel(offerDetailsGridPane, "Total:", "", ++row);
setTotal();
collateralLabel1 = FormBuilder.addLabel(offerDetailsGridPane, "Collateral:", Formatter.formatCollateral(offer.getOfferConstraints().getCollateral(), getAmount()), ++row);
FormBuilder.addLabel(offerDetailsGridPane, "Offer fee:", Formatter.formatSatoshis(Fees.OFFER_CREATION_FEE, true), ++row);
FormBuilder.addVSpacer(offerDetailsGridPane, ++row);
totalToPayLabel = FormBuilder.addLabel(offerDetailsGridPane, "You pay:", getTotalToPay(), ++row);
totalToReceiveLabel = FormBuilder.addLabel(offerDetailsGridPane, "You receive:\n ", getTotalToReceive(), ++row);
// totalToReceiveLabel = FormBuilder.addLabel(offerDetailsGridPane, "You receive:\n ", getTotalToReceive(), ++row);
offerDetailsTitlePane = new TitledPane(takerIsSelling() ? "Sell Bitcoin" : "Buy Bitcoin", offerDetailsGridPane);
offerDetailsTitlePane.setCollapsible(false);
@ -286,10 +284,9 @@ public class TradeProcessController implements Initializable, ChildController
volumeLabel = FormBuilder.addLabel(contractGridPane, "Volume:", "", ++row);
setVolume();
FormBuilder.addLabel(contractGridPane, "Price:", Formatter.formatPriceWithCurrencyPair(offer.getPrice(), offer.getCurrency()), ++row);
collateralLabel2 = FormBuilder.addLabel(contractGridPane, "Collateral:", "", ++row);
setCollateral();
// FormBuilder.addLabel(contractGridPane, "Language:", Formatter.formatList(offerConstraints.getLanguageLocales()), ++row);
FormBuilder.addLabel(contractGridPane, "Arbitrator:", offerConstraints.getArbitrator(), ++row);
//setCollateral();
// FormBuilder.addLabel(contractGridPane, "Language:", Formatter.formatList(offerConstraints.getAcceptedLanguageLocales()), ++row);
// FormBuilder.addLabel(contractGridPane, "Arbitrator:", offerConstraints.getArbitrator(), ++row);
// FormBuilder.addLabel(contractGridPane, "Identity verification:", Formatter.formatList(offerConstraints.getIdentityVerifications()), ++row);
FormBuilder.addLabel(contractGridPane, "Bank transfer reference ID:", "Purchase xyz 01.04.2014", ++row);
@ -299,8 +296,8 @@ public class TradeProcessController implements Initializable, ChildController
FormBuilder.addLabel(contractGridPane, "Messaging ID:", offerer.getMessageID(), ++row);
//FormBuilder.addLabel(contractGridPane, "Country:", offerer.getCountry(), ++row);
offererPubKeyLabel = FormBuilder.addLabel(contractGridPane, "Payment public key:", contract.getOffererPubKey(), ++row);
FormBuilder.addLabel(contractGridPane, "Bank transfer type:", offerer.getCurrentBankAccount().getBankAccountType().toString(), ++row);
offererAccountPrimaryID = FormBuilder.addLabel(contractGridPane, "Bank account IBAN:", offerer.getCurrentBankAccount().getAccountPrimaryID(), ++row);
// FormBuilder.addLabel(contractGridPane, "Bank transfer type:", offerer.getCurrentBankAccount().getBankAccountType().toString(), ++row);
// offererAccountPrimaryID = FormBuilder.addLabel(contractGridPane, "Bank account IBAN:", offerer.getCurrentBankAccount().getAccountPrimaryID(), ++row);
offererAccountSecondaryIDLabel = FormBuilder.addLabel(contractGridPane, "Bank account BIC:", offerer.getCurrentBankAccount().getAccountSecondaryID(), ++row);
offererAccountHolderNameLabel = FormBuilder.addLabel(contractGridPane, "Bank account holder:", offerer.getCurrentBankAccount().getAccountHolderName(), ++row);
@ -352,7 +349,7 @@ public class TradeProcessController implements Initializable, ChildController
private double getVolume()
{
return offer.getPrice() * Converter.convertToDouble(amountTextField.getText());
return offer.getPrice() * Converter.stringToDouble(amountTextField.getText());
}
private double getAmount()
@ -365,40 +362,40 @@ public class TradeProcessController implements Initializable, ChildController
String result = "";
if (takerIsSelling())
{
double btcValue = Converter.convertToDouble(amountTextField.getText()) + BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE) +
offer.getOfferConstraints().getCollateral() * Converter.convertToDouble(amountTextField.getText());
double btcValue = Converter.stringToDouble(amountTextField.getText()) + BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE)/* +
offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText())*/;
result = Formatter.formatAmount(btcValue, true, true);
}
else
{
double btcValue = BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE) + offer.getOfferConstraints().getCollateral() * Converter.convertToDouble(amountTextField.getText());
double btcValue = BtcFormatter.satoshiToBTC(Fees.OFFER_CREATION_FEE) /*+ offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText())*/;
result = Formatter.formatAmount(btcValue, true, true) + "\n" + Formatter.formatVolume(getVolume(), offer.getCurrency());
}
return result;
}
private String getTotalToReceive()
/*private String getTotalToReceive()
{
String result = "";
if (takerIsSelling())
{
double btcValue = offer.getOfferConstraints().getCollateral() * Converter.convertToDouble(amountTextField.getText());
double btcValue = offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText());
result = Formatter.formatAmount(btcValue, true, true) + "\n" + Formatter.formatVolume(getVolume(), offer.getCurrency());
}
else
{
double btcValue = Converter.convertToDouble(amountTextField.getText()) +
offer.getOfferConstraints().getCollateral() * Converter.convertToDouble(amountTextField.getText());
double btcValue = Converter.stringToDouble(amountTextField.getText()) +
offer.getConstraints().getCollateral() * Converter.stringToDouble(amountTextField.getText());
result = Formatter.formatAmount(btcValue, true, true);
}
return result;
}
} */
public void setCollateral()
/*public void setCollateral()
{
String value = Formatter.formatCollateral(offer.getOfferConstraints().getCollateral(), Converter.convertToDouble(amountTextField.getText()));
String value = Formatter.formatCollateral(offer.getConstraints().getCollateral(), Converter.stringToDouble(amountTextField.getText()));
collateralLabel1.setText(value);
collateralLabel2.setText(value);
}
}*/
}

View File

@ -1,23 +1,27 @@
package io.bitsquare.gui.util;
import io.bitsquare.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Locale;
public class Converter
{
public static double convertToDouble(String input)
private static final Logger log = LoggerFactory.getLogger(Converter.class);
public static double stringToDouble(String input)
{
try
{
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Settings.getLocale());
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
return decimalFormat.parse(input).doubleValue();
} catch (ParseException e)
{
//e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
log.warn(e.toString());
}
return 0.0;
return 0;
}

View File

@ -1,11 +1,11 @@
package io.bitsquare.gui.util;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.components.VSpacer;
import javafx.collections.FXCollections;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import java.util.List;
@ -20,18 +20,32 @@ public class FormBuilder
return valueLabel;
}
public static void addHeaderLabel(GridPane gridPane, String title, int row)
public static Label addHeaderLabel(GridPane gridPane, String title, int row)
{
Label headerLabel = new Label(title);
headerLabel.setId("form-header-text");
gridPane.add(headerLabel, 0, row);
return headerLabel;
}
public static TextField addInputField(GridPane gridPane, String title, String value, int row)
{
return addTextField(gridPane, title, value, row, true, true);
}
public static TextField addTextField(GridPane gridPane, String title, String value, int row)
{
return addTextField(gridPane, title, value, row, false, false);
}
public static TextField addTextField(GridPane gridPane, String title, String value, int row, boolean editable, boolean selectable)
{
gridPane.add(new Label(title), 0, row);
TextField textField = new TextField(value);
gridPane.add(textField, 1, row);
textField.setMouseTransparent(!selectable && !editable);
textField.setEditable(editable);
return textField;
}
@ -54,4 +68,49 @@ public class FormBuilder
gridPane.add(comboBox, 1, row);
return comboBox;
}
public static TextField addConfirmationsLabel(GridPane gridPane, WalletFacade walletFacade, int row)
{
return FormBuilder.addTextField(gridPane, "Confirmations:", getConfirmationText(walletFacade), row);
}
public static ProgressIndicator addConfirmationsSpinner(GridPane gridPane, WalletFacade walletFacade, int row)
{
ProgressIndicator progressIndicator = new ProgressIndicator();
gridPane.add(progressIndicator, 3, row);
progressIndicator.setPrefSize(18, 18);
if (walletFacade.getRegConfDepthInBlocks() == 0)
progressIndicator.setProgress(-1);
else
progressIndicator.setOpacity(0);
return progressIndicator;
}
public static ImageView addConfirmationsIcon(GridPane gridPane, WalletFacade walletFacade, int row)
{
int depthInBlocks = walletFacade.getRegConfNumBroadcastPeers();
int numBroadcastPeers = walletFacade.getRegConfDepthInBlocks();
Image confirmIconImage;
if (depthInBlocks > 0)
confirmIconImage = Icons.getIconImage(Icons.getIconIDForConfirmations(depthInBlocks));
else
confirmIconImage = Icons.getIconImage(Icons.getIconIDForPeersSeenTx(numBroadcastPeers));
ImageView confirmIconImageView = new ImageView(confirmIconImage);
gridPane.add(confirmIconImageView, 2, row);
return confirmIconImageView;
}
public static String getConfirmationText(WalletFacade walletFacade)
{
int numBroadcastPeers = walletFacade.getRegConfNumBroadcastPeers();
int depthInBlocks = walletFacade.getRegConfDepthInBlocks();
return depthInBlocks + " confirmation(s) / " + "Seen by " + numBroadcastPeers + " peer(s)";
}
}

View File

@ -1,13 +1,13 @@
package io.bitsquare.gui.util;
import io.bitsquare.btc.BtcFormatter;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Currency;
import java.util.List;
import java.util.Locale;
public class Formatter
{
@ -111,7 +111,7 @@ public class Formatter
public static DecimalFormat getDecimalFormat(int fractionDigits)
{
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Settings.getLocale());
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
decimalFormat.setMinimumFractionDigits(fractionDigits);
decimalFormat.setMaximumFractionDigits(fractionDigits);
decimalFormat.setGroupingUsed(false);
@ -123,4 +123,32 @@ public class Formatter
return value * 100 + "%";
}
public static String countryLocalesToString(List<Locale> countryLocales)
{
String result = "";
int i = 0;
for (Locale locale : countryLocales)
{
result += locale.getCountry();
i++;
if (i < countryLocales.size())
result += ", ";
}
return result;
}
public static String languageLocalesToString(List<Locale> languageLocales)
{
String result = "";
int i = 0;
for (Locale locale : languageLocales)
{
result += locale.getDisplayLanguage();
i++;
if (i < languageLocales.size())
result += ", ";
}
return result;
}
}

View File

@ -4,7 +4,7 @@ import javafx.animation.AnimationTimer;
import java.util.function.Function;
public class Utils
public class GUIUtils
{
/**
* @param delay in milliseconds

View File

@ -1,194 +1,65 @@
package io.bitsquare.settings;
import com.google.inject.Inject;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import java.util.*;
import java.util.function.Predicate;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class Settings
public class Settings implements Serializable
{
private static final long serialVersionUID = 7995048077355006861L;
public static Locale locale = Locale.ENGLISH;
public static Currency currency = Currency.getInstance("USD");
private Storage storage;
private OrderBookFilter orderBookFilter;
public static Locale getLocale()
{
return Settings.locale;
}
public static Currency getCurrency()
{
return Settings.currency;
}
private List<Locale> acceptedLanguageLocales = new ArrayList<>();
private List<Locale> acceptedCountryLocales = new ArrayList<>();
@Inject
public Settings(Storage storage, OrderBookFilter orderBookFilter)
public Settings()
{
this.storage = storage;
this.orderBookFilter = orderBookFilter;
locale = Locale.ENGLISH;
currency = Currency.getInstance("USD");
currency = (Currency) storage.read("Settings.currency");
if (currency == null)
currency = Currency.getInstance("USD");
}
public ArrayList<Locale> getAllLocales()
public void updateFromStorage(Settings savedSettings)
{
ArrayList<Locale> list = new ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales()));
list.removeIf(new Predicate<Locale>()
if (savedSettings != null)
{
@Override
public boolean test(Locale locale)
{
return locale == null || locale.getCountry().equals("") || locale.getLanguage().equals("");
}
});
acceptedLanguageLocales = savedSettings.getAcceptedLanguageLocales();
list.sort(new Comparator<Locale>()
{
@Override
public int compare(Locale locale1, Locale locale2)
{
return locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry());
}
});
Locale defaultLocale = Locale.getDefault();
list.remove(defaultLocale);
list.add(0, defaultLocale);
return list;
acceptedCountryLocales = savedSettings.getAcceptedCountryLocales();
}
}
public List<Currency> getAllCurrencies()
public void addAcceptedLanguageLocale(Locale locale)
{
ArrayList<Currency> mainCurrencies = new ArrayList<>();
mainCurrencies.add(Currency.getInstance("USD"));
mainCurrencies.add(Currency.getInstance("EUR"));
mainCurrencies.add(Currency.getInstance("CNY"));
mainCurrencies.add(Currency.getInstance("RUB"));
mainCurrencies.add(Currency.getInstance("JPY"));
mainCurrencies.add(Currency.getInstance("GBP"));
mainCurrencies.add(Currency.getInstance("CAD"));
mainCurrencies.add(Currency.getInstance("AUD"));
mainCurrencies.add(Currency.getInstance("CHF"));
mainCurrencies.add(Currency.getInstance("CNY"));
Set<Currency> allCurrenciesSet = Currency.getAvailableCurrencies();
allCurrenciesSet.removeAll(mainCurrencies);
List<Currency> allCurrenciesList = new ArrayList<>(allCurrenciesSet);
allCurrenciesList.sort(new Comparator<Currency>()
{
@Override
public int compare(Currency a, Currency b)
{
return a.getCurrencyCode().compareTo(b.getCurrencyCode());
}
});
List<Currency> resultList = new ArrayList<>(mainCurrencies);
resultList.addAll(allCurrenciesList);
Currency defaultCurrency = Currency.getInstance(Locale.getDefault());
resultList.remove(defaultCurrency);
resultList.add(0, defaultCurrency);
return resultList;
acceptedLanguageLocales.add(locale);
}
public ArrayList<BankAccountType.BankAccountTypeEnum> getAllBankAccountTypeEnums()
public void addAcceptedCountryLocale(Locale locale)
{
ArrayList<BankAccountType.BankAccountTypeEnum> bankAccountTypeEnums = new ArrayList<>();
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.SEPA);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.WIRE);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.INTERNATIONAL);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OK_PAY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.NET_TELLER);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OTHER);
return bankAccountTypeEnums;
acceptedCountryLocales.add(locale);
}
public ArrayList<BankAccountType> getAllBankAccountTypes()
//setters
public void setAcceptedLanguageLocales(List<Locale> acceptedLanguageLocales)
{
ArrayList<BankAccountType> bankTransferTypes = new ArrayList<>();
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.SEPA, "IBAN", "BIC"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.WIRE, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.INTERNATIONAL, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OK_PAY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.NET_TELLER, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OTHER, "Prim_todo", "Sec_todo"));
return bankTransferTypes;
this.acceptedLanguageLocales = acceptedLanguageLocales;
}
public void setAcceptedCountryLocales(List<Locale> acceptedCountryLocales)
{
this.acceptedCountryLocales = acceptedCountryLocales;
}
//getters
public List<Locale> getAcceptedLanguageLocales()
{
return acceptedLanguageLocales;
}
public ArrayList<String> getAllArbitrators()
public List<Locale> getAcceptedCountryLocales()
{
ArrayList<String> arbitrators = new ArrayList<>();
arbitrators.add("Paysty pool 1");
arbitrators.add("Paysty pool 2");
arbitrators.add("Paysty pool 3");
arbitrators.add("Paysty pool 4");
return arbitrators;
}
public ArrayList<String> getAllIdentityVerifications()
{
ArrayList<String> identityVerifications = new ArrayList<>();
identityVerifications.add("Passport");
identityVerifications.add("PGP");
identityVerifications.add("BTC-OTC");
identityVerifications.add("Bitcointalk");
identityVerifications.add("Reddit");
identityVerifications.add("Skype");
identityVerifications.add("Google+");
identityVerifications.add("Twitter");
identityVerifications.add("Diaspora");
identityVerifications.add("Facebook");
identityVerifications.add("Jabber");
identityVerifications.add("Other");
identityVerifications.add("Any");
identityVerifications.add("None");
return identityVerifications;
}
public ArrayList<String> getAllCollaterals()
{
ArrayList<String> list = new ArrayList<>();
list.add("0.01");
list.add("0.1");
list.add("0.5");
list.add("1.0");
return list;
}
public void setCurrency(Currency currency)
{
Settings.currency = currency;
storage.write("Settings.currency", currency);
}
public void setLocale(Locale locale)
{
Settings.locale = locale;
}
public OrderBookFilter getOrderBookFilter()
{
return orderBookFilter;
return acceptedCountryLocales;
}

View File

@ -1,32 +0,0 @@
package io.bitsquare.settings;
import com.google.inject.Inject;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User;
public class Startup
{
private Storage storage;
private User user;
private OrderBookFilter orderBookFilter;
@Inject
public Startup(Storage storage, OrderBookFilter orderBookFilter)
{
this.storage = storage;
this.orderBookFilter = orderBookFilter;
}
public void applyPersistedData()
{
// todo use persistence
orderBookFilter.setAmount(0.0);
orderBookFilter.setPrice(0.0);
orderBookFilter.setDirection(Direction.BUY);
orderBookFilter.setCurrency(Settings.getCurrency());
}
}

View File

@ -33,10 +33,6 @@ public class Storage
}
}
public void saveUser(User user)
{
write(user.getClass().getName(), user);
}
public void updateUserFromStorage(User user)
{
@ -47,7 +43,7 @@ public class Storage
public void write(String key, Object value)
{
log.info("Write object with key = " + key + " / value = " + value);
//log.info("Write object with key = " + key + " / value = " + value);
dataVO.dict.put(key, value);
writeDataVO(dataVO);
}
@ -56,7 +52,7 @@ public class Storage
{
dataVO = readDataVO();
Object result = dataVO.dict.get(key);
log.info("Read object with key = " + key + " result = " + result);
//log.info("Read object with key = " + key + " result = " + result);
return result;
}

View File

@ -1,8 +1,10 @@
package io.bitsquare.trade;
import io.bitsquare.user.User;
import io.bitsquare.bank.BankAccountType;
import java.util.Currency;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
public class Offer
@ -11,28 +13,110 @@ public class Offer
private double price;
private double amount;
private double minAmount;
private Direction direction;
private Currency currency;
private User offerer;
private OfferConstraints offerConstraints;
public Offer(UUID uid,
private String accountID;
private String messageID;
private Direction direction;
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum;
private Currency currency;
private Locale bankAccountCountryLocale;
private List<Locale> acceptedCountryLocales;
private List<Locale> acceptedLanguageLocales;
private String offerPaymentTxID;
public Offer(String accountID,
String messageID,
Direction direction,
double price,
double amount,
double minAmount,
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum,
Currency currency,
User offerer,
OfferConstraints offerConstraints)
Locale bankAccountCountryLocale,
List<Locale> acceptedCountryLocales,
List<Locale> acceptedLanguageLocales)
{
this.uid = uid;
this.accountID = accountID;
this.messageID = messageID;
this.direction = direction;
this.price = price;
this.amount = amount;
this.minAmount = minAmount;
this.bankAccountTypeEnum = bankAccountTypeEnum;
this.currency = currency;
this.offerer = offerer;
this.offerConstraints = offerConstraints;
this.bankAccountCountryLocale = bankAccountCountryLocale;
this.acceptedCountryLocales = acceptedCountryLocales;
this.acceptedLanguageLocales = acceptedLanguageLocales;
uid = UUID.randomUUID();
}
// setter
public void setOfferPaymentTxID(String offerPaymentTxID)
{
this.offerPaymentTxID = offerPaymentTxID;
}
// getters
public String getAccountID()
{
return accountID;
}
public String getMessageID()
{
return messageID;
}
public UUID getUid()
{
return uid;
}
public double getPrice()
{
return price;
}
public double getAmount()
{
return amount;
}
public double getMinAmount()
{
return minAmount;
}
public Direction getDirection()
{
return direction;
}
public BankAccountType.BankAccountTypeEnum getBankAccountTypeEnum()
{
return bankAccountTypeEnum;
}
public Currency getCurrency()
{
return currency;
}
public Locale getBankAccountCountryLocale()
{
return bankAccountCountryLocale;
}
public List<Locale> getAcceptedCountryLocales()
{
return acceptedCountryLocales;
}
public List<Locale> getAcceptedLanguageLocales()
{
return acceptedLanguageLocales;
}
public double getVolume()
@ -45,85 +129,9 @@ public class Offer
return price * minAmount;
}
public UUID getUid()
public String getOfferPaymentTxID()
{
return uid;
return offerPaymentTxID;
}
public void setUid(UUID uid)
{
this.uid = uid;
}
public Direction getDirection()
{
return direction;
}
public void setDirection(Direction direction)
{
this.direction = direction;
}
public double getPrice()
{
return price;
}
public void setPrice(double price)
{
this.price = price;
}
public double getAmount()
{
return amount;
}
public void setAmount(double amount)
{
this.amount = amount;
}
public double getMinAmount()
{
return minAmount;
}
public void setMinAmount(double minAmount)
{
this.minAmount = minAmount;
}
public Currency getCurrency()
{
return currency;
}
public void setCurrency(Currency currency)
{
this.currency = currency;
}
public OfferConstraints getOfferConstraints()
{
return offerConstraints;
}
public void setOfferConstraints(OfferConstraints offerConstraints)
{
this.offerConstraints = offerConstraints;
}
public User getOfferer()
{
return offerer;
}
public void setOfferer(User offerer)
{
this.offerer = offerer;
}
}

View File

@ -0,0 +1,29 @@
package io.bitsquare.trade;
import io.bitsquare.bank.BankAccountType;
import java.util.List;
import java.util.Locale;
public class OfferConstraint
{
private List<Locale> languageLocales;
private List<BankAccountType.BankAccountTypeEnum> bankAccountTypes;
public OfferConstraint(List<Locale> languageLocales,
List<BankAccountType.BankAccountTypeEnum> bankAccountTypes)
{
this.languageLocales = languageLocales;
this.bankAccountTypes = bankAccountTypes;
}
public List<Locale> getLanguageLocales()
{
return languageLocales;
}
public List<BankAccountType.BankAccountTypeEnum> getBankAccountTypes()
{
return bankAccountTypes;
}
}

View File

@ -1,73 +0,0 @@
package io.bitsquare.trade;
import io.bitsquare.bank.BankAccountType;
import java.util.List;
import java.util.Locale;
public class OfferConstraints
{
//TODO remove
private double collateral;
private String arbitrator;
private String identityVerification;
private List<Locale> countryLocales;
private List<Locale> languageLocales;
private List<BankAccountType.BankAccountTypeEnum> bankAccountTypes;
public OfferConstraints(List<Locale> countryLocales,
List<Locale> languageLocales,
double collateral,
List<BankAccountType.BankAccountTypeEnum> bankAccountTypes,
String arbitrator,
String identityVerification)
{
this.countryLocales = countryLocales;
this.languageLocales = languageLocales;
this.bankAccountTypes = bankAccountTypes;
this.collateral = collateral;
this.arbitrator = arbitrator;
this.identityVerification = identityVerification;
}
/**
* @return List of ISO3 country codes
*/
public List<Locale> getCountryLocales()
{
return countryLocales;
}
/**
* @return List of ISO3 language codes
*/
public List<Locale> getLanguageLocales()
{
return languageLocales;
}
public List<BankAccountType.BankAccountTypeEnum> getBankAccountTypes()
{
return bankAccountTypes;
}
public String getArbitrator()
{
return arbitrator;
}
public String getIdentityVerification()
{
return identityVerification;
}
public double getCollateral()
{
return collateral;
}
}

View File

@ -1,5 +1,6 @@
package io.bitsquare.trade;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.inject.Inject;
import io.bitsquare.btc.BlockChainFacade;
import io.bitsquare.btc.KeyPair;
@ -52,11 +53,15 @@ public class Trading
/**
* @param offer
*/
public void placeNewOffer(Offer offer)
public String placeNewOffer(Offer offer) throws InsufficientMoneyException
{
log.info("place New Offer");
offers.put(offer.getUid().toString(), offer);
String txID = walletFacade.payOfferFee();
offer.setOfferPaymentTxID(txID);
messageFacade.broadcast(new Message(Message.BROADCAST_NEW_OFFER, offer));
return txID;
}
/**
@ -67,7 +72,7 @@ public class Trading
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());
//messageFacade.send(new Message(Message.REQUEST_TAKE_OFFER, trade), trade.getOffer().getOfferer().getMessageID());
}
@ -81,7 +86,7 @@ public class Trading
KeyPair address = walletFacade.createNewAddress();
Contract contract = new Contract(trade, address.getPubKey());
contract.setOfferer(trade.getOffer().getOfferer());
//contract.setOfferer(trade.getOffer().getOfferer());
contract.setTaker(user);
contracts.put(trade.getUid().toString(), contract);
return contract;
@ -132,7 +137,7 @@ public class Trading
trade.setTakeOfferFeeTxID(txID);
log.info("Taker asks offerer for confirmation for his fee payment. txID=" + txID);
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());
}
@ -154,7 +159,7 @@ public class Trading
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());
}
@ -168,7 +173,7 @@ public class Trading
log.info("Broadcast payment tx");
log.info("Send message to peer that payment Tx has been broadcasted.");
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());
}

View File

@ -0,0 +1,118 @@
package io.bitsquare.trade.orderbook;
import com.google.inject.Inject;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.trade.orderbook.OrderBookListItem;
import io.bitsquare.gui.util.Converter;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.user.User;
import io.bitsquare.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class MockOrderBook extends OrderBook
{
private static final Logger log = LoggerFactory.getLogger(MockOrderBook.class);
@Inject
public MockOrderBook(Settings settings, User user)
{
super(settings, user);
for (int i = 0; i < 1000; i++)
{
allOffers.add(new OrderBookListItem(getOffer()));
}
}
private Offer getOffer()
{
double amount = Math.random() * 10 + 0.1;
amount = Converter.stringToDouble(Formatter.formatAmount(amount));
double minAmount = Math.random() * amount;
minAmount = Converter.stringToDouble(Formatter.formatAmount(minAmount));
Direction direction = Direction.BUY;
double price = 500 + Math.random() * 50;
if (Math.random() > 0.5)
{
direction = Direction.SELL;
price = 500 - Math.random() * 50;
}
Offer offer = new Offer(UUID.randomUUID().toString(),
UUID.randomUUID().toString(),
direction,
price,
amount,
minAmount,
getBankTransferTypeEnums().get(0),
getCurrencies().get(0),
getLocales().get(0),
getLocales(),
getLocales());
return offer;
}
private List<Currency> getCurrencies()
{
List<Currency> list = new ArrayList<>();
list.add(Currency.getInstance("EUR"));
list.add(Currency.getInstance("USD"));
list.add(Currency.getInstance("GBP"));
list.add(Currency.getInstance("RUB"));
list.add(Currency.getInstance("CAD"));
list.add(Currency.getInstance("AUD"));
list.add(Currency.getInstance("JPY"));
list.add(Currency.getInstance("CNY"));
list.add(Currency.getInstance("CHF"));
return randomizeList(list);
}
private List<Locale> getLocales()
{
List<Locale> list = new ArrayList<>();
list.add(new Locale("de", "AT"));
list.add(new Locale("de", "DE"));
list.add(new Locale("en", "US"));
list.add(new Locale("en", "UK"));
list.add(new Locale("es", "ES"));
list.add(new Locale("ru", "RU"));
list.add(new Locale("zh", "CN"));
list.add(new Locale("en", "AU"));
list.add(new Locale("it", "IT"));
list.add(new Locale("en", "CA"));
return randomizeList(list);
}
private List<BankAccountType.BankAccountTypeEnum> getBankTransferTypeEnums()
{
return randomizeList(Utils.getAllBankAccountTypeEnums());
}
private List randomizeList(List list)
{
int e = new Random().nextInt(list.size());
if (list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List reduce(List list, int count)
{
List result = new ArrayList();
for (int i = 0; i < count && i < list.size(); i++)
{
result.add(list.get(i));
}
return result;
}
}

View File

@ -1,239 +1,167 @@
package io.bitsquare.trade.orderbook;
import com.google.inject.Inject;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.gui.trade.orderbook.OrderBookListItem;
import io.bitsquare.gui.util.Converter;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.OfferConstraints;
import io.bitsquare.user.User;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
public class OrderBook
{
private ObservableList<OrderBookListItem> orderBookListItems;
private static final Logger log = LoggerFactory.getLogger(OrderBook.class);
private FilteredList<OrderBookListItem> filteredList;
private SortedList<OrderBookListItem> offerList;
protected ObservableList<OrderBookListItem> allOffers = FXCollections.observableArrayList();
private Settings settings;
private User user;
@Inject
public OrderBook(Settings settings)
public OrderBook(Settings settings, User user)
{
this.settings = settings;
orderBookListItems = FXCollections.observableArrayList();
for (int i = 0; i < 100; i++)
{
orderBookListItems.add(getOrderBookListItem());
}
this.user = user;
filteredList = new FilteredList<>(allOffers);
// FilteredList does not support sorting, so we need to wrap it to a SortedList
offerList = new SortedList<>(filteredList);
}
public ObservableList<OrderBookListItem> getFilteredList(OrderBookFilter orderBookFilter)
public SortedList<OrderBookListItem> getOfferList()
{
FilteredList filtered = orderBookListItems.filtered(new Predicate<OrderBookListItem>()
return offerList;
}
public void updateFilter(OrderBookFilter orderBookFilter)
{
filteredList.setPredicate(new Predicate<OrderBookListItem>()
{
@Override
public boolean test(OrderBookListItem offerListVO)
public boolean test(OrderBookListItem orderBookListItem)
{
boolean priceResult;
boolean amountResult = offerListVO.getOffer().getAmount() >= orderBookFilter.getAmount();
// swap direction. use who want to buy btc want to see sell offers...
boolean directionResult = offerListVO.getOffer().getDirection() != orderBookFilter.getDirection();
boolean currencyResult = offerListVO.getOffer().getCurrency().equals(orderBookFilter.getCurrency());
Offer offer = orderBookListItem.getOffer();
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (offerListVO.getOffer().getDirection() == Direction.SELL && orderBookFilter.getPrice() > 0)
priceResult = offerListVO.getOffer().getPrice() <= orderBookFilter.getPrice();
else
priceResult = offerListVO.getOffer().getPrice() >= orderBookFilter.getPrice();
return priceResult && amountResult && directionResult && currencyResult;
if (orderBookFilter == null
|| offer == null
|| currentBankAccount == null
|| orderBookFilter.getDirection() == null)
return false;
// The users current bank account currency must match the offer currency (1 to 1)
boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency());
// The offer bank account country must match one of the accepted countries defined in the settings (1 to n)
boolean countryResult = countryInList(offer.getBankAccountCountryLocale(), settings.getAcceptedCountryLocales());
// One of the supported languages from the settings must match one of the offer languages (n to n)
boolean languageResult = languagesInList(settings.getAcceptedLanguageLocales(), offer.getAcceptedLanguageLocales());
// Apply updateFilter only if there is a valid value set
// The requested amount must be lower or equal then the offer amount
boolean amountResult = true;
if (orderBookFilter.getAmount() > 0)
amountResult = orderBookFilter.getAmount() <= offer.getAmount();
// The requested trade direction must be opposite of the offerList trade direction
boolean directionResult = !orderBookFilter.getDirection().equals(offer.getDirection());
// Apply updateFilter only if there is a valid value set
boolean priceResult = true;
if (orderBookFilter.getPrice() > 0)
{
if (offer.getDirection() == Direction.SELL)
priceResult = orderBookFilter.getPrice() >= offer.getPrice();
else
priceResult = orderBookFilter.getPrice() <= offer.getPrice();
}
boolean result = currencyResult
&& countryResult
&& languageResult
&& amountResult
&& directionResult
&& priceResult;
/*
log.debug("result = " + result +
", currencyResult = " + currencyResult +
", countryResult = " + countryResult +
", languageResult = " + languageResult +
", bankAccountTypeEnumResult = " + bankAccountTypeEnumResult +
", amountResult = " + amountResult +
", directionResult = " + directionResult +
", priceResult = " + priceResult
);
log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() +
", offer.getCurrency() = " + offer.getCurrency());
log.debug("offer.getCountryLocale() = " + offer.getCountryLocale() +
", settings.getAcceptedCountryLocales() = " + settings.getAcceptedCountryLocales().toString());
log.debug("settings.getAcceptedLanguageLocales() = " + settings.getAcceptedLanguageLocales() +
", constraints.getAcceptedLanguageLocales() = " + constraints.getLanguageLocales());
log.debug("currentBankAccount.getBankAccountType().getType() = " + currentBankAccount.getBankAccountType().getType() +
", constraints.getBankAccountTypes() = " + constraints.getBankAccountTypes());
log.debug("orderBookFilter.getAmount() = " + orderBookFilter.getAmount() +
", offer.getAmount() = " + offer.getAmount());
log.debug("orderBookFilter.getDirection() = " + orderBookFilter.getDirection() +
", offer.getDirection() = " + offer.getDirection());
log.debug("orderBookFilter.getPrice() = " + orderBookFilter.getPrice() +
", offer.getPrice() = " + offer.getPrice());
*/
return result;
}
});
//TODO use FilteredList
ObservableList<OrderBookListItem> result = FXCollections.observableArrayList();
result.addAll(filtered);
return result;
}
private OrderBookListItem getOrderBookListItem()
private boolean countryInList(Locale orderBookFilterLocale, List<Locale> offerConstraintsLocales)
{
return new OrderBookListItem(getOffer());
}
public ArrayList<Currency> getCurrencies()
{
ArrayList<Currency> currencies = new ArrayList<>();
currencies.add(Currency.getInstance("USD"));
currencies.add(Currency.getInstance("EUR"));
currencies.add(Currency.getInstance("CNY"));
currencies.add(Currency.getInstance("RUB"));
currencies.add(Currency.getInstance("JPY"));
currencies.add(Currency.getInstance("GBP"));
currencies.add(Currency.getInstance("CAD"));
currencies.add(Currency.getInstance("AUD"));
currencies.add(Currency.getInstance("CHF"));
currencies.add(Currency.getInstance("CNY"));
/* Set<Currency> otherCurrenciesSet = Currency.getAvailableCurrencies();
ArrayList<Currency> otherCurrenciesList = new ArrayList<>();
otherCurrenciesList.addAll(otherCurrenciesSet);
Collections.sort(otherCurrenciesList, new CurrencyComparator());
currencies.addAll(otherCurrenciesList); */
return currencies;
}
private Offer getOffer()
{
User offerer = new User();
offerer.setAccountID(UUID.randomUUID().toString());
offerer.setMessageID(UUID.randomUUID().toString());
offerer.setOnline(Math.random() > 0.5 ? true : false);
offerer.setLanguageLocales(getLanguageLocales());
double amount = Math.random() * 10 + 0.1;
amount = Converter.convertToDouble(Formatter.formatAmount(amount));
double minAmount = Math.random() * amount;
minAmount = Converter.convertToDouble(Formatter.formatAmount(minAmount));
Direction direction = Direction.BUY;
double price = 500 + Math.random() * 50;
if (Math.random() > 0.5)
for (Locale locale : offerConstraintsLocales)
{
direction = Direction.SELL;
price = 500 - Math.random() * 50;
if (locale.getCountry().equals(orderBookFilterLocale.getCountry()))
return true;
}
Currency currency = (randomizeCurrencies(getCurrencies(), false)).get(0);
return new Offer(UUID.randomUUID(),
direction,
price,
amount,
minAmount,
currency,
offerer,
getRandomOfferConstraints()
);
return false;
}
public OfferConstraints getRandomOfferConstraints()
private boolean languagesInList(List<Locale> orderBookFilterLocales, List<Locale> offerConstraintsLocales)
{
OfferConstraints offerConstraints = new OfferConstraints(getCountryLocales(),
getLanguageLocales(),
Double.valueOf(getCollaterals().get(0)),
getBankTransferTypeEnums(),
getArbitrators().get(0),
randomizeStrings(settings.getAllIdentityVerifications(), false).get(0));
return offerConstraints;
for (Locale offerConstraintsLocale : offerConstraintsLocales)
{
for (Locale orderBookFilterLocale : orderBookFilterLocales)
{
if (offerConstraintsLocale.getLanguage().equals(orderBookFilterLocale.getLanguage()))
return true;
}
}
return false;
}
private List<Locale> getCountryLocales()
private boolean matchBankAccountTypeEnum(BankAccountType.BankAccountTypeEnum orderBookFilterBankAccountType, List<BankAccountType.BankAccountTypeEnum> offerConstraintsBankAccountTypes)
{
return randomizeList(settings.getAllLocales(), false);
}
private List<Locale> getLanguageLocales()
{
return randomizeList(settings.getAllLocales(), false);
for (BankAccountType.BankAccountTypeEnum bankAccountType : offerConstraintsBankAccountTypes)
{
if (bankAccountType.equals(orderBookFilterBankAccountType))
return true;
}
return false;
}
private List<BankAccountType> getBankTransferTypes()
{
return randomizeBankAccountTypes(settings.getAllBankAccountTypes(), false);
}
private List<BankAccountType.BankAccountTypeEnum> getBankTransferTypeEnums()
{
return randomizeBankAccountTypeEnums(settings.getAllBankAccountTypeEnums(), false);
}
private List<String> getArbitrators()
{
return randomizeStrings(settings.getAllArbitrators(), false);
}
private List<String> getCollaterals()
{
return randomizeStrings(settings.getAllCollaterals(), false);
}
private List<BankAccountType.BankAccountTypeEnum> randomizeBankAccountTypeEnums(List<BankAccountType.BankAccountTypeEnum> list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List<BankAccountType> randomizeBankAccountTypes(List<BankAccountType> list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List<String> randomizeStrings(List<String> list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List randomizeList(List list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List<Double> randomizeDouble(List<Double> list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
private List<Currency> randomizeCurrencies(List<Currency> list, boolean optional)
{
int e = new Random().nextInt(list.size());
if (!optional && list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
}
class CurrencyComparator implements Comparator<Currency>
{
@Override
public int compare(Currency a, Currency b)
{
return a.getCurrencyCode().compareTo(b.getCurrencyCode());
}
}

View File

@ -1,36 +1,17 @@
package io.bitsquare.trade.orderbook;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.OfferConstraints;
import javafx.beans.property.SimpleBooleanProperty;
import java.util.Currency;
import java.util.Locale;
public class OrderBookFilter
{
transient private final SimpleBooleanProperty changedProperty = new SimpleBooleanProperty();
private double price;
private double amount;
private Direction direction;
private Currency currency;
private Locale countryLocale;
private Locale languageLocale;
private OfferConstraints offerConstraints;
public SimpleBooleanProperty changedPropertyProperty()
{
return changedProperty;
}
private final SimpleBooleanProperty changedProperty = new SimpleBooleanProperty();
// setters
public void setCurrency(Currency currency)
{
this.currency = currency;
triggerChange();
}
public void setAmount(double amount)
{
@ -50,23 +31,6 @@ public class OrderBookFilter
triggerChange();
}
public void setOfferConstraints(OfferConstraints offerConstraints)
{
this.offerConstraints = offerConstraints;
triggerChange();
}
public void setCountryLocale(Locale countryLocale)
{
this.countryLocale = countryLocale;
triggerChange();
}
public void setLanguageLocale(Locale languageLocale)
{
this.languageLocale = languageLocale;
triggerChange();
}
// getters
public double getAmount()
@ -84,25 +48,6 @@ public class OrderBookFilter
return price;
}
public Currency getCurrency()
{
return currency;
}
public OfferConstraints getOfferConstraints()
{
return offerConstraints;
}
public Locale getCountryLocale()
{
return countryLocale;
}
public Locale getLanguageLocale()
{
return languageLocale;
}
public SimpleBooleanProperty getChangedProperty()
{
@ -113,4 +58,5 @@ public class OrderBookFilter
{
changedProperty.set(!changedProperty.get());
}
}

View File

@ -1,28 +1,30 @@
package io.bitsquare.user;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.trade.OfferConstraint;
import javafx.beans.property.SimpleBooleanProperty;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
public class User implements Serializable
{
private static final long serialVersionUID = 7409078808248518638L;
transient private final SimpleBooleanProperty changedProperty = new SimpleBooleanProperty();
private String accountID;
private String messageID;
private boolean online;
private List<BankAccount> bankAccounts = new ArrayList<>();
private BankAccount currentBankAccount = null;
private List<Locale> languageLocales = new ArrayList<>();
private Locale currentLanguageLocale = null;
private OfferConstraint offerConstraint;
public User()
{
addLanguageLocales(Locale.getDefault());
}
public void updateFromStorage(User savedUser)
@ -34,8 +36,6 @@ public class User implements Serializable
online = savedUser.isOnline();
currentBankAccount = savedUser.getCurrentBankAccount();
bankAccounts = savedUser.getBankAccounts();
languageLocales = savedUser.getLanguageLocales();
currentLanguageLocale = savedUser.getCurrentLanguageLocale();
}
}
@ -53,15 +53,8 @@ public class User implements Serializable
return bankAccountUIDs;
}
public void addLanguageLocales(Locale locale)
{
languageLocales.add(locale);
currentLanguageLocale = locale;
}
public void addBankAccount(BankAccount bankAccount)
{
bankAccounts.add(bankAccount);
currentBankAccount = bankAccount;
}
@ -77,7 +70,6 @@ public class User implements Serializable
this.accountID = accountID;
}
public void setBankAccounts(List<BankAccount> bankAccounts)
{
this.bankAccounts = bankAccounts;
@ -86,23 +78,19 @@ public class User implements Serializable
public void setCurrentBankAccount(BankAccount currentBankAccount)
{
this.currentBankAccount = currentBankAccount;
triggerChange();
}
public void setLanguageLocales(List<Locale> languageLocales)
{
this.languageLocales = languageLocales;
}
public void setCurrentLanguageLocale(Locale currentLanguageLocale)
{
this.currentLanguageLocale = currentLanguageLocale;
}
public void setOnline(boolean online)
{
this.online = online;
}
public void setOfferConstraint(OfferConstraint offerConstraint)
{
this.offerConstraint = offerConstraint;
}
// getter
public String getMessageID()
@ -125,20 +113,24 @@ public class User implements Serializable
return currentBankAccount;
}
public List<Locale> getLanguageLocales()
{
return languageLocales;
}
public Locale getCurrentLanguageLocale()
{
return currentLanguageLocale;
}
public boolean isOnline()
{
return online;
}
public OfferConstraint getOfferConstraint()
{
return offerConstraint;
}
public SimpleBooleanProperty getChangedProperty()
{
return changedProperty;
}
private void triggerChange()
{
changedProperty.set(!changedProperty.get());
}
}

View File

@ -3,17 +3,40 @@ package io.bitsquare.util;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.bitsquare.bank.BankAccountType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
import java.util.function.Predicate;
public class Utils
{
private static final Logger log = LoggerFactory.getLogger(Utils.class);
public static String convertToJson(Object object)
{
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
return gson.toJson(object);
}
private static long lastTimeStamp = System.currentTimeMillis();
public static void printElapsedTime(String msg)
{
if (msg.length() > 0)
msg += " / ";
long timeStamp = System.currentTimeMillis();
log.debug(msg + "Elapsed: " + String.valueOf(timeStamp - lastTimeStamp));
lastTimeStamp = timeStamp;
}
public static void printElapsedTime()
{
printElapsedTime("");
}
public static Object copy(Object orig)
{
Object obj = null;
@ -40,4 +63,97 @@ public class Utils
return obj;
}
public static ArrayList<Locale> getAllLocales()
{
ArrayList<Locale> list = new ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales()));
list.removeIf(new Predicate<Locale>()
{
@Override
public boolean test(Locale locale)
{
return locale == null || locale.getCountry().equals("") || locale.getLanguage().equals("");
}
});
list.sort(new Comparator<Locale>()
{
@Override
public int compare(Locale locale1, Locale locale2)
{
return locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry());
}
});
Locale defaultLocale = Locale.getDefault();
//Locale defaultLocale = new Locale("de", "AT");
list.remove(defaultLocale);
list.add(0, defaultLocale);
return list;
}
public static List<Currency> getAllCurrencies()
{
ArrayList<Currency> mainCurrencies = new ArrayList<>();
mainCurrencies.add(Currency.getInstance("USD"));
mainCurrencies.add(Currency.getInstance("EUR"));
mainCurrencies.add(Currency.getInstance("CNY"));
mainCurrencies.add(Currency.getInstance("RUB"));
mainCurrencies.add(Currency.getInstance("JPY"));
mainCurrencies.add(Currency.getInstance("GBP"));
mainCurrencies.add(Currency.getInstance("CAD"));
mainCurrencies.add(Currency.getInstance("AUD"));
mainCurrencies.add(Currency.getInstance("CHF"));
mainCurrencies.add(Currency.getInstance("CNY"));
Set<Currency> allCurrenciesSet = Currency.getAvailableCurrencies();
allCurrenciesSet.removeAll(mainCurrencies);
List<Currency> allCurrenciesList = new ArrayList<>(allCurrenciesSet);
allCurrenciesList.sort(new Comparator<Currency>()
{
@Override
public int compare(Currency a, Currency b)
{
return a.getCurrencyCode().compareTo(b.getCurrencyCode());
}
});
List<Currency> resultList = new ArrayList<>(mainCurrencies);
resultList.addAll(allCurrenciesList);
Currency defaultCurrency = Currency.getInstance(Locale.getDefault());
resultList.remove(defaultCurrency);
resultList.add(0, defaultCurrency);
return resultList;
}
public static ArrayList<BankAccountType.BankAccountTypeEnum> getAllBankAccountTypeEnums()
{
ArrayList<BankAccountType.BankAccountTypeEnum> bankAccountTypeEnums = new ArrayList<>();
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.SEPA);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.WIRE);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.INTERNATIONAL);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OK_PAY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.NET_TELLER);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OTHER);
return bankAccountTypeEnums;
}
public static ArrayList<BankAccountType> getAllBankAccountTypes()
{
ArrayList<BankAccountType> bankTransferTypes = new ArrayList<>();
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.SEPA, "IBAN", "BIC"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.WIRE, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.INTERNATIONAL, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OK_PAY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.NET_TELLER, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OTHER, "Prim_todo", "Sec_todo"));
return bankTransferTypes;
}
}

View File

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 599 B

View File

Before

Width:  |  Height:  |  Size: 157 B

After

Width:  |  Height:  |  Size: 157 B

View File

Before

Width:  |  Height:  |  Size: 573 B

After

Width:  |  Height:  |  Size: 573 B

View File

Before

Width:  |  Height:  |  Size: 205 B

After

Width:  |  Height:  |  Size: 205 B