diff --git a/core/src/main/java/io/bitsquare/user/PopupId.java b/core/src/main/java/io/bitsquare/user/PopupId.java index 47cce412b4..eda792c6e4 100644 --- a/core/src/main/java/io/bitsquare/user/PopupId.java +++ b/core/src/main/java/io/bitsquare/user/PopupId.java @@ -21,7 +21,9 @@ public class PopupId { // We don't use an enum because it would break updates if we add a new item in a new version - public static String SEC_DEPOSIT = "SEC_DEPOSIT"; - public static String TRADE_WALLET = "TRADE_WALLET"; + public static String TRADE_WALLET = "tradeWallet"; + public static String SEND_PAYMENT_INFO = "sendPaymentInfo"; + public static String PAYMENT_SENT = "paymentSent"; + public static String PAYMENT_RECEIVED = "paymentReceived"; } diff --git a/core/src/main/java/io/bitsquare/user/Preferences.java b/core/src/main/java/io/bitsquare/user/Preferences.java index a7e72797a0..7f8ffd48ee 100644 --- a/core/src/main/java/io/bitsquare/user/Preferences.java +++ b/core/src/main/java/io/bitsquare/user/Preferences.java @@ -143,8 +143,10 @@ public class Preferences implements Serializable { showTakeOfferConfirmation = true; showAgainMap = new HashMap<>(); - showAgainMap.put(PopupId.SEC_DEPOSIT, true); showAgainMap.put(PopupId.TRADE_WALLET, true); + showAgainMap.put(PopupId.SEND_PAYMENT_INFO, true); + showAgainMap.put(PopupId.PAYMENT_SENT, true); + showAgainMap.put(PopupId.PAYMENT_RECEIVED, true); storage.queueUpForSave(); } @@ -345,6 +347,10 @@ public class Preferences implements Serializable { return showAgainMap; } + public boolean showAgain(String key) { + return getShowAgainMap().containsKey(key) && getShowAgainMap().get(key); + } + public boolean getTacAccepted() { return tacAccepted; } diff --git a/core/src/main/java/io/bitsquare/user/User.java b/core/src/main/java/io/bitsquare/user/User.java index 9197c6fbb5..3b422f1ed6 100644 --- a/core/src/main/java/io/bitsquare/user/User.java +++ b/core/src/main/java/io/bitsquare/user/User.java @@ -269,7 +269,11 @@ public class User implements Serializable { }*/ public Arbitrator getAcceptedArbitratorByAddress(Address address) { - return acceptedArbitrators.stream().filter(e -> e.getArbitratorAddress().equals(address)).findFirst().get(); + Optional arbitratorOptional = acceptedArbitrators.stream().filter(e -> e.getArbitratorAddress().equals(address)).findFirst(); + if (arbitratorOptional.isPresent()) + return arbitratorOptional.get(); + else + return null; } diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 9bf84106e3..47efdd9b40 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -73,7 +73,7 @@ import static io.bitsquare.app.BitsquareEnvironment.APP_NAME_KEY; public class BitsquareApp extends Application { private static final Logger log = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(BitsquareApp.class); - public static final boolean DEV_MODE = true; + public static final boolean DEV_MODE = false; private static Environment env; diff --git a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/OKPayForm.java b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/OKPayForm.java index d235a41953..05575510c7 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/OKPayForm.java +++ b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/OKPayForm.java @@ -31,6 +31,7 @@ import javafx.geometry.Insets; import javafx.geometry.VPos; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; import javafx.scene.layout.FlowPane; import javafx.scene.layout.GridPane; import org.slf4j.Logger; @@ -94,6 +95,7 @@ public class OKPayForm extends PaymentMethodForm { checkBox.setSelected(okPayAccount.getTradeCurrencies().contains(e)); checkBox.setMinWidth(60); checkBox.setMaxWidth(checkBox.getMinWidth()); + checkBox.setTooltip(new Tooltip(e.getName())); checkBox.setOnAction(event -> { if (checkBox.isSelected()) okPayAccount.addCurrency(e); diff --git a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/SepaForm.java b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/SepaForm.java index 55f4939e81..14f0d59017 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/SepaForm.java +++ b/gui/src/main/java/io/bitsquare/gui/components/paymentmethods/SepaForm.java @@ -34,6 +34,7 @@ import javafx.geometry.VPos; import javafx.scene.control.*; import javafx.scene.layout.FlowPane; import javafx.scene.layout.GridPane; +import javafx.scene.text.TextAlignment; import javafx.util.StringConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -98,9 +99,9 @@ public class SepaForm extends PaymentMethodForm { }); - Tuple2 tuple2 = addLabelComboBox(gridPane, ++gridRow, "Country of Bank:"); + Tuple2 tuple2 = addLabelComboBox(gridPane, ++gridRow, "Country of your Bank:"); ComboBox countryComboBox = tuple2.second; - countryComboBox.setPromptText("Select country of Bank"); + countryComboBox.setPromptText("Select country of your Bank"); countryComboBox.setConverter(new StringConverter() { @Override public String toString(Country country) { @@ -141,15 +142,18 @@ public class SepaForm extends PaymentMethodForm { } private void addEuroCountriesGrid(boolean isEditable) { - addCountriesGrid(isEditable, "Accept taker countries (Euro):", euroCountryCheckBoxes, CountryUtil.getAllSepaEuroCountries()); + addCountriesGrid(isEditable, "Accept trades from those Euro countries:", euroCountryCheckBoxes, CountryUtil.getAllSepaEuroCountries()); } private void addNonEuroCountriesGrid(boolean isEditable) { - addCountriesGrid(isEditable, "Accepted taker countries (non-Euro):", nonEuroCountryCheckBoxes, CountryUtil.getAllSepaNonEuroCountries()); + addCountriesGrid(isEditable, "Accept trades from those non-Euro countries:", nonEuroCountryCheckBoxes, CountryUtil.getAllSepaNonEuroCountries()); } private void addCountriesGrid(boolean isEditable, String title, List checkBoxList, List dataProvider) { Label label = addLabel(gridPane, ++gridRow, title, 0); + label.setWrapText(true); + label.setPrefWidth(200); + label.setTextAlignment(TextAlignment.RIGHT); GridPane.setValignment(label, VPos.TOP); FlowPane flowPane = new FlowPane(); flowPane.setPadding(new Insets(10, 10, 10, 10)); @@ -169,7 +173,6 @@ public class SepaForm extends PaymentMethodForm { checkBoxList.add(checkBox); checkBox.setMouseTransparent(!isEditable); checkBox.setMinWidth(45); - checkBox.setMaxWidth(checkBox.getMinWidth()); checkBox.setTooltip(new Tooltip(country.name)); checkBox.setOnAction(event -> { if (checkBox.isSelected()) 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 306c927557..70e6baadba 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -338,7 +338,7 @@ class MainViewModel implements ViewModel { // tac if (!preferences.getTacAccepted() && !BitsquareApp.DEV_MODE) - new TacPopup().url(WebViewPopup.getLocalUrl("tac.html")).onAgree(() -> preferences.setTacAccepted(true)).show(); + new TacPopup().url(WebViewPopup.getLocalUrl("tac")).onAgree(() -> preferences.setTacAccepted(true)).show(); // update nr of peers in footer diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java index 4cbf14f7d5..58a2a9b5d2 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java @@ -196,8 +196,8 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel model.setAutoSelectArbitrators(autoSelectAllMatchingCheckBox.isSelected())); - Button reloadButton = addButton(root, gridRow, "Reload"); - GridPane.setColumnIndex(reloadButton, 1); - GridPane.setHalignment(reloadButton, HPos.RIGHT); - GridPane.setMargin(reloadButton, new Insets(0, -10, 0, -10)); - reloadButton.setOnAction(event -> model.reload()); - TableColumn dateColumn = new TableColumn("Registration date"); dateColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper(param.getValue().getRegistrationDate())); dateColumn.setMinWidth(130); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java index 1a8ee09f96..2b5fa4062d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionViewModel.java @@ -130,10 +130,6 @@ class ArbitratorSelectionViewModel extends ActivatableDataModel { return user.isMyOwnRegisteredArbitrator(arbitrator); } - public void reload() { - arbitratorManager.applyArbitrators(); - } - private void updateAutoSelectArbitrators() { if (preferences.getAutoSelectArbitrators()) { arbitratorListItems.stream().forEach(item -> { diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java index 7948fd03aa..647c5491b0 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/FundsView.java @@ -25,7 +25,7 @@ import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.funds.reserved.ReservedView; import io.bitsquare.gui.main.funds.transactions.TransactionsView; import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView; -import io.bitsquare.gui.popups.FirstTimePopup; +import io.bitsquare.gui.popups.FirstTimeWebViewPopup; import io.bitsquare.gui.popups.WebViewPopup; import io.bitsquare.user.PopupId; import io.bitsquare.user.Preferences; @@ -85,8 +85,9 @@ public class FundsView extends ActivatableViewAndModel { else if (root.getSelectionModel().getSelectedItem() == transactionsTab) navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class); - if (preferences.getShowAgainMap().get(PopupId.TRADE_WALLET) && !BitsquareApp.DEV_MODE) - new FirstTimePopup(preferences).url(WebViewPopup.getLocalUrl("tradeWallet.html")).show(); + String key = PopupId.TRADE_WALLET; + if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) + new FirstTimeWebViewPopup(preferences).id(key).url(WebViewPopup.getLocalUrl(key)).show(); } @Override diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java index c63cdccf58..63c39f52cc 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java @@ -21,19 +21,14 @@ import io.bitsquare.btc.WalletService; import io.bitsquare.btc.listeners.AddressConfidenceListener; import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator; import io.bitsquare.gui.util.BSFormatter; - -import org.bitcoinj.core.Address; -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.Transaction; -import org.bitcoinj.core.TransactionConfidence; -import org.bitcoinj.core.TransactionOutput; - import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.scene.control.*; +import javafx.scene.control.Tooltip; +import org.bitcoinj.core.*; public class TransactionsListItem { + private final StringProperty date = new SimpleStringProperty(); private final StringProperty amount = new SimpleStringProperty(); private final StringProperty type = new SimpleStringProperty(); @@ -44,6 +39,7 @@ public class TransactionsListItem { private final Tooltip tooltip; private String addressString; + private boolean notAnAddress; private AddressConfidenceListener confidenceListener; public TransactionsListItem(Transaction transaction, WalletService walletService, BSFormatter formatter) { @@ -64,14 +60,13 @@ public class TransactionsListItem { address = transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams()); addressString = address.toString(); - } - else { + } else { addressString = "No sent to address script used."; + notAnAddress = true; } } } - } - else if (valueSentFromMe.isZero()) { + } else if (valueSentFromMe.isZero()) { amount.set(formatter.formatCoin(valueSentToMe)); type.set("Received with"); @@ -82,14 +77,13 @@ public class TransactionsListItem { address = transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams()); addressString = address.toString(); - } - else { + } else { addressString = "No sent to address script used."; + notAnAddress = true; } } } - } - else { + } else { amount.set(formatter.formatCoin(valueSentToMe.subtract(valueSentFromMe))); boolean outgoing = false; for (TransactionOutput transactionOutput : transaction.getOutputs()) { @@ -100,19 +94,19 @@ public class TransactionsListItem { address = transactionOutput.getScriptPubKey().getToAddress(walletService.getWallet().getParams ()); addressString = address.toString(); - } - else { + } else { addressString = "No sent to address script used."; + notAnAddress = true; } } } if (outgoing) { type.set("Sent to"); - } - else { + } else { type.set("Internal (TX Fee)"); addressString = "Internal swap between addresses."; + notAnAddress = true; } } @@ -194,5 +188,9 @@ public class TransactionsListItem { public String getAddressString() { return addressString; } + + public boolean isNotAnAddress() { + return notAnAddress; + } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java index d359cc4f0c..c08b217793 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsView.java @@ -40,8 +40,10 @@ import java.util.stream.Collectors; @FxmlView public class TransactionsView extends ActivatableView { - @FXML TableView table; - @FXML TableColumn dateColumn, addressColumn, amountColumn, typeColumn, + @FXML + TableView table; + @FXML + TableColumn dateColumn, addressColumn, amountColumn, typeColumn, confidenceColumn; private ObservableList transactionsListItems; @@ -85,12 +87,14 @@ public class TransactionsView extends ActivatableView { // TODO Open popup with details view log.debug("openTxDetails " + item); - try { - Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString()); - } catch (Exception e) { - log.error(e.getMessage()); - new Popup().warning("Opening browser failed. Please check your internet " + - "connection.").show(); + if (!item.isNotAnAddress()) { + try { + Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString()); + } catch (Exception e) { + log.error(e.getMessage()); + new Popup().warning("Opening browser failed. Please check your internet " + + "connection.").show(); + } } } @@ -114,8 +118,7 @@ public class TransactionsView extends ActivatableView { hyperlink = new Hyperlink(item.getAddressString()); hyperlink.setOnAction(event -> openTxDetails(item)); setGraphic(hyperlink); - } - else { + } else { setGraphic(null); setId(null); } @@ -143,8 +146,7 @@ public class TransactionsView extends ActivatableView { if (item != null && !empty) { setGraphic(item.getProgressIndicator()); - } - else { + } else { setGraphic(null); } } 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 481481dda4..e291b05bf4 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 @@ -203,7 +203,7 @@ public class WithdrawalView extends ActivatableView { formatter.formatCoinWithCode(FeePolicy.TX_FEE) + "\n" + "Receivers amount: " + formatter.formatCoinWithCode(amount.subtract(FeePolicy.TX_FEE)) + " BTC\n\n" + - "Are you sure you withdraw that amount?") + "Are you sure you want to withdraw that amount?") .onAction(() -> { doWithdraw(amount, callback); }) diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/BuyerSubView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/BuyerSubView.java index da3928bbf7..ad07e654b1 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/BuyerSubView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/BuyerSubView.java @@ -56,8 +56,8 @@ public class BuyerSubView extends TradeSubView { @Override protected void addWizards() { waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation"); - startPayment = new TradeWizardItem(StartPaymentView.class, "Start EUR payment"); - waitPaymentReceived = new TradeWizardItem(WaitPaymentReceivedView.class, "Wait until EUR payment arrived"); + startPayment = new TradeWizardItem(StartPaymentView.class, "Start payment"); + waitPaymentReceived = new TradeWizardItem(WaitPaymentReceivedView.class, "Wait until payment arrived"); waitPayoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock"); completed = new TradeWizardItem(CompletedView.class, "Completed"); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java index 09c7cf6133..3dca2cfa92 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -36,6 +36,7 @@ import io.bitsquare.gui.popups.WalletPasswordPopup; import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.trade.*; import io.bitsquare.trade.offer.Offer; +import io.bitsquare.user.Preferences; import io.bitsquare.user.User; import javafx.beans.property.*; import javafx.collections.FXCollections; @@ -69,6 +70,7 @@ public class PendingTradesDataModel extends ActivatableDataModel { private final ObjectProperty tradeProperty = new SimpleObjectProperty<>(); private final StringProperty txId = new SimpleStringProperty(); private Trade trade; + private Preferences preferences; /////////////////////////////////////////////////////////////////////////////////////////// @@ -77,7 +79,7 @@ public class PendingTradesDataModel extends ActivatableDataModel { @Inject public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, TradeWalletService tradeWalletService, - User user, KeyRing keyRing, DisputeManager disputeManager, + User user, KeyRing keyRing, DisputeManager disputeManager, Preferences preferences, Navigation navigation, WalletPasswordPopup walletPasswordPopup) { this.tradeManager = tradeManager; this.walletService = walletService; @@ -85,6 +87,7 @@ public class PendingTradesDataModel extends ActivatableDataModel { this.user = user; this.keyRing = keyRing; this.disputeManager = disputeManager; + this.preferences = preferences; this.navigation = navigation; this.walletPasswordPopup = walletPasswordPopup; @@ -323,6 +326,10 @@ public class PendingTradesDataModel extends ActivatableDataModel { return disputeManager; } + public Preferences getPreferences() { + return preferences; + } + /////////////////////////////////////////////////////////////////////////////////////////// // Utils diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/SellerSubView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/SellerSubView.java index ace4eb35ea..e2986996d4 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/SellerSubView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/SellerSubView.java @@ -56,8 +56,8 @@ public class SellerSubView extends TradeSubView { @Override protected void addWizards() { waitTxInBlockchain = new TradeWizardItem(WaitTxInBlockchainView.class, "Wait for blockchain confirmation"); - waitPaymentStarted = new TradeWizardItem(WaitPaymentStartedView.class, "Wait until EUR payment has started"); - confirmPaymentReceived = new TradeWizardItem(ConfirmPaymentReceivedView.class, "Confirm EUR payment received"); + waitPaymentStarted = new TradeWizardItem(WaitPaymentStartedView.class, "Wait until payment has started"); + confirmPaymentReceived = new TradeWizardItem(ConfirmPaymentReceivedView.class, "Confirm payment received"); waitPayoutUnlock = new TradeWizardItem(WaitPayoutLockTimeView.class, "Wait for payout unlock"); completed = new TradeWizardItem(CompletedView.class, "Completed"); @@ -110,11 +110,11 @@ public class SellerSubView extends TradeSubView { showItem(confirmPaymentReceived); if (model.isBlockChainMethod()) { - ((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment." + + ((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment. " + "Check your Altcoin wallet or Block explorer and confirm when you have received the payment.", model.getCurrencyCode())); } else { - ((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment." + + ((ConfirmPaymentReceivedView) tradeStepDetailsView).setInfoLabelText(BSResources.get("The Bitcoin buyer has started the {0} payment. " + "Check your payment account and confirm when you have received the payment.", model.getCurrencyCode())); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/ConfirmPaymentReceivedView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/ConfirmPaymentReceivedView.java index fe1e3dd5ad..378b064f3d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/ConfirmPaymentReceivedView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/ConfirmPaymentReceivedView.java @@ -17,10 +17,13 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps; +import io.bitsquare.app.BitsquareApp; import io.bitsquare.gui.components.TxIdTextField; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel; import io.bitsquare.gui.popups.Popup; import io.bitsquare.gui.util.Layout; +import io.bitsquare.user.PopupId; +import io.bitsquare.user.Preferences; import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.geometry.HPos; @@ -105,13 +108,23 @@ public class ConfirmPaymentReceivedView extends TradeStepDetailsView { private void onPaymentReceived(ActionEvent actionEvent) { log.debug("onPaymentReceived"); if (model.isAuthenticated()) { - confirmFiatReceivedButton.setDisable(true); + Preferences preferences = model.dataModel.getPreferences(); + String key = PopupId.PAYMENT_RECEIVED; + if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) { + new Popup().information("Please note that as soon you have confirmed that you have received the " + + "payment the locked Bitcoin will be released.\n" + + "There is no way to reverse a Bitcoin payment. Confirm only if you are sure.") + .onClose(() -> preferences.dontShowAgain(key)) + .show(); + } else { + confirmFiatReceivedButton.setDisable(true); - statusProgressIndicator.setVisible(true); - statusProgressIndicator.setProgress(-1); - statusLabel.setText("Sending message to trading partner..."); + statusProgressIndicator.setVisible(true); + statusProgressIndicator.setProgress(-1); + statusLabel.setText("Sending message to trading partner..."); - model.fiatPaymentReceived(); + model.fiatPaymentReceived(); + } } else { new Popup().warning("You need to wait until your client is authenticated in the network.\n" + "That might take up to about 2 minutes at startup.").show(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/StartPaymentView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/StartPaymentView.java index baa9d558da..c72ded76c6 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/StartPaymentView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/steps/StartPaymentView.java @@ -17,6 +17,7 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps; +import io.bitsquare.app.BitsquareApp; import io.bitsquare.common.util.Tuple3; import io.bitsquare.gui.components.TitledGroupBg; import io.bitsquare.gui.components.TxIdTextField; @@ -26,6 +27,8 @@ import io.bitsquare.gui.popups.Popup; import io.bitsquare.gui.util.Layout; import io.bitsquare.payment.PaymentAccountContractData; import io.bitsquare.payment.PaymentMethod; +import io.bitsquare.user.PopupId; +import io.bitsquare.user.Preferences; import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.geometry.Insets; @@ -37,6 +40,7 @@ import javafx.scene.layout.GridPane; import static io.bitsquare.gui.util.FormBuilder.*; public class StartPaymentView extends TradeStepDetailsView { + private final Preferences preferences; private TxIdTextField txIdTextField; private Button paymentStartedButton; @@ -55,6 +59,7 @@ public class StartPaymentView extends TradeStepDetailsView { public StartPaymentView(PendingTradesViewModel model) { super(model); txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(newValue); + preferences = model.dataModel.getPreferences(); } @Override @@ -63,6 +68,16 @@ public class StartPaymentView extends TradeStepDetailsView { model.getTxId().addListener(txIdChangeListener); txIdTextField.setup(model.getTxId().get()); + + String key = PopupId.SEND_PAYMENT_INFO; + if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) { + new Popup().information("You need to transfer now the agreed amount to your trading partner.\n" + + "Please take care that you use the exact data presented here, including the reference text\n" + + "Please do not click the \"Payment started\" button if you have before you have completed the transfer.\n" + + "Take care that you make the transfer soon to not miss the exceed trading period.") + .onClose(() -> preferences.dontShowAgain(key)) + .show(); + } } @Override @@ -126,13 +141,21 @@ public class StartPaymentView extends TradeStepDetailsView { private void onPaymentStarted(ActionEvent actionEvent) { log.debug("onPaymentStarted"); if (model.isAuthenticated()) { - paymentStartedButton.setDisable(true); + String key = PopupId.PAYMENT_SENT; + if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) { + new Popup().information("You are confirming that you have transferred the payment to your trading partner.\n" + + "Please click the \"Payment started\" button only if you have completed the transfer.") + .onClose(() -> preferences.dontShowAgain(key)) + .show(); + } else { + paymentStartedButton.setDisable(true); - statusProgressIndicator.setVisible(true); - statusProgressIndicator.setProgress(-1); - statusLabel.setText("Sending message to trading partner..."); + statusProgressIndicator.setVisible(true); + statusProgressIndicator.setProgress(-1); + statusLabel.setText("Sending message to trading partner..."); - model.fiatPaymentStarted(); + model.fiatPaymentStarted(); + } } else { new Popup().warning("You need to wait until your client is authenticated in the network.\n" + "That might take up to about 2 minutes at startup.").show(); diff --git a/gui/src/main/java/io/bitsquare/gui/popups/FirstTimePopup.java b/gui/src/main/java/io/bitsquare/gui/popups/FirstTimeWebViewPopup.java similarity index 88% rename from gui/src/main/java/io/bitsquare/gui/popups/FirstTimePopup.java rename to gui/src/main/java/io/bitsquare/gui/popups/FirstTimeWebViewPopup.java index f257779ad0..72650fc1af 100644 --- a/gui/src/main/java/io/bitsquare/gui/popups/FirstTimePopup.java +++ b/gui/src/main/java/io/bitsquare/gui/popups/FirstTimeWebViewPopup.java @@ -29,8 +29,8 @@ import java.util.Optional; import static io.bitsquare.gui.util.FormBuilder.addCheckBox; -public class FirstTimePopup extends WebViewPopup { - private static final Logger log = LoggerFactory.getLogger(FirstTimePopup.class); +public class FirstTimeWebViewPopup extends WebViewPopup { + private static final Logger log = LoggerFactory.getLogger(FirstTimeWebViewPopup.class); private Preferences preferences; private String id; @@ -39,22 +39,22 @@ public class FirstTimePopup extends WebViewPopup { // Public API /////////////////////////////////////////////////////////////////////////////////////////// - public FirstTimePopup(Preferences preferences) { + public FirstTimeWebViewPopup(Preferences preferences) { this.preferences = preferences; } @Override - public FirstTimePopup url(String url) { + public FirstTimeWebViewPopup url(String url) { super.url(url); return this; } - public FirstTimePopup onClose(Runnable closeHandler) { + public FirstTimeWebViewPopup onClose(Runnable closeHandler) { this.closeHandlerOptional = Optional.of(closeHandler); return this; } - public FirstTimePopup id(String id) { + public FirstTimeWebViewPopup id(String id) { this.id = id; return this; } diff --git a/gui/src/main/java/io/bitsquare/gui/popups/OfferDetailsPopup.java b/gui/src/main/java/io/bitsquare/gui/popups/OfferDetailsPopup.java index 76f2febd0b..353621ef22 100644 --- a/gui/src/main/java/io/bitsquare/gui/popups/OfferDetailsPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/popups/OfferDetailsPopup.java @@ -110,7 +110,7 @@ public class OfferDetailsPopup extends Popup { } private void addContent() { - int rows = 9; + int rows = 11; if (offer.getPaymentMethodCountryCode() != null) rows++; if (offer.getOfferFeePaymentTxID() != null) @@ -124,7 +124,8 @@ public class OfferDetailsPopup extends Popup { addLabelTextField(gridPane, rowIndex, "Offer ID:", offer.getId(), Layout.FIRST_ROW_DISTANCE); addLabelTextField(gridPane, ++rowIndex, "Creation date:", formatter.formatDateTime(offer.getDate())); addLabelTextField(gridPane, ++rowIndex, "Offer direction:", Offer.Direction.BUY.name()); - addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode()); + addLabelTextField(gridPane, ++rowIndex, "Currency:", offer.getCurrencyCode()); + addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC"); addLabelTextField(gridPane, ++rowIndex, "Amount:", formatter.formatCoinWithCode(offer.getAmount())); addLabelTextField(gridPane, ++rowIndex, "Min. amount:", formatter.formatCoinWithCode(offer.getMinAmount())); addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(offer.getPaymentMethod().getId())); @@ -192,6 +193,7 @@ public class OfferDetailsPopup extends Popup { }); CheckBox checkBox = addCheckBox(gridPane, ++rowIndex, "Don't show again", 5); + checkBox.setPadding(new Insets(10, 0, 15, 0)); checkBox.setSelected(!preferences.getShowTakeOfferConfirmation()); checkBox.setOnAction(e -> preferences.setShowTakeOfferConfirmation(!checkBox.isSelected())); } else { diff --git a/gui/src/main/java/io/bitsquare/gui/popups/TradeDetailsPopup.java b/gui/src/main/java/io/bitsquare/gui/popups/TradeDetailsPopup.java index 211d32e5ff..80f684cbca 100644 --- a/gui/src/main/java/io/bitsquare/gui/popups/TradeDetailsPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/popups/TradeDetailsPopup.java @@ -30,6 +30,7 @@ import javafx.geometry.Insets; import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; +import javafx.scene.control.Tooltip; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,15 +127,19 @@ public class TradeDetailsPopup extends Popup { addLabelTextField(gridPane, ++rowIndex, "Offer direction:", direction); addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode()); addLabelTextField(gridPane, ++rowIndex, "Trade amount:", formatter.formatCoinWithCode(trade.getTradeAmount())); - addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", formatter.arbitratorAddressToShortAddress(trade.getArbitratorAddress())); + addLabelTextField(gridPane, ++rowIndex, "Selected arbitrator:", trade.getArbitratorAddress().getFullAddress()); if (contract != null) { - if (buyerPaymentAccountContractData != null) - addLabelTextField(gridPane, ++rowIndex, "Buyer payment details:", BSResources.get(buyerPaymentAccountContractData.getPaymentDetails())); - - if (sellerPaymentAccountContractData != null) - addLabelTextField(gridPane, ++rowIndex, "Seller payment details:", BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())); - + if (buyerPaymentAccountContractData != null) { + TextField tf = addLabelTextField(gridPane, ++rowIndex, "Buyer payment details:", BSResources.get(buyerPaymentAccountContractData.getPaymentDetails())).second; + tf.setTooltip(new Tooltip(tf.getText())); + tf.setMouseTransparent(false); + } + if (sellerPaymentAccountContractData != null) { + TextField tf = addLabelTextField(gridPane, ++rowIndex, "Seller payment details:", BSResources.get(sellerPaymentAccountContractData.getPaymentDetails())).second; + tf.setTooltip(new Tooltip(tf.getText())); + tf.setMouseTransparent(false); + } if (buyerPaymentAccountContractData == null && sellerPaymentAccountContractData == null) addLabelTextField(gridPane, ++rowIndex, "Payment method:", BSResources.get(contract.getPaymentMethodName())); } diff --git a/gui/src/main/java/io/bitsquare/gui/popups/WebViewPopup.java b/gui/src/main/java/io/bitsquare/gui/popups/WebViewPopup.java index 58c163f69b..9060df5b53 100644 --- a/gui/src/main/java/io/bitsquare/gui/popups/WebViewPopup.java +++ b/gui/src/main/java/io/bitsquare/gui/popups/WebViewPopup.java @@ -33,7 +33,7 @@ public class WebViewPopup extends Popup { protected String url; public static String getLocalUrl(String htmlFile) { - return WebViewPopup.class.getResource("/html/" + htmlFile).toExternalForm(); + return WebViewPopup.class.getResource("/html/" + htmlFile + ".html").toExternalForm(); } public WebViewPopup() { diff --git a/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java b/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java index 606145ec5c..022f0a6335 100644 --- a/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java +++ b/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java @@ -308,14 +308,9 @@ public class BSFormatter { public String arbitratorAddressesToString(List
addresses) { - //return addresses.stream().map(e -> e.getFullAddress().substring(0, 8)).collect(Collectors.joining(", ")); return addresses.stream().map(e -> e.getFullAddress()).collect(Collectors.joining(", ")); } - public String arbitratorAddressToShortAddress(Address address) { - return address.getFullAddress().substring(0, 8); - } - public String languageCodesToString(List languageLocales) { return languageLocales.stream().map(LanguageUtil::getDisplayName).collect(Collectors.joining(", ")); } diff --git a/gui/src/main/resources/html/base.css b/gui/src/main/resources/html/base.css index 25d7fbadf6..622231d36d 100644 --- a/gui/src/main/resources/html/base.css +++ b/gui/src/main/resources/html/base.css @@ -18,7 +18,8 @@ body { font-family: sans-serif; color: #333; - font-size: 13px; + font-size: 14px; + line-height: 2; } a { diff --git a/gui/src/main/resources/i18n/displayStrings.properties b/gui/src/main/resources/i18n/displayStrings.properties index 7e07b5daaf..80ca8475ab 100644 --- a/gui/src/main/resources/i18n/displayStrings.properties +++ b/gui/src/main/resources/i18n/displayStrings.properties @@ -75,7 +75,7 @@ createOffer.advancedBox.currency=Currency: 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.headline=Your offer has been published to the offerbook. createOffer.success.info=In the portfolio screen you can manage your open offers. createOffer.error.message=An error occurred when placing the offer.\n\n{0} diff --git a/network/src/main/java/io/bitsquare/p2p/P2PService.java b/network/src/main/java/io/bitsquare/p2p/P2PService.java index 7535ef3221..204c8c5a8e 100644 --- a/network/src/main/java/io/bitsquare/p2p/P2PService.java +++ b/network/src/main/java/io/bitsquare/p2p/P2PService.java @@ -80,7 +80,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis private MonadicBinding readyForAuthentication; private final Storage
dbStorage; private Address myOnionAddress; - + /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -186,7 +186,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis // We set connectionType to that connection to avoid that is get closed when // we get too many connection attempts. // That is used as protection against eclipse attacks. - connection.setConnectionType(ConnectionType.DIRECT_MSG); + connection.setConnectionType(ConnectionMode.DIRECT_MSG); log.info("Received SealedAndSignedMessage and decrypted it: " + decryptedMsgWithPubKey); decryptedMailListeners.stream().forEach( @@ -305,7 +305,8 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis Log.traceCall(); checkArgument(networkNode.getAddress() != null, "Address must be set when we have the hidden service ready"); if (myOnionAddress != null) - checkArgument(networkNode.getAddress() == myOnionAddress, "networkNode.getAddress() must be same as myOnionAddress"); + checkArgument(networkNode.getAddress().equals(myOnionAddress), + "networkNode.getAddress() must be same as myOnionAddress."); myOnionAddress = networkNode.getAddress(); dbStorage.queueUpForSave(myOnionAddress); @@ -709,7 +710,7 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis return blurredAddressHash != null && Arrays.equals(blurredAddressHash, sealedAndSignedMessage.addressPrefixHash); } else { - log.warn("myOnionAddress must not be null at verifyAddressPrefixHash"); + log.debug("myOnionAddress is null at verifyAddressPrefixHash. That is expected at startup."); return false; } } diff --git a/network/src/main/java/io/bitsquare/p2p/network/Connection.java b/network/src/main/java/io/bitsquare/p2p/network/Connection.java index 0883e834b2..4bf0b6527f 100644 --- a/network/src/main/java/io/bitsquare/p2p/network/Connection.java +++ b/network/src/main/java/io/bitsquare/p2p/network/Connection.java @@ -31,7 +31,7 @@ public class Connection implements MessageListener { private static final Logger log = LoggerFactory.getLogger(Connection.class); private static final int MAX_MSG_SIZE = 5 * 1024 * 1024; // 5 MB of compressed data private static final int SOCKET_TIMEOUT = 30 * 60 * 1000; // 30 min. - private ConnectionType connectionType; + private ConnectionMode connectionType; public static int getMaxMsgSize() { return MAX_MSG_SIZE; @@ -123,7 +123,7 @@ public class Connection implements MessageListener { connectionListener.onPeerAddressAuthenticated(peerAddress, connection); } - public void setConnectionType(ConnectionType connectionType) { + public void setConnectionType(ConnectionMode connectionType) { this.connectionType = connectionType; } @@ -210,7 +210,7 @@ public class Connection implements MessageListener { return stopped; } - public ConnectionType getConnectionType() { + public ConnectionMode getConnectionType() { return connectionType; } diff --git a/network/src/main/java/io/bitsquare/p2p/network/ConnectionMode.java b/network/src/main/java/io/bitsquare/p2p/network/ConnectionMode.java new file mode 100644 index 0000000000..702cd413fe --- /dev/null +++ b/network/src/main/java/io/bitsquare/p2p/network/ConnectionMode.java @@ -0,0 +1,8 @@ +package io.bitsquare.p2p.network; + +public enum ConnectionMode { + PASSIVE, // for connections initiated by other peer + ACTIVE, // for connections initiated by us + DIRECT_MSG, // for connections used for direct messaging + AUTH_REQUEST // for connections used for starting the authentication +} diff --git a/network/src/main/java/io/bitsquare/p2p/peers/AuthenticationHandshake.java b/network/src/main/java/io/bitsquare/p2p/peers/AuthenticationHandshake.java index e6ea23f897..e4cce6b0e0 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/AuthenticationHandshake.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/AuthenticationHandshake.java @@ -8,7 +8,7 @@ import io.bitsquare.common.UserThread; import io.bitsquare.p2p.Address; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.network.Connection; -import io.bitsquare.p2p.network.ConnectionType; +import io.bitsquare.p2p.network.ConnectionMode; import io.bitsquare.p2p.network.MessageListener; import io.bitsquare.p2p.network.NetworkNode; import io.bitsquare.p2p.peers.messages.auth.*; @@ -72,7 +72,7 @@ public class AuthenticationHandshake implements MessageListener { // We use the active connectionType if we started the authentication request to another peer // That is used for protecting eclipse attacks - connection.setConnectionType(ConnectionType.ACTIVE); + connection.setConnectionType(ConnectionMode.ACTIVE); AuthenticationResponse authenticationResponse = (AuthenticationResponse) message; Address peerAddress = authenticationResponse.address; @@ -180,7 +180,7 @@ public class AuthenticationHandshake implements MessageListener { log.trace("send AuthenticationRequest to " + peerAddress + " succeeded."); connection.setPeerAddress(peerAddress); // We protect that connection from getting closed by maintenance cleanup... - connection.setConnectionType(ConnectionType.AUTH_REQUEST); + connection.setConnectionType(ConnectionMode.AUTH_REQUEST); } @Override @@ -228,7 +228,7 @@ public class AuthenticationHandshake implements MessageListener { connection.setPeerAddress(peerAddress); // We use passive connectionType for connections created from received authentication requests from other peers // That is used for protecting eclipse attacks - connection.setConnectionType(ConnectionType.PASSIVE); + connection.setConnectionType(ConnectionMode.PASSIVE); } @Override diff --git a/network/src/main/java/io/bitsquare/p2p/peers/PeerGroup.java b/network/src/main/java/io/bitsquare/p2p/peers/PeerGroup.java index ca62f5afbb..3176f10c7b 100644 --- a/network/src/main/java/io/bitsquare/p2p/peers/PeerGroup.java +++ b/network/src/main/java/io/bitsquare/p2p/peers/PeerGroup.java @@ -168,7 +168,7 @@ public class PeerGroup implements MessageListener, ConnectionListener { Address peerAddress = message.address; if (!authenticationHandshakes.containsKey(peerAddress)) { // We protect that connection from getting closed by maintenance cleanup... - connection.setConnectionType(ConnectionType.AUTH_REQUEST); + connection.setConnectionType(ConnectionMode.AUTH_REQUEST); AuthenticationHandshake authenticationHandshake = new AuthenticationHandshake(networkNode, PeerGroup.this, getMyAddress()); authenticationHandshakes.put(peerAddress, authenticationHandshake); SettableFuture future = authenticationHandshake.respondToAuthenticationRequest(message, connection); @@ -186,8 +186,7 @@ public class PeerGroup implements MessageListener, ConnectionListener { @Override public void onFailure(@NotNull Throwable throwable) { - log.error("AuthenticationHandshake failed. " + throwable.getMessage()); - throwable.printStackTrace(); + log.info("AuthenticationHandshake failed. That is expected if peer went offline. " + throwable.getMessage()); removePeer(connection.getPeerAddress()); } }); @@ -468,7 +467,7 @@ public class PeerGroup implements MessageListener, ConnectionListener { List authenticatedConnections = allConnections.stream() .filter(e -> e.isAuthenticated()) - .filter(e -> e.getConnectionType() == ConnectionType.PASSIVE) + .filter(e -> e.getConnectionType() == ConnectionMode.PASSIVE) .collect(Collectors.toList()); if (authenticatedConnections.size() == 0) { @@ -477,7 +476,7 @@ public class PeerGroup implements MessageListener, ConnectionListener { if (size > MAX_CONNECTIONS_NORMAL_PRIO) { authenticatedConnections = allConnections.stream() .filter(e -> e.isAuthenticated()) - .filter(e -> e.getConnectionType() == ConnectionType.PASSIVE || e.getConnectionType() == ConnectionType.ACTIVE) + .filter(e -> e.getConnectionType() == ConnectionMode.PASSIVE || e.getConnectionType() == ConnectionMode.ACTIVE) .collect(Collectors.toList()); if (authenticatedConnections.size() == 0) { diff --git a/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java b/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java index fb4d7554df..5966a84412 100644 --- a/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java +++ b/network/src/main/java/io/bitsquare/p2p/storage/ProtectedExpirableDataStorage.java @@ -285,7 +285,7 @@ public class ProtectedExpirableDataStorage implements MessageListener { Log.traceCall(); int newSequenceNumber = data.sequenceNumber; Integer storedSequenceNumber = sequenceNumberMap.get(hashOfData); - if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber <= storedSequenceNumber) { + if (sequenceNumberMap.containsKey(hashOfData) && newSequenceNumber < storedSequenceNumber) { log.trace("Sequence number is invalid. newSequenceNumber=" + newSequenceNumber + " / storedSequenceNumber=" + storedSequenceNumber); return false;