diff --git a/README.md b/README.md index 6eab85cf62..7d616c1224 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ There are no central points of control or failure in the Bitsquare network. Ther Because the fiat money portion of any trade must be transferred via traditional means such as a wire transfer, Bitsquare incorporates first-class support for human arbitration to resolve any errors or disputes. -You can read about all of this and more in the [overview](http://bitsquare.io/images/overview.png), [whitepaper](https://docs.google.com/document/d/1d3EiWZdaM89-P6MVhS53unXv2-pDpSFsN3W4kCGXKgY/edit#), [arbitration](https://docs.google.com/document/d/1LJCRFdtM2Jn2Oiv49qRXwBDG8HZD0Hiedy8tNjErHps/edit) and [risk analysis](https://docs.google.com/document/d/1sHwU7K7C8Nl-fS4Z6X88L-NVJ_WBiKnsSpYpYfyqUXA/edit) documents. Several [screencasts](https://docs.google.com/document/d/1d3EiWZdaM89-P6MVhS53unXv2-pDpSFsN3W4kCGXKgY/edit#) are available as well. +You can read about all of this and more in the [overview](http://bitsquare.io/images/overview.png), [whitepaper](https://docs.google.com/document/d/1d3EiWZdaM89-P6MVhS53unXv2-pDpSFsN3W4kCGXKgY/edit#), [arbitration](https://docs.google.com/document/d/1LJCRFdtM2Jn2Oiv49qRXwBDG8HZD0Hiedy8tNjErHps/edit) and [risk analysis](https://docs.google.com/document/d/1sHwU7K7C8Nl-fS4Z6X88L-NVJ_WBiKnsSpYpYfyqUXA/edit) documents. Several [screencasts](https://www.youtube.com/playlist?list=PLXvC3iNe_di9bL1A5xyAKI2PzNg8jU092) are available as well. Status diff --git a/build.gradle b/build.gradle index 782a8a041d..41e6267681 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -apply plugin: 'java' -apply plugin: 'application' apply from: 'gradle/javafx.gradle' version = '0.1.0-SNAPSHOT' diff --git a/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java b/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java index b1260cd2fc..3b228a8028 100644 --- a/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java +++ b/src/main/java/io/bitsquare/btc/AddressBasedCoinSelector.java @@ -23,7 +23,6 @@ import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionConfidence; import org.bitcoinj.core.TransactionOutput; -import org.bitcoinj.params.RegTestParams; import org.bitcoinj.wallet.CoinSelection; import org.bitcoinj.wallet.DefaultCoinSelector; @@ -95,14 +94,20 @@ class AddressBasedCoinSelector extends DefaultCoinSelector { // TODO It might be risky to accept 0 confirmation tx from the network with only > 1 numBroadcastPeers // Need to be tested in testnet and mainnet // We need to handle cases when malleability happens or tx get lost and have not been successful propagated - return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || + /* return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || type.equals(TransactionConfidence.ConfidenceType.PENDING) && // we accept network tx without confirmations and numBroadcastPeers > 0 - /*confidence.getSource().equals(TransactionConfidence.Source.SELF) &&*/ + //confidence.getSource().equals(TransactionConfidence.Source.SELF) && // In regtest mode we expect to have only one peer, so we won't see transactions propagate. // TODO: The value 1 below dates from a time when transactions we broadcast *to* were // counted, set to 0 - (confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get()); + (confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get());*/ + + log.debug("numBroadcastPeers = " + confidence.numBroadcastPeers()); + // TODO at testnet we got confidence.numBroadcastPeers()=0 -> probably because we use chained unconfirmed tx + // investigate further + return type.equals(TransactionConfidence.ConfidenceType.BUILDING) || + type.equals(TransactionConfidence.ConfidenceType.PENDING); } private static boolean isInBlockChain(Transaction tx) { diff --git a/src/main/java/io/bitsquare/btc/FeePolicy.java b/src/main/java/io/bitsquare/btc/FeePolicy.java index 27e1b9c274..a8e2b17e39 100644 --- a/src/main/java/io/bitsquare/btc/FeePolicy.java +++ b/src/main/java/io/bitsquare/btc/FeePolicy.java @@ -22,6 +22,9 @@ import org.bitcoinj.core.AddressFormatException; import org.bitcoinj.core.Coin; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.Transaction; +import org.bitcoinj.params.MainNetParams; +import org.bitcoinj.params.RegTestParams; +import org.bitcoinj.params.TestNet3Params; import javax.inject.Inject; @@ -46,14 +49,29 @@ public class FeePolicy { // Not used at the moment // private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR"; - private static final String createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; - private static final String takeOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; + // + private static String createOfferFeeAddress; + private static String takeOfferFeeAddress; private final NetworkParameters params; @Inject public FeePolicy(NetworkParameters params) { this.params = params; + + if (params.equals(TestNet3Params.get())) { + createOfferFeeAddress = "n3LLZ9ngKdxms3gCbHhNPibHTh7DmHigtE"; + takeOfferFeeAddress = "n3LLZ9ngKdxms3gCbHhNPibHTh7DmHigtE"; + } + else if (params.equals(MainNetParams.get())) { + // bitsquare donation address used for the moment... + createOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7"; + takeOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7"; + } + else if (params.equals(RegTestParams.get())) { + createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; + takeOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; + } } //TODO who is receiver? other users or dev address? use donation option list? diff --git a/src/main/java/io/bitsquare/btc/WalletFacade.java b/src/main/java/io/bitsquare/btc/WalletFacade.java index ef881adc26..f94c9d46d5 100644 --- a/src/main/java/io/bitsquare/btc/WalletFacade.java +++ b/src/main/java/io/bitsquare/btc/WalletFacade.java @@ -46,6 +46,7 @@ import org.bitcoinj.crypto.TransactionSignature; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; +import org.bitcoinj.params.TestNet3Params; import org.bitcoinj.script.Script; import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.utils.Threading; @@ -54,13 +55,13 @@ import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.Service; import java.io.Serializable; import java.math.BigInteger; import java.util.ArrayList; -import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -102,7 +103,7 @@ public class WalletFacade { private final FeePolicy feePolicy; private final CryptoFacade cryptoFacade; private final Persistence persistence; - private final List downloadListeners = new CopyOnWriteArrayList<>(); + // private final List downloadListeners = new CopyOnWriteArrayList<>(); private final List addressConfidenceListeners = new CopyOnWriteArrayList<>(); private final List txConfidenceListeners = new CopyOnWriteArrayList<>(); private final List balanceListeners = new CopyOnWriteArrayList<>(); @@ -132,7 +133,7 @@ public class WalletFacade { // Public Methods /////////////////////////////////////////////////////////////////////////////////////////// - public void initialize(StartupListener startupListener) { + public void initialize(org.bitcoinj.core.DownloadListener downloadListener, StartupListener startupListener) { // Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means // we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener // we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in @@ -164,7 +165,7 @@ public class WalletFacade { // Checkpoint files are made using the BuildCheckpoints tool and usually we have to download the // last months worth or more (takes a few seconds). try { - walletAppKit.setCheckpoints(getClass().getClassLoader().getResourceAsStream("wallet/checkpoints")); + walletAppKit.setCheckpoints(getClass().getResourceAsStream("/wallet/checkpoints")); } catch (Exception e) { e.printStackTrace(); log.error(e.toString()); @@ -172,24 +173,40 @@ public class WalletFacade { // As an example! // walletAppKit.useTor(); } - walletAppKit.setDownloadListener(new BlockChainDownloadListener()) + else if (params == TestNet3Params.get()) { + walletAppKit.setCheckpoints(getClass().getResourceAsStream("/wallet/checkpoints.testnet")); + //walletAppKit.useTor(); + } + walletAppKit.setDownloadListener(downloadListener) .setBlockingStartup(false) - .restoreWalletFromSeed(null) .setUserAgent("BitSquare", "0.1"); + + /* + // TODO restore from DeterministicSeed + if (seed != null) + walletAppKit.restoreWalletFromSeed(seed); + */ + walletAppKit.addListener(new Service.Listener() { + @Override + public void failed(Service.State from, Throwable failure) { + walletAppKit = null; + // TODO show error popup + //crashAlert(failure); + } + }, Threading.SAME_THREAD); walletAppKit.startAsync(); } private void initWallet() { wallet = walletAppKit.wallet(); - wallet.allowSpendingUnconfirmedTransactions(); //walletAppKit.peerGroup().setMaxConnections(11); - if (params == RegTestParams.get()) + /* if (params == RegTestParams.get()) walletAppKit.peerGroup().setMinBroadcastConnections(1); else - walletAppKit.peerGroup().setMinBroadcastConnections(3); + walletAppKit.peerGroup().setMinBroadcastConnections(3);*/ walletEventListener = new WalletEventListener() { @@ -266,14 +283,14 @@ public class WalletFacade { // Listener /////////////////////////////////////////////////////////////////////////////////////////// - public DownloadListener addDownloadListener(DownloadListener listener) { + /* public DownloadListener addDownloadListener(DownloadListener listener) { downloadListeners.add(listener); return listener; } public void removeDownloadListener(DownloadListener listener) { downloadListeners.remove(listener); - } + }*/ public AddressConfidenceListener addAddressConfidenceListener(AddressConfidenceListener listener) { addressConfidenceListeners.add(listener); @@ -1140,7 +1157,7 @@ public class WalletFacade { void downloadComplete(); } - private class BlockChainDownloadListener extends org.bitcoinj.core.DownloadListener { + /* private class BlockChainDownloadListener extends org.bitcoinj.core.DownloadListener { @Override protected void progress(double percent, int blocksSoFar, Date date) { super.progress(percent, blocksSoFar, date); @@ -1164,6 +1181,6 @@ public class WalletFacade { downloadListener.downloadComplete(); } } - } + }*/ } diff --git a/src/main/java/io/bitsquare/di/BitSquareModule.java b/src/main/java/io/bitsquare/di/BitSquareModule.java index 7dd98a1e9c..2ac1ce63df 100644 --- a/src/main/java/io/bitsquare/di/BitSquareModule.java +++ b/src/main/java/io/bitsquare/di/BitSquareModule.java @@ -146,7 +146,7 @@ class NetworkParametersProvider implements Provider { // Set default // String networkType= WalletFacade.MAIN_NET; - // String networkType = WalletFacade.TEST_NET; + //String networkType = WalletFacade.TEST_NET; String networkType = WalletFacade.REG_TEST_NET; if (networkTypeFromConfig != null) diff --git a/src/main/java/io/bitsquare/gui/main/MainModel.java b/src/main/java/io/bitsquare/gui/main/MainModel.java index a49e223dd7..ffbb51e607 100644 --- a/src/main/java/io/bitsquare/gui/main/MainModel.java +++ b/src/main/java/io/bitsquare/gui/main/MainModel.java @@ -23,14 +23,20 @@ import io.bitsquare.gui.UIModel; import io.bitsquare.gui.util.Profiler; import io.bitsquare.msg.DHTSeedService; import io.bitsquare.msg.MessageFacade; +import io.bitsquare.msg.actor.event.PeerInitialized; import io.bitsquare.msg.listeners.BootstrapListener; import io.bitsquare.persistence.Persistence; import io.bitsquare.trade.Trade; import io.bitsquare.trade.TradeManager; import io.bitsquare.user.User; +import org.bitcoinj.core.DownloadListener; + import com.google.inject.Inject; +import java.util.Date; + +import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; @@ -57,11 +63,10 @@ class MainModel extends UIModel { private boolean messageFacadeInited; private boolean walletFacadeInited; - final BooleanProperty backendInited = new SimpleBooleanProperty(); - final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(); - final BooleanProperty networkSyncComplete = new SimpleBooleanProperty(); - // final ObjectProperty balance = new SimpleObjectProperty<>(); + final BooleanProperty backendReady = new SimpleBooleanProperty(); + final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(-1); final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0); + private boolean facadesInitialised; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -120,19 +125,34 @@ class MainModel extends UIModel { Profiler.printMsgWithTime("MainModel.initFacades"); - walletFacade.initialize(() -> { + DownloadListener downloadListener = new DownloadListener() { + @Override + protected void progress(double percent, int blocksLeft, Date date) { + super.progress(percent, blocksLeft, date); + Platform.runLater(() -> { + networkSyncProgress.set(percent / 100.0); + + if (facadesInitialised && percent >= 100.0) + backendReady.set(true); + }); + } + + @Override + protected void doneDownload() { + super.doneDownload(); + Platform.runLater(() -> { + networkSyncProgress.set(1.0); + + if (facadesInitialised) + backendReady.set(true); + }); + } + }; + + walletFacade.initialize(downloadListener, () -> { walletFacadeInited = true; if (messageFacadeInited) onFacadesInitialised(); - - - /* walletFacade.addBalanceListener(new BalanceListener() { - @Override - public void onBalanceChanged(Coin balance) { - updateBalance(balance); - } - }); - updateBalance(walletFacade.getWalletBalance());*/ }); } diff --git a/src/main/java/io/bitsquare/gui/main/MainPM.java b/src/main/java/io/bitsquare/gui/main/MainPM.java index fe4903d49a..b4ad8f0dae 100644 --- a/src/main/java/io/bitsquare/gui/main/MainPM.java +++ b/src/main/java/io/bitsquare/gui/main/MainPM.java @@ -24,9 +24,11 @@ import io.bitsquare.gui.util.BSFormatter; import com.google.inject.Inject; import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; @@ -40,15 +42,14 @@ import org.slf4j.LoggerFactory; class MainPM extends PresentationModel { private static final Logger log = LoggerFactory.getLogger(MainPM.class); - final BooleanProperty backendInited = new SimpleBooleanProperty(); - // final StringProperty balance = new SimpleStringProperty(); + private BSFormatter formatter; + + final BooleanProperty backendReady = new SimpleBooleanProperty(); final StringProperty bankAccountsComboBoxPrompt = new SimpleStringProperty(); final BooleanProperty bankAccountsComboBoxDisable = new SimpleBooleanProperty(); final StringProperty splashScreenInfoText = new SimpleStringProperty(); - final BooleanProperty networkSyncComplete = new SimpleBooleanProperty(); final IntegerProperty numPendingTrades = new SimpleIntegerProperty(); - private BSFormatter formatter; - + final DoubleProperty networkSyncProgress = new SimpleDoubleProperty(); /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -70,22 +71,20 @@ class MainPM extends PresentationModel { public void initialize() { super.initialize(); - backendInited.bind(model.backendInited); - networkSyncComplete.bind(model.networkSyncComplete); + backendReady.bind(model.backendReady); + networkSyncProgress.bind(model.networkSyncProgress); numPendingTrades.bind(model.numPendingTrades); model.networkSyncProgress.addListener((ov, oldValue, newValue) -> { - if ((double) newValue > 0) - splashScreenInfoText.set("Synchronise with network " + formatter.formatToPercent((double) newValue)); + if ((double) newValue > 0.0) + splashScreenInfoText.set("Synchronise with network " + formatter.formatToPercent((double) + newValue)); else if ((double) newValue == 1) splashScreenInfoText.set("Synchronise with network completed."); else splashScreenInfoText.set("Synchronise with network..."); - }); - - /*model.balance.addListener((ov, oldValue, newValue) -> balance.set(formatter.formatCoinWithCode - (newValue)));*/ + splashScreenInfoText.set("Synchronise with network..."); model.getBankAccounts().addListener((ListChangeListener) change -> { bankAccountsComboBoxDisable.set(change.getList().isEmpty()); diff --git a/src/main/java/io/bitsquare/gui/main/MainViewCB.java b/src/main/java/io/bitsquare/gui/main/MainViewCB.java index bc361d666d..1d6eea64a5 100644 --- a/src/main/java/io/bitsquare/gui/main/MainViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/MainViewCB.java @@ -22,7 +22,6 @@ import io.bitsquare.bank.BankAccount; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.OverlayManager; import io.bitsquare.gui.ViewCB; -import io.bitsquare.gui.components.NetworkSyncPane; import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.components.SystemNotification; import io.bitsquare.gui.util.Profiler; @@ -39,6 +38,7 @@ import java.util.ResourceBundle; import javax.inject.Inject; import javafx.animation.Interpolator; +import javafx.application.Platform; import javafx.fxml.Initializable; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -61,10 +61,9 @@ public class MainViewCB extends ViewCB { private final ToggleGroup navButtonsGroup = new ToggleGroup(); private BorderPane baseApplicationContainer; - private VBox baseOverlayContainer; + private VBox splashScreen; private AnchorPane contentContainer; private HBox leftNavPane, rightNavPane; - private NetworkSyncPane networkSyncPane; private ToggleButton buyButton, sellButton, homeButton, msgButton, ordersButton, fundsButton, settingsButton, accountButton; private Pane ordersButtonButtonPane; @@ -166,27 +165,22 @@ public class MainViewCB extends ViewCB { private void startup() { baseApplicationContainer = getBaseApplicationContainer(); - baseOverlayContainer = getSplashScreen(); - ((StackPane) root).getChildren().addAll(baseApplicationContainer, baseOverlayContainer); + splashScreen = getSplashScreen(); + ((StackPane) root).getChildren().addAll(baseApplicationContainer, splashScreen); + baseApplicationContainer.setCenter(getApplicationContainer()); - onBaseContainersCreated(); + Platform.runLater(() -> onSplashScreenAdded()); } - private void onBaseContainersCreated() { - Profiler.printMsgWithTime("MainController.onBaseContainersCreated"); - - AnchorPane applicationContainer = getApplicationContainer(); - baseApplicationContainer.setCenter(applicationContainer); - - presentationModel.backendInited.addListener((ov, oldValue, newValue) -> { + private void onSplashScreenAdded() { + presentationModel.backendReady.addListener((ov, oldValue, newValue) -> { if (newValue) - onBackendInited(); + onBackendReady(); }); - presentationModel.initBackend(); } - private void onBackendInited() { + private void onBackendReady() { Profiler.printMsgWithTime("MainController.onBackendInited"); addMainNavigation(); } @@ -238,7 +232,7 @@ public class MainViewCB extends ViewCB { private void onContentAdded() { Profiler.printMsgWithTime("MainController.onContentAdded"); - Transitions.fadeOutAndRemove(baseOverlayContainer, 1500).setInterpolator(Interpolator.EASE_IN); + Transitions.fadeOutAndRemove(splashScreen, 1500).setInterpolator(Interpolator.EASE_IN); } @@ -302,7 +296,12 @@ public class MainViewCB extends ViewCB { loadingLabel.setPadding(new Insets(80, 0, 0, 0)); loadingLabel.textProperty().bind(presentationModel.splashScreenInfoText); - vBox.getChildren().addAll(logo, subTitle, loadingLabel); + ProgressBar progressBar = new ProgressBar(); + progressBar.setPrefWidth(200); + progressBar.progressProperty().bind(presentationModel.networkSyncProgress); + + vBox.getChildren().addAll(logo, subTitle, loadingLabel, progressBar); + return vBox; } @@ -327,22 +326,7 @@ public class MainViewCB extends ViewCB { AnchorPane.setTopAnchor(contentContainer, 60d); AnchorPane.setBottomAnchor(contentContainer, 25d); - networkSyncPane = new NetworkSyncPane(); - networkSyncPane.setSpacing(10); - networkSyncPane.setPrefHeight(20); - AnchorPane.setLeftAnchor(networkSyncPane, 0d); - AnchorPane.setBottomAnchor(networkSyncPane, 5d); - - // TODO sometimes it keeps running... deactivate ti for the moment and replace it with the notification pane - // from Mike Hearn later - networkSyncPane.setVisible(false); - - presentationModel.networkSyncComplete.addListener((ov, old, newValue) -> { - if (newValue) - networkSyncPane.downloadComplete(); - }); - - anchorPane.getChildren().addAll(leftNavPane, rightNavPane, contentContainer, networkSyncPane); + anchorPane.getChildren().addAll(leftNavPane, rightNavPane, contentContainer); return anchorPane; } @@ -361,8 +345,6 @@ public class MainViewCB extends ViewCB { msgButton = addNavButton(msgButtonHolder, "Messages", Navigation.Item.MSG); leftNavPane.getChildren().add(msgButtonHolder); - //addBalanceInfo(rightNavPane); - addBankAccountComboBox(rightNavPane); settingsButton = addNavButton(rightNavPane, "Preferences", Navigation.Item.SETTINGS); @@ -408,28 +390,6 @@ public class MainViewCB extends ViewCB { return toggleButton; } - /*private void addBalanceInfo(Pane parent) { - final TextField balanceTextField = new TextField(); - balanceTextField.setEditable(false); - balanceTextField.setPrefWidth(110); - balanceTextField.setId("nav-balance-label"); - balanceTextField.textProperty().bind(presentationModel.balance); - - - final Label titleLabel = new Label("Balance"); - titleLabel.setMouseTransparent(true); - titleLabel.setId("nav-button-label"); - balanceTextField.widthProperty().addListener((ov, o, n) -> - titleLabel.setLayoutX(((double) n - titleLabel.getWidth()) / 2)); - - final VBox vBox = new VBox(); - vBox.setPadding(new Insets(12, 5, 0, 0)); - vBox.setSpacing(2); - vBox.getChildren().setAll(balanceTextField, titleLabel); - vBox.setAlignment(Pos.CENTER); - parent.getChildren().add(vBox); - }*/ - private void addBankAccountComboBox(Pane parent) { final ComboBox comboBox = new ComboBox<>(presentationModel.getBankAccounts()); comboBox.setLayoutY(12); @@ -460,4 +420,4 @@ public class MainViewCB extends ViewCB { vBox.getChildren().setAll(comboBox, titleLabel); parent.getChildren().add(vBox); } -} +} \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/main/funds/FundsView.fxml b/src/main/java/io/bitsquare/gui/main/funds/FundsView.fxml index 3f58bc1db7..b6abe3ed7b 100644 --- a/src/main/java/io/bitsquare/gui/main/funds/FundsView.fxml +++ b/src/main/java/io/bitsquare/gui/main/funds/FundsView.fxml @@ -24,6 +24,6 @@ xmlns:fx="http://javafx.com/fxml"> - + \ No newline at end of file diff --git a/src/main/java/io/bitsquare/gui/main/orders/pending/PendingTradesPM.java b/src/main/java/io/bitsquare/gui/main/orders/pending/PendingTradesPM.java index 12562bf5d3..757f13f64f 100644 --- a/src/main/java/io/bitsquare/gui/main/orders/pending/PendingTradesPM.java +++ b/src/main/java/io/bitsquare/gui/main/orders/pending/PendingTradesPM.java @@ -17,7 +17,6 @@ package io.bitsquare.gui.main.orders.pending; -import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.WalletFacade; import io.bitsquare.gui.PresentationModel; import io.bitsquare.gui.components.Popups; @@ -151,7 +150,7 @@ public class PendingTradesPM extends PresentationModel { } String getAmountToWithdraw() { - return formatter.formatCoinWithCode(model.getAmountToWithdraw().subtract(FeePolicy.TX_FEE)); + return formatter.formatCoinWithCode(model.getAmountToWithdraw()); //.subtract(FeePolicy.TX_FEE)); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferViewCB.java b/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferViewCB.java index 4647802ca9..292a431528 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/trade/createoffer/CreateOfferViewCB.java @@ -285,6 +285,8 @@ public class CreateOfferViewCB extends CachedViewCB { private void close() { TabPane tabPane = ((TabPane) (root.getParent().getParent())); tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem()); + + navigation.navigationTo(Navigation.Item.MAIN, Navigation.Item.ORDERS, Navigation.Item.OFFERS); } diff --git a/src/main/java/io/bitsquare/gui/main/trade/orderbook/OrderBookListItem.java b/src/main/java/io/bitsquare/gui/main/trade/orderbook/OrderBookListItem.java index 078ceee9b9..4134237769 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/orderbook/OrderBookListItem.java +++ b/src/main/java/io/bitsquare/gui/main/trade/orderbook/OrderBookListItem.java @@ -23,7 +23,7 @@ import io.bitsquare.trade.Offer; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; -class OrderBookListItem { +public class OrderBookListItem { private final Offer offer; private final ObjectProperty bankAccountCountry = new SimpleObjectProperty<>(); @@ -32,7 +32,7 @@ class OrderBookListItem { // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - OrderBookListItem(Offer offer, Country bankAccountCountry) { + public OrderBookListItem(Offer offer, Country bankAccountCountry) { this.offer = offer; setBankAccountCountry(bankAccountCountry); } @@ -51,7 +51,7 @@ class OrderBookListItem { // Getters /////////////////////////////////////////////////////////////////////////////////////////// - Offer getOffer() { + public Offer getOffer() { return offer; } diff --git a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferModel.java b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferModel.java index c374bfd724..bdc6145004 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferModel.java +++ b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferModel.java @@ -22,6 +22,7 @@ import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.listeners.BalanceListener; import io.bitsquare.gui.UIModel; +import io.bitsquare.persistence.Persistence; import io.bitsquare.settings.Settings; import io.bitsquare.trade.Offer; import io.bitsquare.trade.Trade; @@ -56,6 +57,7 @@ class TakeOfferModel extends UIModel { private final TradeManager tradeManager; private final WalletFacade walletFacade; private final Settings settings; + private Persistence persistence; private Offer offer; private AddressEntry addressEntry; @@ -81,10 +83,11 @@ class TakeOfferModel extends UIModel { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - TakeOfferModel(TradeManager tradeManager, WalletFacade walletFacade, Settings settings) { + TakeOfferModel(TradeManager tradeManager, WalletFacade walletFacade, Settings settings, Persistence persistence) { this.tradeManager = tradeManager; this.walletFacade = walletFacade; this.settings = settings; + this.persistence = persistence; } @@ -168,7 +171,7 @@ class TakeOfferModel extends UIModel { requestTakeOfferErrorMessage.set("Take offer request got rejected."); break; default: - log.error("Unhandled trade state: " + newValue); + log.warn("Unhandled trade state: " + newValue); break; } }); @@ -227,6 +230,13 @@ class TakeOfferModel extends UIModel { return true; } + Boolean displaySecurityDepositInfo() { + Object securityDepositInfoDisplayedObject = persistence.read("displaySecurityDepositInfo"); + if (securityDepositInfoDisplayedObject instanceof Boolean) + return (Boolean) securityDepositInfoDisplayedObject; + else + return true; + } /////////////////////////////////////////////////////////////////////////////////////////// // Setter diff --git a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferPM.java b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferPM.java index 36602979f6..76ab575f89 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferPM.java +++ b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferPM.java @@ -303,6 +303,10 @@ class TakeOfferPM extends PresentationModel { return paymentLabel; } + Boolean displaySecurityDepositInfo() { + return model.displaySecurityDepositInfo(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Private diff --git a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewCB.java b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewCB.java index 3f63df824a..1e5934c3d1 100644 --- a/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferViewCB.java @@ -201,6 +201,23 @@ public class TakeOfferViewCB extends CachedViewCB { @FXML void onShowPayFundsScreen() { + if (presentationModel.displaySecurityDepositInfo()) { + overlayManager.blurContent(); + List actions = new ArrayList<>(); + actions.add(new AbstractAction(BSResources.get("shared.close")) { + @Override + public void handle(ActionEvent actionEvent) { + Dialog.Actions.CLOSE.handle(actionEvent); + overlayManager.removeBlurContent(); + } + }); + Popups.openInfo("To ensure that both traders behave fair they need to pay a security deposit.", + "The deposit will stay in your local trading wallet until the offer gets accepted by " + + "another trader. " + + "\nIt will be refunded to you after the trade has successfully completed.", + actions); + } + priceAmountPane.setInactive(); showPaymentInfoScreenButton.setVisible(false); diff --git a/src/main/java/io/bitsquare/gui/util/BSFormatter.java b/src/main/java/io/bitsquare/gui/util/BSFormatter.java index cba210a7a0..1f3244540d 100644 --- a/src/main/java/io/bitsquare/gui/util/BSFormatter.java +++ b/src/main/java/io/bitsquare/gui/util/BSFormatter.java @@ -309,7 +309,7 @@ public class BSFormatter { decimalFormat.setMinimumFractionDigits(1); decimalFormat.setMaximumFractionDigits(1); decimalFormat.setGroupingUsed(false); - return decimalFormat.format(value / 100) + " %"; + return decimalFormat.format(value * 100.0) + " %"; } private String cleanInput(String input) { diff --git a/src/main/java/io/bitsquare/locale/BSResources.java b/src/main/java/io/bitsquare/locale/BSResources.java index 429c436e91..386c02e791 100644 --- a/src/main/java/io/bitsquare/locale/BSResources.java +++ b/src/main/java/io/bitsquare/locale/BSResources.java @@ -48,12 +48,12 @@ public class BSResources { try { return BSResources.getResourceBundle().getString(key); } catch (MissingResourceException e) { - log.warn("MissingResourceException for key: " + key); + log.warn("Missing resource for key: " + key); return key; } } - public static String get(String key, String... arguments) { + public static String get(String key, Object... arguments) { return MessageFormat.format(BSResources.get(key), arguments); } } diff --git a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java b/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java index 8214207a7a..fc56855367 100644 --- a/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java +++ b/src/main/java/io/bitsquare/msg/BootstrappedPeerFactory.java @@ -35,6 +35,10 @@ import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import javafx.application.Platform; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + import net.tomp2p.connection.Ports; import net.tomp2p.dht.PeerBuilderDHT; import net.tomp2p.dht.PeerDHT; @@ -76,6 +80,7 @@ public class BootstrappedPeerFactory { private final Persistence persistence; private final SettableFuture settableFuture = SettableFuture.create(); + public final StringProperty connectionState = new SimpleStringProperty(); /////////////////////////////////////////////////////////////////////////////////////////// @@ -194,6 +199,9 @@ public class BootstrappedPeerFactory { log.debug("We are not behind a NAT and reachable to other peers: My address visible to the " + "outside is " + futureDiscover.peerAddress()); requestBootstrapPeerMap(); + setConnectionState("We are not behind a NAT and reachable to other peers: My address visible to " + + "the " + + "outside is " + futureDiscover.peerAddress()); settableFuture.set(peerDHT); persistence.write(ref, "lastSuccessfulBootstrap", "default"); @@ -203,6 +211,10 @@ public class BootstrappedPeerFactory { log.warn("We are probably behind a NAT and not reachable to other peers. We try port forwarding " + "as next step."); + setConnectionState("We are probably behind a NAT and not reachable to other peers. We try port " + + "forwarding " + + "as next step."); + bootstrapWithPortForwarding(peerDHT, futureDiscover); } } @@ -230,6 +242,8 @@ public class BootstrappedPeerFactory { log.debug("Port forwarding was successful. My address visible to the outside is " + futureNAT.peerAddress()); requestBootstrapPeerMap(); + setConnectionState("Port forwarding was successful. My address visible to the outside is " + + futureNAT.peerAddress()); settableFuture.set(peerDHT); persistence.write(ref, "lastSuccessfulBootstrap", "portForwarding"); @@ -238,6 +252,8 @@ public class BootstrappedPeerFactory { log.warn("Port forwarding has failed. Reason: " + futureNAT.failedReason()); log.warn("We try to use a relay as next step."); + setConnectionState("We try to use a relay as next step."); + bootstrapWithRelay(peerDHT, nodeBehindNat); } } @@ -324,6 +340,8 @@ public class BootstrappedPeerFactory { if (future.isSuccess()) { log.debug("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2.bootstrapTo()); requestBootstrapPeerMap(); + setConnectionState("Final bootstrap was successful. bootstrapTo = " + futureBootstrap2 + .bootstrapTo()); settableFuture.set(peerDHT); persistence.write(ref, "lastSuccessfulBootstrap", "relay"); @@ -348,4 +366,8 @@ public class BootstrappedPeerFactory { private void requestBootstrapPeerMap() { log.debug("getBootstrapPeerMap"); } + + private void setConnectionState(String state) { + Platform.runLater(() -> connectionState.set(state)); + } } diff --git a/src/main/java/io/bitsquare/msg/MessageFacade.java b/src/main/java/io/bitsquare/msg/MessageFacade.java index 8b795aa9d0..4cfe1e06cf 100644 --- a/src/main/java/io/bitsquare/msg/MessageFacade.java +++ b/src/main/java/io/bitsquare/msg/MessageFacade.java @@ -177,6 +177,7 @@ public class MessageFacade implements MessageBroker { try { Object offerDataObject = offerData.object(); if (offerDataObject instanceof Offer) { + log.error("Added offer to DHT with ID: " + ((Offer) offerDataObject).getId()); listener.onOfferAdded((Offer) offerDataObject); } } catch (ClassNotFoundException | IOException e) { diff --git a/src/main/java/io/bitsquare/trade/TradeManager.java b/src/main/java/io/bitsquare/trade/TradeManager.java index be33714191..a8cc7d950b 100644 --- a/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/src/main/java/io/bitsquare/trade/TradeManager.java @@ -373,7 +373,7 @@ public class TradeManager { // probably not needed @Override public void onWaitingForPeerResponse(SellerTakesOfferProtocol.State state) { - log.error("onWaitingForPeerResponse"); + log.debug("onWaitingForPeerResponse"); } }; diff --git a/src/main/resources/i18n/displayStrings.properties b/src/main/resources/i18n/displayStrings.properties index 0851e9af11..9b1f2e866a 100644 --- a/src/main/resources/i18n/displayStrings.properties +++ b/src/main/resources/i18n/displayStrings.properties @@ -71,7 +71,9 @@ createOffer.advancedBox.county=Payments account country: createOffer.advancedBox.info=Your trading partners must fulfill your offer restrictions. You can edit the accepted countries, languages and arbitrators in the settings. The payments account details are used from your current selected payments account (if you have multiple payments accounts). createOffer.success.headline=Your offer has been successfully published to the distributed offerbook. -createOffer.success.info=The Transaction ID for the offer payment is: {0} +createOffer.success.info=In the Offers screen you can manage your open offers.\n\nThe Transaction ID for the offer \ + payment is: {0} + createOffer.error.message=An error occurred when placing the offer.\n{0} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 75ed2bdde6..6b4d2431bf 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -36,6 +36,10 @@ + + + + + + + + + + + + + + + +