diff --git a/apitest/docs/api-beta-test-guide.md b/apitest/docs/api-beta-test-guide.md index 3b6396fcf61..7343410f742 100644 --- a/apitest/docs/api-beta-test-guide.md +++ b/apitest/docs/api-beta-test-guide.md @@ -410,7 +410,7 @@ $ apitest/scripts/trade-simulation.sh -d sell -c jp -m 0.5 -a 0.125 ``` The `createoffer` command can also be used to create BSQ swap offers, where trade execution is performed immediately -after a BSQ swap offer is taken. To swap 0.5 BTC for BSQ at a price of 0.00005 BSQ per 1 BTC: +after a BSQ swap offer is taken. To swap 0.5 BTC for BSQ at a price of 0.00005 BTC for 1 BSQ: ``` $ ./bisq-cli --password=xyz --port=9998 createoffer \ --swap=true \ diff --git a/core/src/main/java/bisq/core/support/dispute/Dispute.java b/core/src/main/java/bisq/core/support/dispute/Dispute.java index 4258d843ba9..326ff97e187 100644 --- a/core/src/main/java/bisq/core/support/dispute/Dispute.java +++ b/core/src/main/java/bisq/core/support/dispute/Dispute.java @@ -352,8 +352,10 @@ public void addAndPersistChatMessage(ChatMessage chatMessage) { } public boolean removeAllChatMessages() { - if (chatMessages.size() > 0) { - chatMessages.clear(); + if (chatMessages.size() > 1) { + // removes all chat except the initial guidelines message. + String firstMessageUid = chatMessages.get(0).getUid(); + chatMessages.removeIf((msg) -> !msg.getUid().equals(firstMessageUid)); return true; } return false; diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java index f8f0824767b..88f6d3eea91 100644 --- a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java @@ -307,7 +307,7 @@ public void maybeClearSensitiveData() { Instant safeDate = closedTradableManager.getSafeDateForSensitiveDataClearing(); getDisputeList().getList().stream() .filter(e -> e.isClosed()) - .filter(e -> e.getTradeDate().toInstant().isBefore(safeDate)) + .filter(e -> e.getOpeningDate().toInstant().isBefore(safeDate)) .forEach(Dispute::maybeClearSensitiveData); requestPersistence(); } diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 22586f991d1..acfef2fb262 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -364,7 +364,8 @@ private void handleBsqSwapRequest(NodeAddress peer, BsqSwapRequest request) { peer, errorMessage -> { if (takeOfferRequestErrorMessageHandler != null) - takeOfferRequestErrorMessageHandler.handleErrorMessage(errorMessage); + takeOfferRequestErrorMessageHandler.handleErrorMessage( + errorMessage + Res.get("notification.bsqSwap.errorHelp")); }); requestPersistence(); diff --git a/core/src/main/java/bisq/core/trade/model/bisq_v1/Contract.java b/core/src/main/java/bisq/core/trade/model/bisq_v1/Contract.java index 4f939e36b2c..5bf915c6f00 100644 --- a/core/src/main/java/bisq/core/trade/model/bisq_v1/Contract.java +++ b/core/src/main/java/bisq/core/trade/model/bisq_v1/Contract.java @@ -151,12 +151,12 @@ public Contract(OfferPayload offerPayload, this.makerPaymentMethodId = makerPaymentMethodId; this.takerPaymentMethodId = takerPaymentMethodId; - // Either makerPaymentAccountPayload is set or makerPaymentMethodId + // Either makerPaymentMethodId is set, or obtained from offerPayload. if (makerPaymentMethodId == null) { - makerPaymentMethodId = checkNotNull(makerPaymentAccountPayload).getPaymentMethodId(); + makerPaymentMethodId = checkNotNull(offerPayload).getPaymentMethodId(); } if (takerPaymentMethodId == null) { - takerPaymentMethodId = checkNotNull(takerPaymentAccountPayload).getPaymentMethodId(); + takerPaymentMethodId = checkNotNull(offerPayload).getPaymentMethodId(); } checkNotNull(makerPaymentMethodId); checkNotNull(takerPaymentMethodId); @@ -298,8 +298,8 @@ public byte[] getHashOfPeersPaymentAccountPayload(PubKeyRing myPubKeyRing) { } public String getPaymentMethodId() { - // Either makerPaymentMethodId is set or available in makerPaymentAccountPayload - return makerPaymentMethodId != null ? makerPaymentMethodId : Objects.requireNonNull(makerPaymentAccountPayload).getPaymentMethodId(); + // Either makerPaymentMethodId is set or available in offerPayload + return makerPaymentMethodId != null ? makerPaymentMethodId : Objects.requireNonNull(getOfferPayload()).getPaymentMethodId(); } public Coin getTradeAmount() { diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index dc7e1a0dae9..78c9f6b0b3e 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -146,7 +146,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid public static final boolean USE_SYMMETRIC_SECURITY_DEPOSIT = true; public static final int CLEAR_DATA_AFTER_DAYS_INITIAL = 99999; // feature effectively disabled until user agrees to settings notification - public static final int CLEAR_DATA_AFTER_DAYS_DEFAULT = 20; // used when user has agreed to settings notification + public static final int CLEAR_DATA_AFTER_DAYS_DEFAULT = 60; // used when user has agreed to settings notification // payload is initialized so the default values are available for Property initialization. @Setter diff --git a/core/src/main/java/bisq/core/util/SimpleMarkdownParser.java b/core/src/main/java/bisq/core/util/SimpleMarkdownParser.java index 84c0517d18b..6cd75f00e65 100644 --- a/core/src/main/java/bisq/core/util/SimpleMarkdownParser.java +++ b/core/src/main/java/bisq/core/util/SimpleMarkdownParser.java @@ -46,9 +46,9 @@ public static List parse(String markdown) { sb = new StringBuilder(); } state = MarkdownParsingState.LINK_TEXT; - } else if (c == '(') { + } else if (c == '(' && state == MarkdownParsingState.LINK_TEXT) { state = MarkdownParsingState.LINK_HREF; - } else if (c == ')') { + } else if (c == ')' && state == MarkdownParsingState.LINK_HREF) { state = MarkdownParsingState.TEXT; items.add(new HyperlinkNode(sb.toString(), sb2.toString())); sb = new StringBuilder(); diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 92d44a99e70..550b1667057 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -1393,7 +1393,7 @@ settings.preferences.sensitiveDataRemoval.msg=To protect the privacy of yourself remove payment account details from old trades. This is particularly important for fiat trades which may include bank \ account details. Read more about this at [HYPERLINK:https://bisq.wiki/Data_Privacy].\n\n\ The threshold for data removal can be configured on this screen via the field "Clear sensitive data after (days)". \ - It is recommended to set it as low as possible, for example 20 days. That means trades from more than 20 \ + It is recommended to set it as low as possible, for example 60 days. That means trades from more than 60 \ days ago will have payment account details cleared, as long as they are finished. Finished trades are ones which \ are found in the Portfolio / History tab. @@ -3164,6 +3164,15 @@ notification.bsqSwap.maker.headline=BSQ swap completed notification.bsqSwap.maker.tradeCompleted=Your offer with ID ''{0}'' has been taken. notification.bsqSwap.confirmed.headline=BSQ swap transaction confirmed notification.bsqSwap.confirmed.text=The BSQ swap transaction for trade with ID ''{0}'' is confirmed. +notification.bsqSwap.errorHelp=\n\n\ + Trade failures with BSQ swaps are rare, in cases like this it is worthwhile checking if:\n\ + ● your DAO state is synced without error.\n\ + ● your SPV wallet is functioning well.\n\n\ + DAO state can be checked by navigating to DAO -> Network Monitor -> DAO State. It can be resynced by \ + pressing the button "Rebuild DAO State From Resources" under Settings -> Preferences.\n\n\ + SPV status is harder to determine, usually a resync is necessary whenever you experience problems transacting \ + on the blockchain. More info at [HYPERLINK:https://bisq.wiki/Resyncing_SPV_file] + #################################################################### # System Tray diff --git a/core/src/test/java/bisq/core/util/SimpleMarkdownParserTest.java b/core/src/test/java/bisq/core/util/SimpleMarkdownParserTest.java index 51c90a7fe3e..4c1ffd82f93 100644 --- a/core/src/test/java/bisq/core/util/SimpleMarkdownParserTest.java +++ b/core/src/test/java/bisq/core/util/SimpleMarkdownParserTest.java @@ -28,4 +28,16 @@ public void testParse() { SimpleMarkdownParser.TextNode item2 = (SimpleMarkdownParser.TextNode) result.get(2); assertEquals(". \n\nIf you have any problems you can try to contact the trade peer in the trade chat.", item2.getText()); } + + @Test + public void testParseWithBrackets() { + String text = "Take a look (here) for more"; + + List result = SimpleMarkdownParser.parse(text); + + assertEquals(1, result.size()); + + SimpleMarkdownParser.TextNode item0 = (SimpleMarkdownParser.TextNode) result.get(0); + assertEquals("Take a look (here) for more", item0.getText()); + } } diff --git a/desktop/src/main/java/bisq/desktop/components/InfoAutoTooltipLabel.java b/desktop/src/main/java/bisq/desktop/components/InfoAutoTooltipLabel.java index add5cf9dbfd..83562396b0f 100644 --- a/desktop/src/main/java/bisq/desktop/components/InfoAutoTooltipLabel.java +++ b/desktop/src/main/java/bisq/desktop/components/InfoAutoTooltipLabel.java @@ -74,6 +74,12 @@ public void hideIcon() { setGraphic(textIcon); } + // May be required until https://bugs.openjdk.java.net/browse/JDK-8265835 is fixed. + public void disableRolloverPopup() { + textIcon.setOnMouseEntered(null); + textIcon.setOnMouseExited(null); + } + private void positionAndActivateIcon(ContentDisplay contentDisplay, String info, double width) { textIcon.setOpacity(0.4); textIcon.getStyleClass().add("tooltip-icon"); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java index 60024d11012..a60856f7cd4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bsq_swap/take_offer/BsqSwapTakeOfferView.java @@ -378,8 +378,8 @@ protected void addSubscriptions() { if (newValue == null) { return; } - new Popup().error(Res.get("takeOffer.error.message", model.errorMessage.get()) + "\n\n" + - Res.get("popup.error.tryRestart")) + new Popup().warning(Res.get("takeOffer.error.message", model.errorMessage.get()) + + Res.get("notification.bsqSwap.errorHelp")) .onClose(() -> { model.resetErrorMessage(); model.dataModel.removeOffer(); diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java index a7840faf891..7b2394d852d 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java @@ -756,21 +756,23 @@ protected void applyStyles() { if (headLineLabel != null) { - copyIcon.getStyleClass().add("popup-icon-information"); - copyIcon.setManaged(true); - copyIcon.setVisible(true); - FormBuilder.getIconForLabel(AwesomeIcon.COPY, copyIcon, "1.5em"); - copyIcon.addEventHandler(MOUSE_CLICKED, mouseEvent -> { - if (message != null) { - String forClipboard = headLineLabel.getText() + System.lineSeparator() + message - + System.lineSeparator() + (messageHyperlinks == null ? "" : messageHyperlinks.toString()); - Utilities.copyToClipboard(forClipboard); - Tooltip tp = new Tooltip(Res.get("shared.copiedToClipboard")); - Node node = (Node) mouseEvent.getSource(); - UserThread.runAfter(() -> tp.hide(), 1); - tp.show(node, mouseEvent.getScreenX() + Layout.PADDING, mouseEvent.getScreenY() + Layout.PADDING); - } - }); + if (copyIcon != null) { + copyIcon.getStyleClass().add("popup-icon-information"); + copyIcon.setManaged(true); + copyIcon.setVisible(true); + FormBuilder.getIconForLabel(AwesomeIcon.COPY, copyIcon, "1.5em"); + copyIcon.addEventHandler(MOUSE_CLICKED, mouseEvent -> { + if (message != null) { + String forClipboard = headLineLabel.getText() + System.lineSeparator() + message + + System.lineSeparator() + (messageHyperlinks == null ? "" : messageHyperlinks.toString()); + Utilities.copyToClipboard(forClipboard); + Tooltip tp = new Tooltip(Res.get("shared.copiedToClipboard")); + Node node = (Node) mouseEvent.getSource(); + UserThread.runAfter(() -> tp.hide(), 1); + tp.show(node, mouseEvent.getScreenX() + Layout.PADDING, mouseEvent.getScreenY() + Layout.PADDING); + } + }); + } switch (type) { case Information: @@ -815,14 +817,6 @@ protected void addHeadLine() { HBox hBox = new HBox(); hBox.setSpacing(7); - copyIcon = new Label(); - copyIcon.setManaged(false); - copyIcon.setVisible(false); - copyIcon.setPadding(new Insets(3)); - copyIcon.setTooltip(new Tooltip(Res.get("shared.copyToClipboard"))); - final Pane spacer = new Pane(); - HBox.setHgrow(spacer, Priority.ALWAYS); - spacer.setMinSize(Layout.PADDING, 1); headLineLabel = new AutoTooltipLabel(headLine); headlineIcon = new Label(); headlineIcon.setManaged(false); @@ -833,7 +827,19 @@ protected void addHeadLine() { if (headlineStyle != null) headLineLabel.setStyle(headlineStyle); - hBox.getChildren().addAll(headlineIcon, headLineLabel, spacer, copyIcon); + if (message != null) { + copyIcon = new Label(); + copyIcon.setManaged(false); + copyIcon.setVisible(false); + copyIcon.setPadding(new Insets(3)); + copyIcon.setTooltip(new Tooltip(Res.get("shared.copyToClipboard"))); + final Pane spacer = new Pane(); + HBox.setHgrow(spacer, Priority.ALWAYS); + spacer.setMinSize(Layout.PADDING, 1); + hBox.getChildren().addAll(headlineIcon, headLineLabel, spacer, copyIcon); + } else { + hBox.getChildren().addAll(headlineIcon, headLineLabel); + } GridPane.setHalignment(hBox, HPos.LEFT); GridPane.setRowIndex(hBox, rowIndex); diff --git a/desktop/src/main/java/bisq/desktop/main/presentation/DaoPresentation.java b/desktop/src/main/java/bisq/desktop/main/presentation/DaoPresentation.java index 1ff32e07e19..d36efe3faa6 100644 --- a/desktop/src/main/java/bisq/desktop/main/presentation/DaoPresentation.java +++ b/desktop/src/main/java/bisq/desktop/main/presentation/DaoPresentation.java @@ -1,6 +1,7 @@ package bisq.desktop.main.presentation; import bisq.desktop.Navigation; +import bisq.desktop.util.GUIUtil; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; @@ -98,9 +99,7 @@ private void onUpdateAnyChainHeight() { bsqInfo.set(""); if (daoFacade.isInConflictWithSeedNode() && !daoConflictWarningShown) { daoConflictWarningShown = true; // only warn max 1 time per session so as not to annoy - // TODO: only temporarily removed for v1.8.2 to prevent showing false positives and will be - // re-enabled with the next release -// GUIUtil.showDaoNeedsResyncPopup(navigation); + GUIUtil.showDaoNeedsResyncPopup(navigation); } } else { bsqInfo.set(Res.get("mainView.footer.bsqInfo.synchronizing")); diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index 29040f67305..d663f7873e7 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -959,6 +959,7 @@ protected void updateItem(PaymentAccount item, boolean empty) { MaterialDesignIcon icon = getIconForSignState(signState); label.setIcon(icon, info); + label.disableRolloverPopup(); // see https://github.com/bisq-network/bisq/issues/6059 } setGraphic(label); } else { diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 1595202ac34..cbe6a4701ac 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -172,6 +172,7 @@ message GetMyBsqSwapOffersReply { repeated OfferInfo bsqSwapOffers = 1; // The returned list of user's open BSQ swap offers. } +// TODO: Change some numeric fields to string to prevent loss of precision and/or ambiguity. message CreateBsqSwapOfferRequest { // The new BSQ swap offer's BUY (BTC) or SELL (BTC) direction. string direction = 1; @@ -187,6 +188,7 @@ message CreateBsqSwapOfferReply { OfferInfo bsqSwapOffer = 1; // The newly created BSQ swap offer. } +// TODO: Change some numeric fields to string to prevent loss of precision and/or ambiguity. message CreateOfferRequest { // The new offer's fiat or altcoin currency code. string currencyCode = 1;