diff --git a/common/pom.xml b/common/pom.xml index fd2c7a2261..247371afaf 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/common/src/main/java/io/bitsquare/common/util/Tuple3.java b/common/src/main/java/io/bitsquare/common/util/Tuple3.java index aca55aee37..be08d6aa63 100644 --- a/common/src/main/java/io/bitsquare/common/util/Tuple3.java +++ b/common/src/main/java/io/bitsquare/common/util/Tuple3.java @@ -50,6 +50,4 @@ public class Tuple3 implements Serializable { result = 31 * result + (third != null ? third.hashCode() : 0); return result; } - - } diff --git a/core/pom.xml b/core/pom.xml index 75de5cddb0..3fc718c82d 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -6,7 +6,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 core @@ -52,6 +52,5 @@ 4.8 - diff --git a/core/src/main/java/io/bitsquare/btc/FeePolicy.java b/core/src/main/java/io/bitsquare/btc/FeePolicy.java index c84eeb3a67..7c34a0fb66 100644 --- a/core/src/main/java/io/bitsquare/btc/FeePolicy.java +++ b/core/src/main/java/io/bitsquare/btc/FeePolicy.java @@ -61,7 +61,7 @@ public class FeePolicy { } // Some wallets (Mycelium) don't support higher fees - public static Coin getMinFundingFee() { + public static Coin getMinRequiredFeeForFundingTx() { return Coin.valueOf(20_000); } diff --git a/core/src/main/java/io/bitsquare/btc/blockchain/BlockchainService.java b/core/src/main/java/io/bitsquare/btc/blockchain/BlockchainService.java index 3c335bfaaf..67e8320c20 100644 --- a/core/src/main/java/io/bitsquare/btc/blockchain/BlockchainService.java +++ b/core/src/main/java/io/bitsquare/btc/blockchain/BlockchainService.java @@ -4,10 +4,14 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.SettableFuture; import com.google.inject.Inject; +import io.bitsquare.app.Log; +import io.bitsquare.btc.BitcoinNetwork; +import io.bitsquare.btc.FeePolicy; import io.bitsquare.btc.blockchain.providers.BlockTrailProvider; import io.bitsquare.btc.blockchain.providers.BlockchainApiProvider; import io.bitsquare.btc.blockchain.providers.BlockrIOProvider; import io.bitsquare.btc.blockchain.providers.TradeBlockProvider; +import io.bitsquare.user.Preferences; import org.bitcoinj.core.Coin; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -20,34 +24,47 @@ public class BlockchainService { private static final Logger log = LoggerFactory.getLogger(BlockchainService.class); private final ArrayList providers; + private final boolean isMainNet; @Inject + public BlockchainService(Preferences preferences) { + isMainNet = preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET; + providers = new ArrayList<>(Arrays.asList(new BlockrIOProvider(), new BlockTrailProvider(), new TradeBlockProvider())); + } + public BlockchainService() { + isMainNet = false; providers = new ArrayList<>(Arrays.asList(new BlockrIOProvider(), new BlockTrailProvider(), new TradeBlockProvider())); } public SettableFuture requestFeeFromBlockchain(String transactionId) { - log.debug("Request fee from providers"); + Log.traceCall(transactionId); long startTime = System.currentTimeMillis(); final SettableFuture resultFuture = SettableFuture.create(); - for (BlockchainApiProvider provider : providers) { - GetFeeRequest getFeeRequest = new GetFeeRequest(); - SettableFuture future = getFeeRequest.requestFee(transactionId, provider); - Futures.addCallback(future, new FutureCallback() { - public void onSuccess(Coin fee) { - if (!resultFuture.isDone()) { - log.info("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime)); - resultFuture.set(fee); - } - } - public void onFailure(@NotNull Throwable throwable) { - if (!resultFuture.isDone()) { - log.warn("Could not get the fee from any provider after repeated requests."); - resultFuture.setException(throwable); + if (isMainNet) { + for (BlockchainApiProvider provider : providers) { + GetFeeRequest getFeeRequest = new GetFeeRequest(); + SettableFuture future = getFeeRequest.requestFee(transactionId, provider); + Futures.addCallback(future, new FutureCallback() { + public void onSuccess(Coin fee) { + if (!resultFuture.isDone()) { + log.info("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime)); + resultFuture.set(fee); + } } - } - }); + + public void onFailure(@NotNull Throwable throwable) { + if (!resultFuture.isDone()) { + log.warn("Could not get the fee from any provider after repeated requests."); + resultFuture.setException(throwable); + } + } + }); + } + } else { + // For regtest/testnet we dont care of the check and set the expected value + resultFuture.set(FeePolicy.getMinRequiredFeeForFundingTx()); } return resultFuture; } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java index 55b25e31fb..5b8c32cf08 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/FinalizePayoutTxRequest.java @@ -31,18 +31,18 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb public final byte[] sellerSignature; public final String sellerPayoutAddress; - public final long lockTime; + public final long lockTimeAsBlockHeight; private final NodeAddress senderNodeAddress; public FinalizePayoutTxRequest(String tradeId, byte[] sellerSignature, String sellerPayoutAddress, - long lockTime, + long lockTimeAsBlockHeight, NodeAddress senderNodeAddress) { super(tradeId); this.sellerSignature = sellerSignature; this.sellerPayoutAddress = sellerPayoutAddress; - this.lockTime = lockTime; + this.lockTimeAsBlockHeight = lockTimeAsBlockHeight; this.senderNodeAddress = senderNodeAddress; } @@ -59,7 +59,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb FinalizePayoutTxRequest that = (FinalizePayoutTxRequest) o; - if (lockTime != that.lockTime) return false; + if (lockTimeAsBlockHeight != that.lockTimeAsBlockHeight) return false; if (!Arrays.equals(sellerSignature, that.sellerSignature)) return false; if (sellerPayoutAddress != null ? !sellerPayoutAddress.equals(that.sellerPayoutAddress) : that.sellerPayoutAddress != null) return false; @@ -72,7 +72,7 @@ public final class FinalizePayoutTxRequest extends TradeMessage implements Mailb int result = super.hashCode(); result = 31 * result + (sellerSignature != null ? Arrays.hashCode(sellerSignature) : 0); result = 31 * result + (sellerPayoutAddress != null ? sellerPayoutAddress.hashCode() : 0); - result = 31 * result + (int) (lockTime ^ (lockTime >>> 32)); + result = 31 * result + (int) (lockTimeAsBlockHeight ^ (lockTimeAsBlockHeight >>> 32)); result = 31 * result + (senderNodeAddress != null ? senderNodeAddress.hashCode() : 0); return result; } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/ProcessFinalizePayoutTxRequest.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/ProcessFinalizePayoutTxRequest.java index 260fa8703f..e1ffbdb3b8 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/ProcessFinalizePayoutTxRequest.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/ProcessFinalizePayoutTxRequest.java @@ -45,7 +45,7 @@ public class ProcessFinalizePayoutTxRequest extends TradeTask { processModel.tradingPeer.setSignature(checkNotNull(message.sellerSignature)); processModel.tradingPeer.setPayoutAddressString(nonEmptyStringOf(message.sellerPayoutAddress)); - trade.setLockTimeAsBlockHeight(nonNegativeLongOf(message.lockTime)); + trade.setLockTimeAsBlockHeight(nonNegativeLongOf(message.lockTimeAsBlockHeight)); trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_RECEIVED); diff --git a/core/src/main/java/io/bitsquare/user/Preferences.java b/core/src/main/java/io/bitsquare/user/Preferences.java index 9b256e64f4..269720f1b1 100644 --- a/core/src/main/java/io/bitsquare/user/Preferences.java +++ b/core/src/main/java/io/bitsquare/user/Preferences.java @@ -72,7 +72,7 @@ public class Preferences implements Serializable { private static Locale defaultLocale = Locale.getDefault(); //TODO test with other locales - //private static Locale defaultLocale = Locale.US; + // private static Locale defaultLocale = Locale.US; public static Locale getDefaultLocale() { return defaultLocale; @@ -416,5 +416,4 @@ public class Preferences implements Serializable { public boolean getUseTorForBitcoinJ() { return useTorForBitcoinJ; } - } diff --git a/gui/pom.xml b/gui/pom.xml index 5504ac17a3..ddef5cf526 100644 --- a/gui/pom.xml +++ b/gui/pom.xml @@ -22,7 +22,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index e39cf050cd..659614d9cd 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -56,6 +56,7 @@ import javafx.scene.layout.StackPane; import javafx.stage.Modality; import javafx.stage.Stage; import javafx.stage.StageStyle; +import org.bitcoinj.store.BlockStoreException; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.controlsfx.dialog.Dialogs; import org.reactfx.EventStreams; @@ -108,10 +109,15 @@ public class BitsquareApp extends Application { // setup UncaughtExceptionHandler Thread.UncaughtExceptionHandler handler = (thread, throwable) -> { // Might come from another thread - log.error("Uncaught Exception from thread " + Thread.currentThread().getName()); - log.error("Uncaught Exception throwableMessage= " + throwable.getMessage()); - throwable.printStackTrace(); - UserThread.execute(() -> showErrorPopup(throwable, false)); + if (throwable.getCause() != null && throwable.getCause().getCause() != null && + throwable.getCause().getCause() instanceof BlockStoreException) { + log.error(throwable.getMessage()); + } else { + log.error("Uncaught Exception from thread " + Thread.currentThread().getName()); + log.error("Uncaught Exception throwableMessage= " + throwable.getMessage()); + throwable.printStackTrace(); + UserThread.execute(() -> showErrorPopup(throwable, false)); + } }; Thread.setDefaultUncaughtExceptionHandler(handler); Thread.currentThread().setUncaughtExceptionHandler(handler); @@ -135,7 +141,7 @@ public class BitsquareApp extends Application { if (mainView != null) mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles); }); - + // load the main view and create the main scene CachingViewLoader viewLoader = injector.getInstance(CachingViewLoader.class); mainView = (MainView) viewLoader.load(MainView.class); diff --git a/gui/src/main/java/io/bitsquare/gui/components/TitledGroupBg.java b/gui/src/main/java/io/bitsquare/gui/components/TitledGroupBg.java index b98316dcd3..57e07d0673 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/TitledGroupBg.java +++ b/gui/src/main/java/io/bitsquare/gui/components/TitledGroupBg.java @@ -26,7 +26,6 @@ import javafx.scene.layout.Pane; public class TitledGroupBg extends Pane { - private final Label label; private final StringProperty text = new SimpleStringProperty(); 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 21a2c9849a..b64ccc32ec 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -637,7 +637,10 @@ public class MainViewModel implements ViewModel { if (error instanceof TimeoutException) { walletServiceErrorMsg.set("Connecting to the bitcoin network failed because of a timeout."); } else if (error.getCause() instanceof BlockStoreException) { - walletServiceErrorMsg.set("Bitsquare is already running. You cannot run 2 instances of Bitsquare."); + new Popup().warning("Bitsquare is already running. You cannot run 2 instances of Bitsquare.") + .closeButtonText("Shut down") + .onClose(BitsquareApp.shutDownHandler::run) + .show(); } else if (error.getMessage() != null) { walletServiceErrorMsg.set("Connection to the bitcoin network failed because of an error:" + error.getMessage()); } else { diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.fxml b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.fxml index 2c32179467..fb75a67b18 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.fxml @@ -29,7 +29,7 @@ - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml index 5cae4d66eb..f198e78543 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.fxml @@ -28,12 +28,12 @@ - + - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.fxml b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.fxml index 12ec49bae3..223a801c60 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.fxml @@ -30,7 +30,7 @@ - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java index 7b1e67057a..0111807813 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java @@ -191,9 +191,9 @@ public class WithdrawalView extends ActivatableView { new Popup().headLine("Confirm your withdrawal request") .message("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" + "From address: " + withdrawFromTextField.getText() + "\n" + - "To receiving address: " + withdrawToTextField.getText() + ".\n\n" + - "Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n" + - "Recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" + + "To receiving address: " + withdrawToTextField.getText() + ".\n" + + "Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" + + "The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" + "Are you sure you want to withdraw that amount?") .onAction(() -> doWithdraw(receiverAmount, callback)) .show(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java index 9afc4b5149..a559bbb4aa 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java @@ -103,6 +103,7 @@ class CreateOfferDataModel extends ActivatableDataModel { final ObservableList paymentAccounts = FXCollections.observableArrayList(); private PaymentAccount paymentAccount; + private WalletEventListener walletEventListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -138,42 +139,7 @@ class CreateOfferDataModel extends ActivatableDataModel { }; paymentAccountsChangeListener = change -> paymentAccounts.setAll(user.getPaymentAccounts()); - } - - - @Override - protected void activate() { - addBindings(); - addListeners(); - - paymentAccounts.setAll(user.getPaymentAccounts()); - updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress())); - - if (direction == Offer.Direction.BUY) - calculateTotalToPay(); - } - - @Override - protected void deactivate() { - removeBindings(); - removeListeners(); - } - - private void addBindings() { - btcCode.bind(preferences.btcDenominationProperty()); - } - - private void removeBindings() { - btcCode.unbind(); - } - - boolean isFeeFromFundingTxSufficient() { - return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinFundingFee()) >= 0; - } - - private void addListeners() { - walletService.addBalanceListener(balanceListener); - walletService.getWallet().addEventListener(new WalletEventListener() { + walletEventListener = new WalletEventListener() { @Override public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { requestFeeFromBlockchain(tx.getHashAsString()); @@ -202,28 +168,45 @@ class CreateOfferDataModel extends ActivatableDataModel { @Override public void onKeysAdded(List keys) { } - }); - user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener); + }; } - private void requestFeeFromBlockchain(String transactionId) { - SettableFuture future = blockchainService.requestFeeFromBlockchain(transactionId); - Futures.addCallback(future, new FutureCallback() { - public void onSuccess(Coin fee) { - UserThread.execute(() -> feeFromFundingTxProperty.set(fee)); - } + @Override + protected void activate() { + addBindings(); + addListeners(); - public void onFailure(@NotNull Throwable throwable) { - UserThread.execute(() -> new Popup() - .warning("We did not get a result for the mining fee used in the funding transaction.") - .show()); - } - }); + paymentAccounts.setAll(user.getPaymentAccounts()); + updateBalance(walletService.getBalanceForAddress(getAddressEntry().getAddress())); + + if (direction == Offer.Direction.BUY) + calculateTotalToPay(); + } + + @Override + protected void deactivate() { + removeBindings(); + removeListeners(); + } + + private void addBindings() { + btcCode.bind(preferences.btcDenominationProperty()); + } + + private void removeBindings() { + btcCode.unbind(); + } + + private void addListeners() { + walletService.addBalanceListener(balanceListener); + walletService.getWallet().addEventListener(walletEventListener); + user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener); } private void removeListeners() { walletService.removeBalanceListener(balanceListener); + walletService.getWallet().removeEventListener(walletEventListener); user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener); } @@ -343,10 +326,30 @@ class CreateOfferDataModel extends ActivatableDataModel { return user.getAcceptedArbitrators().size() > 0; } + boolean isFeeFromFundingTxSufficient() { + return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0; + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Utils /////////////////////////////////////////////////////////////////////////////////////////// + private void requestFeeFromBlockchain(String transactionId) { + SettableFuture future = blockchainService.requestFeeFromBlockchain(transactionId); + Futures.addCallback(future, new FutureCallback() { + public void onSuccess(Coin fee) { + UserThread.execute(() -> feeFromFundingTxProperty.set(fee)); + } + + public void onFailure(@NotNull Throwable throwable) { + UserThread.execute(() -> new Popup() + .warning("We did not get a response for the request of the mining fee used in the funding transaction.") + .show()); + } + }); + } + void calculateVolume() { if (priceAsFiat.get() != null && amountAsCoin.get() != null && diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java index aaa4ddf14c..cab467c0bd 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java @@ -241,7 +241,7 @@ public class CreateOfferView extends ActivatableViewAndModel parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/jtorctl/pom.xml b/jtorctl/pom.xml index ede1b12cae..61f9b2269f 100644 --- a/jtorctl/pom.xml +++ b/jtorctl/pom.xml @@ -5,7 +5,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/jtorproxy/pom.xml b/jtorproxy/pom.xml index 8f32aab4e8..787b9a3117 100644 --- a/jtorproxy/pom.xml +++ b/jtorproxy/pom.xml @@ -5,7 +5,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/jtorproxy/src/main/java/io/nucleo/net/TorNode.java b/jtorproxy/src/main/java/io/nucleo/net/TorNode.java index ebe5e55397..9ab8688df5 100644 --- a/jtorproxy/src/main/java/io/nucleo/net/TorNode.java +++ b/jtorproxy/src/main/java/io/nucleo/net/TorNode.java @@ -23,11 +23,6 @@ public abstract class TorNode parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0 diff --git a/network/src/main/java/io/bitsquare/p2p/seed/SeedNodesRepository.java b/network/src/main/java/io/bitsquare/p2p/seed/SeedNodesRepository.java index 601fe93954..bde06df46b 100644 --- a/network/src/main/java/io/bitsquare/p2p/seed/SeedNodesRepository.java +++ b/network/src/main/java/io/bitsquare/p2p/seed/SeedNodesRepository.java @@ -16,11 +16,12 @@ public class SeedNodesRepository { // regtest use port 8002 private Set torSeedNodeAddresses = Sets.newHashSet( // mainnet - // 0.3.3 + // v0.3.3 /* new NodeAddress("oyyii5ogv7y7iadi.onion:8000"), new NodeAddress("ugcro2f5xnkguash.onion:8000"), new NodeAddress("qarhpdsl6mfhbnud.onion:8000"),*/ + // v0.3.4 new NodeAddress("lih5zsr2bvxi24pk.onion:8000"), new NodeAddress("s5xpstlooosehtxm.onion:8000"), new NodeAddress("izs5oz7i5ta7c2ir.onion:8000"), diff --git a/pom.xml b/pom.xml index 3a686e2f4a..e8f68a196c 100755 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.bitsquare parent pom - 0.3.4-SNAPSHOT + 0.3.4 Bitsquare - The decentralized bitcoin exchange https://bitsquare.io diff --git a/seednode/pom.xml b/seednode/pom.xml index ea3beb2914..8460623522 100644 --- a/seednode/pom.xml +++ b/seednode/pom.xml @@ -5,7 +5,7 @@ parent io.bitsquare - 0.3.4-SNAPSHOT + 0.3.4 4.0.0