From 844a6dd66c9b96a457ddd51e5a3bfc47f04cd682 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sun, 10 May 2015 13:31:09 +0200 Subject: [PATCH] Add btc network selector to preferences --- .../app/bootstrap/BootstrapNode.java | 14 ++-- .../app/bootstrap/BootstrapNodeMain.java | 10 ++- .../bitsquare/app/BitsquareEnvironment.java | 7 +- .../java/io/bitsquare/btc/BitcoinModule.java | 1 - .../java/io/bitsquare/btc/BitcoinNetwork.java | 4 +- .../main/java/io/bitsquare/btc/FeePolicy.java | 5 +- .../io/bitsquare/btc/TradeWalletService.java | 5 +- .../java/io/bitsquare/btc/WalletService.java | 9 +- .../java/io/bitsquare/p2p/BootstrapNodes.java | 13 ++- core/src/main/java/io/bitsquare/p2p/Node.java | 6 +- .../p2p/tomp2p/BootstrappedPeerBuilder.java | 82 +++++++++++++++++-- .../java/io/bitsquare/user/Preferences.java | 31 ++++++- .../java/io/bitsquare/app/BitsquareApp.java | 4 + .../io/bitsquare/gui/main/MainViewModel.java | 8 +- .../settings/network/NetworkSettingsView.fxml | 60 ++++++++------ .../settings/network/NetworkSettingsView.java | 61 +++++++++++++- .../util/validation/BtcAddressValidator.java | 10 +-- 17 files changed, 248 insertions(+), 82 deletions(-) diff --git a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java index 617b490c33..b8a46d791a 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNode.java @@ -22,7 +22,6 @@ import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.Node; import java.util.Collection; -import java.util.Random; import java.util.stream.Collectors; import net.tomp2p.dht.PeerBuilderDHT; @@ -45,6 +44,9 @@ public class BootstrapNode { private static final String VERSION = "0.1.3"; + public static final String P2P_ID = "node.p2pId"; + public static int DEFAULT_P2P_ID = 1; // 0 | 1 | 2 for mainnet/testnet/regtest + private static Peer peer = null; private final Environment env; @@ -56,12 +58,13 @@ public class BootstrapNode { public void start() { - int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.PORT); - String name = env.getProperty(Node.NAME_KEY, BootstrapNodes.DEFAULT_NODE_NAME); + int p2pId = env.getProperty(P2P_ID, Integer.class, DEFAULT_P2P_ID); + int port = env.getProperty(Node.PORT_KEY, Integer.class, BootstrapNodes.BASE_PORT + p2pId); + String name = env.getRequiredProperty(Node.NAME_KEY); Logging.setup(name + "_" + port); try { - Number160 peerId = Number160.createHash(new Random().nextInt()); + Number160 peerId = Number160.createHash(name); /* DefaultEventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(50); ChannelClientConfiguration clientConf = PeerBuilder.createDefaultChannelClientConfiguration(); @@ -73,6 +76,7 @@ public class BootstrapNode { peer = new PeerBuilder(peerId) .ports(port) + .p2pId(p2pId) /* .channelClientConfiguration(clientConf) .channelServerConfiguration(serverConf)*/ .start(); @@ -87,7 +91,7 @@ public class BootstrapNode { if (!name.equals(BootstrapNodes.LOCALHOST.getName())) { Collection bootstrapNodes = BootstrapNodes.getAllBootstrapNodes().stream().filter(e -> !e.getName().equals(name)) - .map(e -> e.toPeerAddress()).collect(Collectors.toList()); + .map(e -> e.toPeerAddressWithPort(port)).collect(Collectors.toList()); log.info("Bootstrapping to " + bootstrapNodes.size() + " bootstrapNode(s)"); log.info("Bootstrapping bootstrapNodes " + bootstrapNodes); diff --git a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java index 0d0c416447..dc06c754e1 100644 --- a/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java +++ b/bootstrap/src/main/java/io/bitsquare/app/bootstrap/BootstrapNodeMain.java @@ -32,9 +32,13 @@ public class BootstrapNodeMain extends BitsquareExecutable { } protected void customizeOptionParsing(OptionParser parser) { - parser.accepts(Node.NAME_KEY, description("Name of this node", BootstrapNodes.DEFAULT_NODE_NAME)) - .withRequiredArg(); - parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.PORT)) + parser.accepts(Node.NAME_KEY, description("Name of this node", null)) + .withRequiredArg() + .isRequired(); + parser.accepts(Node.PORT_KEY, description("Port to listen on", BootstrapNodes.BASE_PORT)) + .withRequiredArg() + .ofType(int.class); + parser.accepts(BootstrapNode.P2P_ID, description("P2P Network ID [0 | 1 | 2 for mainnet/testnet/regtest]", BootstrapNode.DEFAULT_P2P_ID)) .withRequiredArg() .ofType(int.class); } diff --git a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java index 3c0994893d..5c864266a2 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareEnvironment.java @@ -18,7 +18,6 @@ package io.bitsquare.app; import io.bitsquare.BitsquareException; -import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.UserAgent; import io.bitsquare.btc.WalletService; import io.bitsquare.crypto.KeyStorage; @@ -88,12 +87,8 @@ public class BitsquareEnvironment extends StandardEnvironment { (String) commandLineProperties.getProperty(APP_DATA_DIR_KEY) : appDataDir(userDataDir, appName); - String bitcoinNetwork = commandLineProperties.containsProperty(BitcoinNetwork.KEY) ? - (String) commandLineProperties.getProperty(BitcoinNetwork.KEY) : - BitcoinNetwork.DEFAULT.toString(); - this.bootstrapNodePort = commandLineProperties.containsProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) ? - (String) commandLineProperties.getProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) : String.valueOf(BootstrapNodes.PORT); + (String) commandLineProperties.getProperty(TomP2PModule.BOOTSTRAP_NODE_PORT_KEY) : String.valueOf(BootstrapNodes.BASE_PORT); MutablePropertySources propertySources = this.getPropertySources(); propertySources.addFirst(commandLineProperties); diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java index 4fbe23863b..5d0a484cdb 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -40,7 +40,6 @@ public class BitcoinModule extends BitsquareModule { @Override protected void configure() { - bind(BitcoinNetwork.class).toInstance(env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); bind(RegTestHost.class).toInstance(env.getProperty(RegTestHost.KEY, RegTestHost.class, RegTestHost.DEFAULT)); bind(FeePolicy.class).in(Singleton.class); diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java index 152d01db6e..5840681235 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinNetwork.java @@ -22,7 +22,9 @@ import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; import org.bitcoinj.params.TestNet3Params; -public enum BitcoinNetwork { +import java.io.Serializable; + +public enum BitcoinNetwork implements Serializable { MAINNET(MainNetParams.get()), TESTNET(TestNet3Params.get()), diff --git a/core/src/main/java/io/bitsquare/btc/FeePolicy.java b/core/src/main/java/io/bitsquare/btc/FeePolicy.java index 959714c133..523215193a 100644 --- a/core/src/main/java/io/bitsquare/btc/FeePolicy.java +++ b/core/src/main/java/io/bitsquare/btc/FeePolicy.java @@ -18,6 +18,7 @@ package io.bitsquare.btc; import io.bitsquare.BitsquareException; +import io.bitsquare.user.Preferences; import org.bitcoinj.core.Address; import org.bitcoinj.core.AddressFormatException; @@ -41,8 +42,8 @@ public class FeePolicy { private final String takeOfferFeeAddress; @Inject - public FeePolicy(BitcoinNetwork bitcoinNetwork) { - this.bitcoinNetwork = bitcoinNetwork; + public FeePolicy(Preferences preferences) { + this.bitcoinNetwork = preferences.getBitcoinNetwork(); switch (bitcoinNetwork) { case TESTNET: diff --git a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java index 5ea59dda49..21a94b26b1 100644 --- a/core/src/main/java/io/bitsquare/btc/TradeWalletService.java +++ b/core/src/main/java/io/bitsquare/btc/TradeWalletService.java @@ -20,6 +20,7 @@ package io.bitsquare.btc; import io.bitsquare.btc.exceptions.SigningException; import io.bitsquare.btc.exceptions.TransactionVerificationException; import io.bitsquare.btc.exceptions.WalletException; +import io.bitsquare.user.Preferences; import org.bitcoinj.core.Address; import org.bitcoinj.core.AddressFormatException; @@ -91,8 +92,8 @@ public class TradeWalletService { private final FeePolicy feePolicy; @Inject - public TradeWalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy) { - this.params = bitcoinNetwork.getParameters(); + public TradeWalletService(Preferences preferences, FeePolicy feePolicy) { + this.params = preferences.getBitcoinNetwork().getParameters(); this.feePolicy = feePolicy; } diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index f72bc3fe53..d0fe6e34c1 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -21,6 +21,7 @@ import io.bitsquare.btc.listeners.AddressConfidenceListener; import io.bitsquare.btc.listeners.BalanceListener; import io.bitsquare.btc.listeners.TxConfidenceListener; import io.bitsquare.crypto.CryptoService; +import io.bitsquare.user.Preferences; import org.bitcoinj.core.AbstractWalletEventListener; import org.bitcoinj.core.Address; @@ -127,15 +128,15 @@ public class WalletService { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public WalletService(BitcoinNetwork bitcoinNetwork, RegTestHost regTestHost, CryptoService cryptoService, + public WalletService(RegTestHost regTestHost, CryptoService cryptoService, TradeWalletService tradeWalletService, AddressEntryList addressEntryList, UserAgent userAgent, - @Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix) { + @Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix, Preferences preferences) { this.regTestHost = regTestHost; this.tradeWalletService = tradeWalletService; this.addressEntryList = addressEntryList; - this.params = bitcoinNetwork.getParameters(); + this.params = preferences.getBitcoinNetwork().getParameters(); this.cryptoService = cryptoService; - this.walletDir = walletDir; + this.walletDir = new File(walletDir, preferences.getBitcoinNetwork().toString().toLowerCase()); this.walletPrefix = walletPrefix; this.userAgent = userAgent; } diff --git a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java index 8effd1634c..13a9c21743 100644 --- a/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java +++ b/core/src/main/java/io/bitsquare/p2p/BootstrapNodes.java @@ -27,20 +27,19 @@ import org.slf4j.LoggerFactory; public class BootstrapNodes { private static final Logger log = LoggerFactory.getLogger(BootstrapNodes.class); - public static final int PORT = 7366; - public static final String DEFAULT_NODE_NAME = "default"; - + public static final int BASE_PORT = 7366; // port will be evaluated from btc network 7366 for mainnet, 7367 for testnet and 7368 for regtest + private static List bootstrapNodes = Arrays.asList( - Node.at(DEFAULT_NODE_NAME, "188.226.179.109", PORT), - Node.at(DEFAULT_NODE_NAME, "52.24.144.42", PORT), - Node.at(DEFAULT_NODE_NAME, "52.11.125.194", PORT) + //Node.at("digitalocean1.bitsquare.io", "188.226.179.109", BASE_PORT), + Node.at("aws1.bitsquare.io", "52.24.144.42", BASE_PORT), + Node.at("aws2.bitsquare.io", "52.11.125.194", BASE_PORT) ); /** * A locally-running BootstrapNode instance. * Typically used only for testing. Not included in results from {@link #getAllBootstrapNodes()}. */ - public static Node LOCALHOST = Node.at("localhost", "127.0.0.1", PORT); + public static Node LOCALHOST = Node.at("localhost", "127.0.0.1", BASE_PORT); private static Node selectedNode = bootstrapNodes.get(new Random().nextInt(bootstrapNodes.size())); diff --git a/core/src/main/java/io/bitsquare/p2p/Node.java b/core/src/main/java/io/bitsquare/p2p/Node.java index 84998410b5..43ac287069 100644 --- a/core/src/main/java/io/bitsquare/p2p/Node.java +++ b/core/src/main/java/io/bitsquare/p2p/Node.java @@ -94,12 +94,12 @@ public final class Node { return port; } - public PeerAddress toPeerAddress() { + public PeerAddress toPeerAddressWithPort(int port) { try { return new PeerAddress(Number160.createHash(getName()), InetAddress.getByName(getIp()), - getPort(), - getPort()); + port, + port); } catch (UnknownHostException e) { log.error("toPeerAddress failed: " + e.getMessage()); return null; diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java index 66aedcc639..6f37ffb36b 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java @@ -19,6 +19,7 @@ package io.bitsquare.p2p.tomp2p; import io.bitsquare.p2p.BootstrapNodes; import io.bitsquare.p2p.Node; +import io.bitsquare.user.Preferences; import com.google.common.util.concurrent.SettableFuture; @@ -114,17 +115,17 @@ public class BootstrappedPeerBuilder { } } - private KeyPair keyPair; private final int port; private final boolean useManualPortForwarding; - private Node bootstrapNode; private final String networkInterface; + private final Preferences preferences; private final SettableFuture settableFuture = SettableFuture.create(); - private final ObjectProperty state = new SimpleObjectProperty<>(State.UNDEFINED); private final ObjectProperty connectionType = new SimpleObjectProperty<>(ConnectionType.UNDEFINED); + private Node bootstrapNode; + private KeyPair keyPair; private Peer peer; private PeerDHT peerDHT; private boolean retriedOtherBootstrapNode; @@ -139,13 +140,13 @@ public class BootstrappedPeerBuilder { public BootstrappedPeerBuilder(@Named(Node.PORT_KEY) int port, @Named(USE_MANUAL_PORT_FORWARDING_KEY) boolean useManualPortForwarding, @Named(BOOTSTRAP_NODE_KEY) Node bootstrapNode, - @Named(NETWORK_INTERFACE_KEY) String networkInterface) { + @Named(NETWORK_INTERFACE_KEY) String networkInterface, + Preferences preferences) { this.port = port; this.useManualPortForwarding = useManualPortForwarding; this.bootstrapNode = bootstrapNode; this.networkInterface = networkInterface; - - log.debug("Bootstrap to {}", bootstrapNode.toString()); + this.preferences = preferences; } @@ -168,6 +169,10 @@ public class BootstrappedPeerBuilder { public SettableFuture start(int networkId) { try { + // port is evaluated from btc network. 7366 for mainnet, 7367 for testnet and 7368 for regtest + bootstrapNode = Node.at(bootstrapNode.getName(), bootstrapNode.getIp(), bootstrapNode.getPort() + networkId); + log.debug("Bootstrap to {}", bootstrapNode.toString()); + DefaultEventExecutorGroup eventExecutorGroup = new DefaultEventExecutorGroup(20); ChannelClientConfiguration clientConf = PeerBuilder.createDefaultChannelClientConfiguration(); clientConf.pipelineFilter(new PeerBuilder.EventExecutorGroupFilter(eventExecutorGroup)); @@ -219,8 +224,10 @@ public class BootstrappedPeerBuilder { // log.debug("Peer updated: peerAddress=" + peerAddress + ", peerStatistics=" + peerStatistics); } }); - - discoverExternalAddress(); + if (preferences.getUseUPnP()) + discoverExternalAddressUsingUPnP(); + else + discoverExternalAddress(); } catch (IOException e) { handleError(State.PEER_CREATION_FAILED, "Cannot create a peer with port: " + port + ". Exception: " + e); @@ -247,10 +254,11 @@ public class BootstrappedPeerBuilder { // 4. If the port forwarding failed we can try as last resort to open a permanent TCP connection to the // bootstrap node and use that peer as relay - private void discoverExternalAddress() { + private void discoverExternalAddressUsingUPnP() { FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start(); setState(State.DISCOVERY_STARTED); PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); + FutureNAT futureNAT = peerNAT.startSetupPortforwarding(futureDiscover); FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover, futureNAT); @@ -312,6 +320,62 @@ public class BootstrappedPeerBuilder { }); } + private void discoverExternalAddress() { + FutureDiscover futureDiscover = peer.discover().peerAddress(getBootstrapAddress()).start(); + setState(State.DISCOVERY_STARTED); + PeerNAT peerNAT = new PeerBuilderNAT(peer).start(); + + FutureRelayNAT futureRelayNAT = peerNAT.startRelay(new TCPRelayClientConfig(), futureDiscover); + + futureRelayNAT.addListener(new BaseFutureListener() { + @Override + public void operationComplete(BaseFuture futureRelayNAT) throws Exception { + if (futureDiscover.isSuccess()) { + if (useManualPortForwarding) { + setState(State.DISCOVERY_MANUAL_PORT_FORWARDING_SUCCEEDED, + "NAT traversal successful with manual port forwarding."); + setConnectionType(ConnectionType.MANUAL_PORT_FORWARDING); + bootstrap(); + } + else { + setState(State.DISCOVERY_DIRECT_SUCCEEDED, "Visible to the network. No NAT traversal needed."); + setConnectionType(ConnectionType.DIRECT); + bootstrap(); + } + } + else { + if (futureRelayNAT.isSuccess()) { + // relay mode succeeded + setState(State.RELAY_SUCCEEDED, "Using relay mode."); + setConnectionType(ConnectionType.RELAY); + bootstrap(); + } + else { + if (!retriedOtherBootstrapNode && BootstrapNodes.getAllBootstrapNodes().size() > 1) { + log.warn("Bootstrap failed with bootstrapNode: " + bootstrapNode + ". We try again with another node."); + retriedOtherBootstrapNode = true; + Optional optional = BootstrapNodes.getAllBootstrapNodes().stream().filter(e -> !e.equals(bootstrapNode)).findAny(); + if (optional.isPresent()) { + bootstrapNode = optional.get(); + executor.execute(() -> discoverExternalAddress()); + } + } + else { + // All attempts failed. Give up... + handleError(State.RELAY_FAILED, "NAT traversal using relay mode failed " + + futureRelayNAT.failedReason()); + } + } + } + } + + @Override + public void exceptionCaught(Throwable t) throws Exception { + handleError(State.RELAY_FAILED, "Exception at bootstrap: " + t.getMessage()); + } + }); + } + private void bootstrap() { log.trace("start bootstrap"); diff --git a/core/src/main/java/io/bitsquare/user/Preferences.java b/core/src/main/java/io/bitsquare/user/Preferences.java index 811482bbb7..4b686eede5 100644 --- a/core/src/main/java/io/bitsquare/user/Preferences.java +++ b/core/src/main/java/io/bitsquare/user/Preferences.java @@ -18,6 +18,7 @@ package io.bitsquare.user; import io.bitsquare.app.Version; +import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.storage.Storage; import org.bitcoinj.utils.MonetaryFormat; @@ -37,6 +38,8 @@ import javafx.beans.property.StringProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; + public class Preferences implements Serializable { // That object is saved to disc. We need to take care of changes to not break deserialization. private static final long serialVersionUID = Version.LOCAL_DB_VERSION; @@ -45,7 +48,6 @@ public class Preferences implements Serializable { // Deactivate mBit for now as most screens are not supporting it yet transient private static final List BTC_DENOMINATIONS = Arrays.asList(MonetaryFormat.CODE_BTC/*, MonetaryFormat.CODE_MBTC*/); - public static List getBtcDenominations() { return BTC_DENOMINATIONS; } @@ -54,21 +56,25 @@ public class Preferences implements Serializable { // Persisted fields private String btcDenomination = MonetaryFormat.CODE_BTC; + private boolean useAnimations = true; private boolean useEffects = true; private boolean displaySecurityDepositInfo = true; + private boolean useUPnP = true; + private BitcoinNetwork bitcoinNetwork; // Observable wrappers transient private final StringProperty btcDenominationProperty = new SimpleStringProperty(btcDenomination); transient private final BooleanProperty useAnimationsProperty = new SimpleBooleanProperty(useAnimations); transient private final BooleanProperty useEffectsProperty = new SimpleBooleanProperty(useEffects); + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public Preferences(Storage storage) { + public Preferences(Storage storage, Environment environment) { this.storage = storage; Preferences persisted = storage.initAndGetPersisted(this); @@ -76,8 +82,13 @@ public class Preferences implements Serializable { setBtcDenomination(persisted.btcDenomination); setUseAnimations(persisted.useAnimations); setUseEffects(persisted.useEffects); + setUseUPnP(persisted.useUPnP); + setBitcoinNetwork(persisted.bitcoinNetwork); displaySecurityDepositInfo = persisted.getDisplaySecurityDepositInfo(); } + else { + setBitcoinNetwork(environment.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); + } // Use that to guarantee update of the serializable field and to make a storage update in case of a change btcDenominationProperty.addListener((ov) -> { @@ -116,6 +127,16 @@ public class Preferences implements Serializable { storage.queueUpForSave(); } + public void setUseUPnP(boolean useUPnP) { + this.useUPnP = useUPnP; + storage.queueUpForSave(); + } + + public void setBitcoinNetwork(BitcoinNetwork bitcoinNetwork) { + this.bitcoinNetwork = bitcoinNetwork; + storage.queueUpForSave(); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Getter @@ -149,5 +170,11 @@ public class Preferences implements Serializable { return useEffectsProperty; } + public boolean getUseUPnP() { + return useUPnP; + } + public BitcoinNetwork getBitcoinNetwork() { + return bitcoinNetwork; + } } diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 15e2088cf2..75490b717c 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -69,6 +69,8 @@ public class BitsquareApp extends Application { private List corruptedDatabaseFiles = new ArrayList<>(); private MainView mainView; + public static Runnable shutDownHandler; + public static void setEnvironment(Environment env) { BitsquareApp.env = env; } @@ -77,6 +79,8 @@ public class BitsquareApp extends Application { public void start(Stage primaryStage) throws IOException { this.primaryStage = primaryStage; + shutDownHandler = this::stop; + // setup UncaughtExceptionHandler Thread.UncaughtExceptionHandler handler = (thread, throwable) -> { // Might come from another thread diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index cfa5227f28..025b6c48f4 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -20,7 +20,6 @@ package io.bitsquare.gui.main; import io.bitsquare.app.UpdateProcess; import io.bitsquare.app.Version; import io.bitsquare.arbitration.ArbitrationRepository; -import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.WalletService; import io.bitsquare.crypto.KeyRing; import io.bitsquare.fiat.FiatAccount; @@ -33,6 +32,7 @@ import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder; import io.bitsquare.trade.Trade; import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.offer.OpenOfferManager; +import io.bitsquare.user.Preferences; import io.bitsquare.user.User; import io.bitsquare.util.Utilities; @@ -117,7 +117,7 @@ class MainViewModel implements ViewModel { @Inject public MainViewModel(User user, KeyRing keyRing, WalletService walletService, ArbitrationRepository arbitrationRepository, ClientNode clientNode, - TradeManager tradeManager, OpenOfferManager openOfferManager, BitcoinNetwork bitcoinNetwork, UpdateProcess updateProcess, + TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences, UpdateProcess updateProcess, BSFormatter formatter) { this.user = user; this.keyRing = keyRing; @@ -129,8 +129,8 @@ class MainViewModel implements ViewModel { this.updateProcess = updateProcess; this.formatter = formatter; - bitcoinNetworkAsString = formatter.formatBitcoinNetwork(bitcoinNetwork); - networkId = bitcoinNetwork.ordinal(); + bitcoinNetworkAsString = formatter.formatBitcoinNetwork(preferences.getBitcoinNetwork()); + networkId = preferences.getBitcoinNetwork().ordinal(); updateProcess.state.addListener((observableValue, oldValue, newValue) -> applyUpdateState(newValue)); applyUpdateState(updateProcess.state.get()); diff --git a/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml b/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml index 20c1c836d0..b6cb477d75 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/settings/network/NetworkSettingsView.fxml @@ -31,7 +31,7 @@ - +