diff --git a/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java b/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java index 67ef050693..e69680e0c8 100644 --- a/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java +++ b/src/main/java/io/bitsquare/app/gui/BitsquareAppMain.java @@ -19,15 +19,15 @@ package io.bitsquare.app.gui; import io.bitsquare.app.BitsquareEnvironment; import io.bitsquare.app.BitsquareExecutable; -import io.bitsquare.btc.BitcoinModule; +import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.network.BootstrapNodes; import io.bitsquare.network.Node; +import io.bitsquare.util.joptsimple.EnumValueConverter; import joptsimple.OptionParser; import joptsimple.OptionSet; import static io.bitsquare.app.BitsquareEnvironment.*; -import static io.bitsquare.btc.BitcoinModule.BITCOIN_NETWORK_KEY; import static io.bitsquare.msg.tomp2p.TomP2PMessageModule.*; import static io.bitsquare.network.Node.*; @@ -44,8 +44,10 @@ public class BitsquareAppMain extends BitsquareExecutable { parser.accepts(APP_DATA_DIR_KEY, "Application data directory").withRequiredArg() .defaultsTo(DEFAULT_APP_DATA_DIR); parser.accepts(NAME_KEY, "Name of this node").withRequiredArg(); - parser.accepts(BITCOIN_NETWORK_KEY).withRequiredArg().defaultsTo(BitcoinModule.DEFAULT_BITCOIN_NETWORK); parser.accepts(PORT_KEY, "Port to listen on").withRequiredArg().ofType(int.class).defaultsTo(Node.DEFAULT_PORT); + parser.accepts(BitcoinNetwork.KEY).withRequiredArg().ofType(BitcoinNetwork.class) + .withValuesConvertedBy(new EnumValueConverter(BitcoinNetwork.class)) + .defaultsTo(BitcoinNetwork.DEFAULT); parser.accepts(BOOTSTRAP_NODE_NAME_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getName()); parser.accepts(BOOTSTRAP_NODE_IP_KEY).withRequiredArg().defaultsTo(BootstrapNodes.DEFAULT.getIp()); parser.accepts(BOOTSTRAP_NODE_PORT_KEY).withRequiredArg().ofType(int.class) diff --git a/src/main/java/io/bitsquare/btc/BitcoinModule.java b/src/main/java/io/bitsquare/btc/BitcoinModule.java index 2105829d3a..48eae71bfb 100644 --- a/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -34,8 +34,6 @@ import static com.google.inject.name.Names.named; public class BitcoinModule extends BitsquareModule { - public static final String BITCOIN_NETWORK_KEY = "bitcoin.network"; - public static final String DEFAULT_BITCOIN_NETWORK = BitcoinNetwork.TESTNET.toString(); public BitcoinModule(Environment env) { super(env); @@ -43,7 +41,8 @@ public class BitcoinModule extends BitsquareModule { @Override protected void configure() { - bind(NetworkParameters.class).toInstance(network()); + bind(BitcoinNetwork.class).toInstance( + env.getProperty(BitcoinNetwork.KEY, BitcoinNetwork.class, BitcoinNetwork.DEFAULT)); bind(FeePolicy.class).asEagerSingleton(); bindConstant().annotatedWith(named(UserAgent.NAME_KEY)).to(env.getRequiredProperty(UserAgent.NAME_KEY)); @@ -63,21 +62,5 @@ public class BitcoinModule extends BitsquareModule { protected void doClose(Injector injector) { injector.getInstance(WalletService.class).shutDown(); } - - private NetworkParameters network() { - BitcoinNetwork network = BitcoinNetwork.valueOf( - env.getProperty(BITCOIN_NETWORK_KEY, DEFAULT_BITCOIN_NETWORK).toUpperCase()); - - switch (network) { - case MAINNET: - return MainNetParams.get(); - case TESTNET: - return TestNet3Params.get(); - case REGTEST: - return RegTestParams.get(); - default: - throw new IllegalArgumentException("Unknown bitcoin network: " + network); - } - } } diff --git a/src/main/java/io/bitsquare/btc/BitcoinNetwork.java b/src/main/java/io/bitsquare/btc/BitcoinNetwork.java index d0a1fa2007..152d01db6e 100644 --- a/src/main/java/io/bitsquare/btc/BitcoinNetwork.java +++ b/src/main/java/io/bitsquare/btc/BitcoinNetwork.java @@ -17,6 +17,27 @@ package io.bitsquare.btc; +import org.bitcoinj.core.NetworkParameters; +import org.bitcoinj.params.MainNetParams; +import org.bitcoinj.params.RegTestParams; +import org.bitcoinj.params.TestNet3Params; + public enum BitcoinNetwork { - MAINNET, TESTNET, REGTEST; + + MAINNET(MainNetParams.get()), + TESTNET(TestNet3Params.get()), + REGTEST(RegTestParams.get()); + + public static final String KEY = "bitcoin.network"; + public static final BitcoinNetwork DEFAULT = TESTNET; + + private final NetworkParameters parameters; + + BitcoinNetwork(NetworkParameters parameters) { + this.parameters = parameters; + } + + public NetworkParameters getParameters() { + return parameters; + } } diff --git a/src/main/java/io/bitsquare/btc/FeePolicy.java b/src/main/java/io/bitsquare/btc/FeePolicy.java index 1e3d2b92f1..183be85354 100644 --- a/src/main/java/io/bitsquare/btc/FeePolicy.java +++ b/src/main/java/io/bitsquare/btc/FeePolicy.java @@ -20,11 +20,7 @@ package io.bitsquare.btc; import org.bitcoinj.core.Address; 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; @@ -49,28 +45,29 @@ public class FeePolicy { // Not used at the moment // private static final String registrationFeeAddress = "mvkDXt4QmN4Nq9dRUsRigBCaovde9nLkZR"; - // private static String createOfferFeeAddress; private static String takeOfferFeeAddress; - private final NetworkParameters params; + private final BitcoinNetwork bitcoinNetwork; @Inject - public FeePolicy(NetworkParameters params) { - this.params = params; + public FeePolicy(BitcoinNetwork bitcoinNetwork) { + this.bitcoinNetwork = bitcoinNetwork; - if (params.equals(TestNet3Params.get())) { - createOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84"; - takeOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84"; - } - 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"; + switch (bitcoinNetwork) { + case TESTNET: + createOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84"; + takeOfferFeeAddress = "mmm8BdTcHoc5wi75RmiQYsJ2Tr1NoZmM84"; + break; + case MAINNET: + // bitsquare donation address used for the moment... + createOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7"; + takeOfferFeeAddress = "1BVxNn3T12veSK6DgqwU4Hdn7QHcDDRag7"; + break; + case REGTEST: + createOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; + takeOfferFeeAddress = "n2upbsaKAe4PD3cc4JfS7UCqPC5oNd7Ckg"; + break; } } @@ -89,7 +86,7 @@ public class FeePolicy { //TODO get address form arbitrator list public Address getAddressForCreateOfferFee() { try { - return new Address(params, createOfferFeeAddress); + return new Address(bitcoinNetwork.getParameters(), createOfferFeeAddress); } catch (AddressFormatException e) { e.printStackTrace(); return null; @@ -99,7 +96,7 @@ public class FeePolicy { //TODO get address form the intersection of both traders arbitrator lists public Address getAddressForTakeOfferFee() { try { - return new Address(params, takeOfferFeeAddress); + return new Address(bitcoinNetwork.getParameters(), takeOfferFeeAddress); } catch (AddressFormatException e) { e.printStackTrace(); return null; diff --git a/src/main/java/io/bitsquare/btc/WalletService.java b/src/main/java/io/bitsquare/btc/WalletService.java index 3a06f4c907..8f4b4aaa69 100644 --- a/src/main/java/io/bitsquare/btc/WalletService.java +++ b/src/main/java/io/bitsquare/btc/WalletService.java @@ -123,10 +123,10 @@ public class WalletService { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public WalletService(NetworkParameters params, FeePolicy feePolicy, SignatureService signatureService, + public WalletService(BitcoinNetwork bitcoinNetwork, FeePolicy feePolicy, SignatureService signatureService, Persistence persistence, UserAgent userAgent, @Named(DIR_KEY) File walletDir, @Named(PREFIX_KEY) String walletPrefix) { - this.params = params; + this.params = bitcoinNetwork.getParameters(); this.feePolicy = feePolicy; this.signatureService = signatureService; this.persistence = persistence; diff --git a/src/main/java/io/bitsquare/gui/main/preferences/network/NetworkPreferencesViewCB.java b/src/main/java/io/bitsquare/gui/main/preferences/network/NetworkPreferencesViewCB.java index f42808a023..e86dca40ca 100644 --- a/src/main/java/io/bitsquare/gui/main/preferences/network/NetworkPreferencesViewCB.java +++ b/src/main/java/io/bitsquare/gui/main/preferences/network/NetworkPreferencesViewCB.java @@ -17,10 +17,9 @@ package io.bitsquare.gui.main.preferences.network; +import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.network.ClientNode; -import org.bitcoinj.core.NetworkParameters; - import java.net.URL; import java.util.ResourceBundle; @@ -33,20 +32,20 @@ import javafx.scene.control.*; public class NetworkPreferencesViewCB implements Initializable { - private final NetworkParameters networkParameters; + private final String bitcoinNetworkValue; private final ClientNode clientNode; @FXML TextField bitcoinNetwork, connectionType, nodeAddress, bootstrapNodeAddress; @Inject - public NetworkPreferencesViewCB(NetworkParameters networkParameters, ClientNode clientNode) { - this.networkParameters = networkParameters; + public NetworkPreferencesViewCB(BitcoinNetwork bitcoinNetwork, ClientNode clientNode) { + this.bitcoinNetworkValue = bitcoinNetwork.toString(); this.clientNode = clientNode; } @Override public void initialize(URL url, ResourceBundle rb) { - bitcoinNetwork.setText(networkParameters.getId()); + bitcoinNetwork.setText(bitcoinNetworkValue); nodeAddress.setText(clientNode.getAddress().toString()); bootstrapNodeAddress.setText(clientNode.getBootstrapNodeAddress().toString()); connectionType.setText(clientNode.getConnectionType().toString()); diff --git a/src/main/java/io/bitsquare/gui/util/validation/BtcAddressValidator.java b/src/main/java/io/bitsquare/gui/util/validation/BtcAddressValidator.java index 1a232a3e72..2fdd8b6481 100644 --- a/src/main/java/io/bitsquare/gui/util/validation/BtcAddressValidator.java +++ b/src/main/java/io/bitsquare/gui/util/validation/BtcAddressValidator.java @@ -17,9 +17,10 @@ package io.bitsquare.gui.util.validation; +import io.bitsquare.btc.BitcoinNetwork; + import org.bitcoinj.core.Address; import org.bitcoinj.core.AddressFormatException; -import org.bitcoinj.core.NetworkParameters; import javax.inject.Inject; @@ -33,7 +34,8 @@ import org.slf4j.LoggerFactory; */ public final class BtcAddressValidator extends InputValidator { private static final Logger log = LoggerFactory.getLogger(BtcAddressValidator.class); - private final NetworkParameters networkParameters; + + private final BitcoinNetwork bitcoinNetwork; /////////////////////////////////////////////////////////////////////////////////////////// @@ -41,8 +43,8 @@ public final class BtcAddressValidator extends InputValidator { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public BtcAddressValidator(NetworkParameters networkParameters) { - this.networkParameters = networkParameters; + public BtcAddressValidator(BitcoinNetwork bitcoinNetwork) { + this.bitcoinNetwork = bitcoinNetwork; } @@ -67,7 +69,7 @@ public final class BtcAddressValidator extends InputValidator { private ValidationResult validateBtcAddress(String input) { try { - new Address(networkParameters, input); + new Address(bitcoinNetwork.getParameters(), input); return new ValidationResult(true); } catch (AddressFormatException e) { return new ValidationResult(false, "Bitcoin address is a valid format"); diff --git a/src/main/java/io/bitsquare/util/joptsimple/EnumValueConverter.java b/src/main/java/io/bitsquare/util/joptsimple/EnumValueConverter.java new file mode 100644 index 0000000000..f939eafa93 --- /dev/null +++ b/src/main/java/io/bitsquare/util/joptsimple/EnumValueConverter.java @@ -0,0 +1,70 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.util.joptsimple; + +import com.google.common.base.Enums; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; + +import java.util.Set; + +import joptsimple.ValueConverter; + +import static org.springframework.util.StringUtils.collectionToDelimitedString; + +/** + * A {@link joptsimple.ValueConverter} that supports case-insensitive conversion from + * String to an enum label. Useful in conjunction with {@link joptsimple.ArgumentAcceptingOptionSpec#ofType(Class)} + * when the type in question is an enum. + */ +public class EnumValueConverter implements ValueConverter { + + private final Class enumType; + + public EnumValueConverter(Class enumType) { + this.enumType = enumType; + } + + /** + * Attempt to resolve an enum of the specified type by looking for a label with the + * given value, trying all case variations in the process. + * @return the matching enum label (if any) + * @throws IllegalArgumentException if no such label matching the given value is found. + */ + @Override + public Enum convert(String value) { + Set candidates = Sets.newHashSet(value, value.toUpperCase(), value.toLowerCase()); + for (String candidate : candidates) { + Optional result = Enums.getIfPresent(enumType, candidate); + if (result.isPresent()) + return result.get(); + } + throw new IllegalArgumentException(String.format( + "No enum constant %s.[%s]", enumType.getName(), collectionToDelimitedString(candidates, "|"))); + } + + @Override + public Class valueType() { + return enumType; + } + + @Override + public String valuePattern() { + return null; + } +}