diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesController.java index 836855e5cc..1ed1e6348e 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesController.java @@ -195,7 +195,7 @@ protected void selectedChannelChanged(ChatChannel chatCha }); } - void onSelectItem(BisqEasyOpenTradesView.ListItem item) { + void onSelectItem(OpenTradeListItem item) { if (item == null || !hasTradeForChannel(item.getChannel())) { selectionService.selectChannel(null); } else { @@ -273,7 +273,7 @@ private void handleChannelRemoved(BisqEasyOpenTradeChannel channel) { bisqEasyTradeService.findTrade(tradeId) .ifPresentOrElse(this::handleTradeAndChannelRemoved, () -> { - Optional listItem = findListItem(tradeId); + Optional listItem = findListItem(tradeId); if (listItem.isEmpty()) { log.debug("Channel with tradeId {} was removed but associated trade and the listItem is not found. " + "This is expected as we first remove the trade and then the channel.", tradeId); @@ -303,7 +303,7 @@ private void handleTradeAndChannelAdded(BisqEasyTrade trade, BisqEasyOpenTradeCh return; } - model.getListItems().add(new BisqEasyOpenTradesView.ListItem(channel, + model.getListItems().add(new OpenTradeListItem(channel, trade, reputationService, chatNotificationService, @@ -334,7 +334,7 @@ private void handleTradeAndChannelRemoved(BisqEasyTrade trade) { return; } - BisqEasyOpenTradesView.ListItem item = findListItem(trade).get(); + OpenTradeListItem item = findListItem(trade).get(); item.dispose(); model.getListItems().remove(item); @@ -352,7 +352,7 @@ private void handleTradeAndChannelRemoved(BisqEasyTrade trade) { private void handleClearTradesAndChannels() { UIThread.run(() -> { - model.getListItems().forEach(BisqEasyOpenTradesView.ListItem::dispose); + model.getListItems().forEach(OpenTradeListItem::dispose); model.getListItems().clear(); isInMediationPinMap.values().forEach(Pin::unbind); @@ -395,11 +395,11 @@ private void updateIsAnyTradeInMediation() { }); } - private Optional findListItem(BisqEasyTrade trade) { + private Optional findListItem(BisqEasyTrade trade) { return findListItem(trade.getId()); } - private Optional findListItem(String tradeId) { + private Optional findListItem(String tradeId) { return model.getListItems().stream() .filter(item -> item.getTrade().getId().equals(tradeId)) .findAny(); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesModel.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesModel.java index d22d1af16e..92e6496021 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesModel.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesModel.java @@ -39,10 +39,10 @@ public final class BisqEasyOpenTradesModel extends ChatModel { private final BooleanProperty isAnyTradeInMediation = new SimpleBooleanProperty(); private final StringProperty chatWindowTitle = new SimpleStringProperty(); private final ObjectProperty chatWindow = new SimpleObjectProperty<>(); - private final ObjectProperty selectedItem = new SimpleObjectProperty<>(); - private final ObservableList listItems = FXCollections.observableArrayList(); - private final FilteredList filteredList = new FilteredList<>(listItems); - private final SortedList sortedList = new SortedList<>(filteredList); + private final ObjectProperty selectedItem = new SimpleObjectProperty<>(); + private final ObservableList listItems = FXCollections.observableArrayList(); + private final FilteredList filteredList = new FilteredList<>(listItems); + private final SortedList sortedList = new SortedList<>(filteredList); public BisqEasyOpenTradesModel(ChatChannelDomain chatChannelDomain) { super(chatChannelDomain); @@ -58,7 +58,7 @@ void reset() { chatWindowTitle.set(null); chatWindow.set(null); selectedItem.set(null); - listItems.forEach(BisqEasyOpenTradesView.ListItem::dispose); + listItems.forEach(OpenTradeListItem::dispose); listItems.clear(); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesView.java index 1e0ea753cd..94c84d064b 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesView.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/BisqEasyOpenTradesView.java @@ -17,13 +17,7 @@ package bisq.desktop.main.content.bisq_easy.open_trades; -import bisq.account.payment_method.BitcoinPaymentRail; -import bisq.account.payment_method.FiatPaymentRail; -import bisq.chat.bisq_easy.open_trades.BisqEasyOpenTradeChannel; -import bisq.chat.notifications.ChatNotificationService; import bisq.common.data.Quadruple; -import bisq.common.observable.Pin; -import bisq.contract.bisq_easy.BisqEasyContract; import bisq.desktop.CssConfig; import bisq.desktop.common.Layout; import bisq.desktop.common.threading.UIThread; @@ -34,23 +28,13 @@ import bisq.desktop.components.table.BisqTableColumn; import bisq.desktop.components.table.BisqTableView; import bisq.desktop.components.table.DateColumnUtil; -import bisq.desktop.components.table.DateTableItem; import bisq.desktop.main.content.bisq_easy.BisqEasyViewUtils; import bisq.desktop.main.content.chat.ChatView; import bisq.desktop.main.content.components.UserProfileDisplay; import bisq.desktop.main.content.components.UserProfileIcon; import bisq.i18n.Res; -import bisq.presentation.formatters.DateFormatter; -import bisq.trade.bisq_easy.BisqEasyTrade; -import bisq.trade.bisq_easy.BisqEasyTradeFormatter; -import bisq.trade.bisq_easy.BisqEasyTradeUtils; import bisq.user.profile.UserProfile; -import bisq.user.profile.UserProfileService; -import bisq.user.reputation.ReputationScore; -import bisq.user.reputation.ReputationService; import javafx.beans.InvalidationListener; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; import javafx.geometry.Insets; import javafx.geometry.Point2D; import javafx.geometry.Pos; @@ -63,9 +47,6 @@ import javafx.stage.Modality; import javafx.stage.Stage; import javafx.util.Callback; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; @@ -75,12 +56,12 @@ @Slf4j public final class BisqEasyOpenTradesView extends ChatView { private final VBox tradeWelcomeViewRoot, tradeStateViewRoot, chatVBox; - private final BisqTableView tableView; + private final BisqTableView tableView; private final Button toggleChatWindowButton; private final AnchorPane tableViewAnchorPane; private Subscription noOpenTradesPin, tradeRulesAcceptedPin, tableViewSelectionPin, selectedModelItemPin, chatWindowPin, isAnyTradeInMediationPin; - private BisqTableColumn mediatorColumn; + private BisqTableColumn mediatorColumn; private final InvalidationListener listItemListener; public BisqEasyOpenTradesView(BisqEasyOpenTradesModel model, @@ -318,90 +299,90 @@ private void chatWindowChanged(Stage chatWindow) { private void configTableView() { tableView.getColumns().add(tableView.getSelectionMarkerColumn()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.me")) .fixWidth(45) .left() - .comparator(Comparator.comparing(ListItem::getMyUserName)) + .comparator(Comparator.comparing(OpenTradeListItem::getMyUserName)) .setCellFactory(getMyUserCellFactory()) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .minWidth(95) .left() - .comparator(Comparator.comparing(ListItem::getDirectionalTitle)) - .valueSupplier(ListItem::getDirectionalTitle) + .comparator(Comparator.comparing(OpenTradeListItem::getDirectionalTitle)) + .valueSupplier(OpenTradeListItem::getDirectionalTitle) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.tradePeer")) .minWidth(110) .left() - .comparator(Comparator.comparing(ListItem::getPeersUserName)) + .comparator(Comparator.comparing(OpenTradeListItem::getPeersUserName)) .setCellFactory(getTradePeerCellFactory()) .build()); - mediatorColumn = new BisqTableColumn.Builder() + mediatorColumn = new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.mediator")) .minWidth(110) .left() - .comparator(Comparator.comparing(ListItem::getMediatorUserName)) + .comparator(Comparator.comparing(OpenTradeListItem::getMediatorUserName)) .setCellFactory(getMediatorCellFactory()) .build(); tableView.getColumns().add(DateColumnUtil.getDateColumn(tableView.getSortOrder())); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.tradeId")) .minWidth(85) - .comparator(Comparator.comparing(ListItem::getTradeId)) - .valueSupplier(ListItem::getShortTradeId) + .comparator(Comparator.comparing(OpenTradeListItem::getTradeId)) + .valueSupplier(OpenTradeListItem::getShortTradeId) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.quoteAmount")) .fixWidth(95) - .comparator(Comparator.comparing(ListItem::getQuoteAmount)) - .valueSupplier(ListItem::getQuoteAmountString) + .comparator(Comparator.comparing(OpenTradeListItem::getQuoteAmount)) + .valueSupplier(OpenTradeListItem::getQuoteAmountString) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.baseAmount")) .fixWidth(120) - .comparator(Comparator.comparing(ListItem::getBaseAmount)) - .valueSupplier(ListItem::getBaseAmountString) + .comparator(Comparator.comparing(OpenTradeListItem::getBaseAmount)) + .valueSupplier(OpenTradeListItem::getBaseAmountString) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.price")) .fixWidth(135) - .comparator(Comparator.comparing(ListItem::getPrice)) - .valueSupplier(ListItem::getPriceString) + .comparator(Comparator.comparing(OpenTradeListItem::getPrice)) + .valueSupplier(OpenTradeListItem::getPriceString) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.paymentMethod")) .minWidth(45) - .comparator(Comparator.comparing(ListItem::getFiatPaymentMethod)) + .comparator(Comparator.comparing(OpenTradeListItem::getFiatPaymentMethod)) .setCellFactory(getPaymentMethodCellFactory()) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.settlementMethod")) .minWidth(45) - .comparator(Comparator.comparing(ListItem::getBitcoinSettlementMethod)) + .comparator(Comparator.comparing(OpenTradeListItem::getBitcoinSettlementMethod)) .setCellFactory(getSettlementMethodCellFactory()) .build()); - tableView.getColumns().add(new BisqTableColumn.Builder() + tableView.getColumns().add(new BisqTableColumn.Builder() .title(Res.get("bisqEasy.openTrades.table.makerTakerRole")) .minWidth(85) .right() - .comparator(Comparator.comparing(ListItem::getMyRole)) - .valueSupplier(ListItem::getMyRole) + .comparator(Comparator.comparing(OpenTradeListItem::getMyRole)) + .valueSupplier(OpenTradeListItem::getMyRole) .build()); } - private Callback, TableCell> getMyUserCellFactory() { + private Callback, TableCell> getMyUserCellFactory() { return column -> new TableCell<>() { private final UserProfileIcon userProfileIcon = new UserProfileIcon(); private final StackPane stackPane = new StackPane(userProfileIcon); @Override - protected void updateItem(ListItem item, boolean empty) { + protected void updateItem(OpenTradeListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { @@ -416,13 +397,13 @@ protected void updateItem(ListItem item, boolean empty) { }; } - private Callback, TableCell> getTradePeerCellFactory() { + private Callback, TableCell> getTradePeerCellFactory() { return column -> new TableCell<>() { private UserProfileDisplay userProfileDisplay; private Badge badge; @Override - protected void updateItem(ListItem item, boolean empty) { + protected void updateItem(OpenTradeListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { @@ -453,13 +434,13 @@ protected void updateItem(ListItem item, boolean empty) { }; } - private Callback, TableCell> getMediatorCellFactory() { + private Callback, TableCell> getMediatorCellFactory() { return column -> new TableCell<>() { private UserProfileDisplay userProfileDisplay; private Badge badge; @Override - protected void updateItem(ListItem item, boolean empty) { + protected void updateItem(OpenTradeListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty && item.getChannel().getMediator().isPresent()) { @@ -489,13 +470,13 @@ protected void updateItem(ListItem item, boolean empty) { }; } - private Callback, TableCell> getPaymentMethodCellFactory() { + private Callback, TableCell> getPaymentMethodCellFactory() { return column -> new TableCell<>() { private final BisqTooltip tooltip = new BisqTooltip(BisqTooltip.Style.MEDIUM_DARK); private final StackPane pane = new StackPane(); @Override - protected void updateItem(ListItem item, boolean empty) { + protected void updateItem(OpenTradeListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { @@ -516,7 +497,7 @@ protected void updateItem(ListItem item, boolean empty) { }; } - private Callback, TableCell> getSettlementMethodCellFactory() { + private Callback, TableCell> getSettlementMethodCellFactory() { return column -> new TableCell<>() { private final BisqTooltip tooltip = new BisqTooltip(BisqTooltip.Style.MEDIUM_DARK); private final StackPane pane = new StackPane(); @@ -527,7 +508,7 @@ private Callback, TableCell> } @Override - protected void updateItem(ListItem item, boolean empty) { + protected void updateItem(OpenTradeListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { @@ -555,107 +536,4 @@ private BisqEasyOpenTradesController getController() { return (BisqEasyOpenTradesController) controller; } - @ToString - @Getter - @EqualsAndHashCode(onlyExplicitlyIncluded = true) - static class ListItem implements DateTableItem { - @EqualsAndHashCode.Include - private final BisqEasyOpenTradeChannel channel; - @EqualsAndHashCode.Include - private final BisqEasyTrade trade; - - private final UserProfile myUserProfile, peersUserProfile; - private final String offerId, tradeId, shortTradeId, myUserName, directionalTitle, peersUserName, dateString, timeString, - market, priceString, baseAmountString, quoteAmountString, myRole, bitcoinSettlementMethod, - fiatPaymentMethod; - private final long date, price, baseAmount, quoteAmount; - private final ChatNotificationService chatNotificationService; - private final ReputationScore reputationScore; - private final StringProperty peerNumNotificationsProperty = new SimpleStringProperty(); - private final StringProperty mediatorNumNotificationsProperty = new SimpleStringProperty(); - private final Pin changedChatNotificationPin, isInMediationPin; - private final BitcoinPaymentRail bitcoinPaymentRail; - private final FiatPaymentRail fiatPaymentRail; - private final boolean isFiatPaymentMethodCustom; - - private long peerNumNotifications, mediatorNumNotifications; - private String mediatorUserName = ""; - private boolean isInMediation; - - public ListItem(BisqEasyOpenTradeChannel channel, - BisqEasyTrade trade, - ReputationService reputationService, - ChatNotificationService chatNotificationService, - UserProfileService userProfileService) { - this.channel = channel; - this.trade = trade; - - myUserProfile = userProfileService.getManagedUserProfile(channel.getMyUserIdentity().getUserProfile()); - peersUserProfile = userProfileService.getManagedUserProfile(channel.getPeer()); - this.chatNotificationService = chatNotificationService; - peersUserName = peersUserProfile.getUserName(); - myUserName = channel.getMyUserIdentity().getUserName(); - directionalTitle = BisqEasyTradeFormatter.getDirectionalTitle(trade); - offerId = channel.getBisqEasyOffer().getId(); - this.tradeId = trade.getId(); - shortTradeId = trade.getShortId(); - - BisqEasyContract contract = trade.getContract(); - date = contract.getTakeOfferDate(); - dateString = DateFormatter.formatDate(date); - timeString = DateFormatter.formatTime(date); - market = trade.getOffer().getMarket().toString(); - price = BisqEasyTradeUtils.getPriceQuote(trade).getValue(); - priceString = BisqEasyTradeFormatter.formatPriceWithCode(trade); - baseAmount = contract.getBaseSideAmount(); - baseAmountString = BisqEasyTradeFormatter.formatBaseSideAmount(trade); - quoteAmount = contract.getQuoteSideAmount(); - quoteAmountString = BisqEasyTradeFormatter.formatQuoteSideAmountWithCode(trade); - bitcoinPaymentRail = contract.getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail(); - fiatPaymentRail = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().getPaymentRail(); - bitcoinSettlementMethod = contract.getBaseSidePaymentMethodSpec().getShortDisplayString(); - fiatPaymentMethod = contract.getQuoteSidePaymentMethodSpec().getShortDisplayString(); - isFiatPaymentMethodCustom = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().isCustomPaymentMethod(); - - myRole = BisqEasyTradeFormatter.getMakerTakerRole(trade); - reputationScore = reputationService.getReputationScore(peersUserProfile); - - changedChatNotificationPin = chatNotificationService.getChangedNotification().addObserver(notification -> - UIThread.run(() -> { - if (notification == null) { - return; - } - if (!notification.getChatChannelId().equals(channel.getId())) { - return; - } - boolean isSenderMediator = notification.getSenderUserProfile().equals(channel.getMediator()); - boolean isNotificationFromMediator = notification.getMediator().equals(notification.getSenderUserProfile()); - long numNotifications = chatNotificationService.getNumNotifications(channel); - if (isSenderMediator && isNotificationFromMediator) { - mediatorNumNotifications = numNotifications - peerNumNotifications; - String value = mediatorNumNotifications > 0 ? String.valueOf(mediatorNumNotifications) : ""; - mediatorNumNotificationsProperty.set(value); - } else { - peerNumNotifications = numNotifications - mediatorNumNotifications; - String value = peerNumNotifications > 0 ? String.valueOf(peerNumNotifications) : ""; - peerNumNotificationsProperty.set(value); - } - })); - - isInMediationPin = channel.isInMediationObservable().addObserver(isInMediation -> { - if (isInMediation == null) { - return; - } - this.isInMediation = isInMediation; - if (isInMediation) { - mediatorUserName = channel.getMediator().map(UserProfile::getUserName).orElse(""); - } - }); - } - - public void dispose() { - changedChatNotificationPin.unbind(); - isInMediationPin.unbind(); - } - } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/OpenTradeListItem.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/OpenTradeListItem.java new file mode 100644 index 0000000000..3a35397849 --- /dev/null +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/OpenTradeListItem.java @@ -0,0 +1,144 @@ +/* + * This file is part of Bisq. + * + * Bisq 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. + * + * Bisq 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 Bisq. If not, see . + */ + +package bisq.desktop.main.content.bisq_easy.open_trades; + +import bisq.account.payment_method.BitcoinPaymentRail; +import bisq.account.payment_method.FiatPaymentRail; +import bisq.chat.bisq_easy.open_trades.BisqEasyOpenTradeChannel; +import bisq.chat.notifications.ChatNotificationService; +import bisq.common.observable.Pin; +import bisq.contract.bisq_easy.BisqEasyContract; +import bisq.desktop.common.threading.UIThread; +import bisq.desktop.components.table.DateTableItem; +import bisq.presentation.formatters.DateFormatter; +import bisq.trade.bisq_easy.BisqEasyTrade; +import bisq.trade.bisq_easy.BisqEasyTradeFormatter; +import bisq.trade.bisq_easy.BisqEasyTradeUtils; +import bisq.user.profile.UserProfile; +import bisq.user.profile.UserProfileService; +import bisq.user.reputation.ReputationScore; +import bisq.user.reputation.ReputationService; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +@ToString +@Getter +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +class OpenTradeListItem implements DateTableItem { + @EqualsAndHashCode.Include + private final BisqEasyOpenTradeChannel channel; + @EqualsAndHashCode.Include + private final BisqEasyTrade trade; + + private final UserProfile myUserProfile, peersUserProfile; + private final String offerId, tradeId, shortTradeId, myUserName, directionalTitle, peersUserName, dateString, timeString, + market, priceString, baseAmountString, quoteAmountString, myRole, bitcoinSettlementMethod, + fiatPaymentMethod; + private final long date, price, baseAmount, quoteAmount; + private final ChatNotificationService chatNotificationService; + private final ReputationScore reputationScore; + private final StringProperty peerNumNotificationsProperty = new SimpleStringProperty(); + private final StringProperty mediatorNumNotificationsProperty = new SimpleStringProperty(); + private final Pin changedChatNotificationPin, isInMediationPin; + private final BitcoinPaymentRail bitcoinPaymentRail; + private final FiatPaymentRail fiatPaymentRail; + private final boolean isFiatPaymentMethodCustom; + + private long peerNumNotifications, mediatorNumNotifications; + private String mediatorUserName = ""; + private boolean isInMediation; + + public OpenTradeListItem(BisqEasyOpenTradeChannel channel, + BisqEasyTrade trade, + ReputationService reputationService, + ChatNotificationService chatNotificationService, + UserProfileService userProfileService) { + this.channel = channel; + this.trade = trade; + + myUserProfile = userProfileService.getManagedUserProfile(channel.getMyUserIdentity().getUserProfile()); + peersUserProfile = userProfileService.getManagedUserProfile(channel.getPeer()); + this.chatNotificationService = chatNotificationService; + peersUserName = peersUserProfile.getUserName(); + myUserName = channel.getMyUserIdentity().getUserName(); + directionalTitle = BisqEasyTradeFormatter.getDirectionalTitle(trade); + offerId = channel.getBisqEasyOffer().getId(); + this.tradeId = trade.getId(); + shortTradeId = trade.getShortId(); + + BisqEasyContract contract = trade.getContract(); + date = contract.getTakeOfferDate(); + dateString = DateFormatter.formatDate(date); + timeString = DateFormatter.formatTime(date); + market = trade.getOffer().getMarket().toString(); + price = BisqEasyTradeUtils.getPriceQuote(trade).getValue(); + priceString = BisqEasyTradeFormatter.formatPriceWithCode(trade); + baseAmount = contract.getBaseSideAmount(); + baseAmountString = BisqEasyTradeFormatter.formatBaseSideAmount(trade); + quoteAmount = contract.getQuoteSideAmount(); + quoteAmountString = BisqEasyTradeFormatter.formatQuoteSideAmountWithCode(trade); + bitcoinPaymentRail = contract.getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail(); + fiatPaymentRail = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().getPaymentRail(); + bitcoinSettlementMethod = contract.getBaseSidePaymentMethodSpec().getShortDisplayString(); + fiatPaymentMethod = contract.getQuoteSidePaymentMethodSpec().getShortDisplayString(); + isFiatPaymentMethodCustom = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().isCustomPaymentMethod(); + + myRole = BisqEasyTradeFormatter.getMakerTakerRole(trade); + reputationScore = reputationService.getReputationScore(peersUserProfile); + + changedChatNotificationPin = chatNotificationService.getChangedNotification().addObserver(notification -> + UIThread.run(() -> { + if (notification == null) { + return; + } + if (!notification.getChatChannelId().equals(channel.getId())) { + return; + } + boolean isSenderMediator = notification.getSenderUserProfile().equals(channel.getMediator()); + boolean isNotificationFromMediator = notification.getMediator().equals(notification.getSenderUserProfile()); + long numNotifications = chatNotificationService.getNumNotifications(channel); + if (isSenderMediator && isNotificationFromMediator) { + mediatorNumNotifications = numNotifications - peerNumNotifications; + String value = mediatorNumNotifications > 0 ? String.valueOf(mediatorNumNotifications) : ""; + mediatorNumNotificationsProperty.set(value); + } else { + peerNumNotifications = numNotifications - mediatorNumNotifications; + String value = peerNumNotifications > 0 ? String.valueOf(peerNumNotifications) : ""; + peerNumNotificationsProperty.set(value); + } + })); + + isInMediationPin = channel.isInMediationObservable().addObserver(isInMediation -> { + if (isInMediation == null) { + return; + } + this.isInMediation = isInMediation; + if (isInMediation) { + mediatorUserName = channel.getMediator().map(UserProfile::getUserName).orElse(""); + } + }); + } + + public void dispose() { + changedChatNotificationPin.unbind(); + isInMediationPin.unbind(); + } +} diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/TradeStateController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/TradeStateController.java index 3dbdd6fb86..b3e1d0e6d6 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/TradeStateController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/TradeStateController.java @@ -308,6 +308,7 @@ private void applyStateInfoVBox(@Nullable BisqEasyTradeState state) { model.getInterruptTradeButtonVisible().set(true); model.getIsTradeCompleted().set(false); + boolean isMainChain = trade.getContract().getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail() == BitcoinPaymentRail.MAIN_CHAIN; switch (state) { case INIT: break; @@ -350,7 +351,7 @@ private void applyStateInfoVBox(@Nullable BisqEasyTradeState state) { model.getStateInfoVBox().set(new SellerState3a(serviceProvider, trade, channel).getView().getRoot()); break; case SELLER_SENT_BTC_SENT_CONFIRMATION: - if (trade.getContract().getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail() == BitcoinPaymentRail.MAIN_CHAIN) { + if (isMainChain) { model.getStateInfoVBox().set(new SellerStateMainChain3b(serviceProvider, trade, channel).getView().getRoot()); } else { model.getStateInfoVBox().set(new SellerStateLightning3b(serviceProvider, trade, channel).getView().getRoot()); @@ -375,7 +376,7 @@ private void applyStateInfoVBox(@Nullable BisqEasyTradeState state) { model.getStateInfoVBox().set(new BuyerState3a(serviceProvider, trade, channel).getView().getRoot()); break; case BUYER_RECEIVED_BTC_SENT_CONFIRMATION: - if (trade.getContract().getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail() == BitcoinPaymentRail.MAIN_CHAIN) { + if (isMainChain) { model.getStateInfoVBox().set(new BuyerStateMainChain3b(serviceProvider, trade, channel).getView().getRoot()); } else { model.getStateInfoVBox().set(new BuyerStateLightning3b(serviceProvider, trade, channel).getView().getRoot()); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState1a.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState1a.java index cc922a119f..58c4c926bc 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState1a.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState1a.java @@ -107,8 +107,8 @@ public void onActivate() { model.setBitcoinPaymentHeadline(Res.get("bisqEasy.tradeState.info.buyer.phase1a.bitcoinPayment.headline." + name)); model.setBitcoinPaymentDescription(Res.get("bisqEasy.tradeState.info.buyer.phase1a.bitcoinPayment.description." + name)); model.setBitcoinPaymentPrompt(Res.get("bisqEasy.tradeState.info.buyer.phase1a.bitcoinPayment.prompt." + name)); + model.setBitcoinPaymentHelp(Res.get("bisqEasy.tradeState.info.buyer.phase1a.bitcoinPayment.walletHelp")); if (paymentRail == BitcoinPaymentRail.MAIN_CHAIN) { - model.setBitcoinPaymentHelp(Res.get("bisqEasy.tradeState.info.buyer.phase1a.bitcoinPayment.walletHelp")); model.setBitcoinPaymentValidator(new BitcoinAddressValidator()); } else { model.setBitcoinPaymentValidator(new LightningInvoiceValidator()); @@ -161,14 +161,14 @@ private void onSend() { } private void doSend() { - String name = getPaymentRail().name(); - String key = "bisqEasy.tradeState.info.buyer.phase1a.tradeLogMessage." + name; + String btcRailName = getPaymentRail().name(); + String key = "bisqEasy.tradeState.info.buyer.phase1a.tradeLogMessage." + btcRailName; String bitcoinPaymentData = model.getBitcoinPaymentData().get(); sendTradeLogMessage(Res.encode(key, model.getChannel().getMyUserIdentity().getUserName(), bitcoinPaymentData)); bisqEasyTradeService.buyerSendBitcoinPaymentData(model.getBisqEasyTrade(), bitcoinPaymentData); } - void onOpenWalletHelp() { + void onOpenWalletGuide() { Navigation.navigateTo(NavigationTarget.WALLET_GUIDE); } @@ -418,7 +418,7 @@ protected void onViewAttached() { }); sendButton.setOnAction(e -> controller.onSend()); - walletInfoButton.setOnAction(e -> controller.onOpenWalletHelp()); + walletInfoButton.setOnAction(e -> controller.onOpenWalletGuide()); scanQrCodeButton.setOnAction(e -> controller.onScanQrCode()); } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState4.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState4.java index b431336125..5cd8ae8650 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState4.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/BuyerState4.java @@ -100,7 +100,7 @@ public void onDeactivate() { super.onDeactivate(); } - private void onLeaveChannel() { + private void onCloseCompletedTrade() { new Popup().feedback(Res.get("bisqEasy.openTrades.closeTrade.warning.completed")) .actionButtonText(Res.get("bisqEasy.openTrades.confirmCloseTrade")) .onAction(() -> { @@ -152,7 +152,7 @@ protected Model(BisqEasyTrade bisqEasyTrade, BisqEasyOpenTradeChannel channel) { } public static class View extends BaseState.View { - private final Button leaveButton, exportButton; + private final Button closeTradeButton, exportButton; private final TradeCompletedTable tradeCompletedTable; private View(Model model, Controller controller) { @@ -161,9 +161,9 @@ private View(Model model, Controller controller) { tradeCompletedTable = new TradeCompletedTable(); exportButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.exportTrade")); - leaveButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.leaveChannel")); - leaveButton.setDefaultButton(true); - HBox buttons = new HBox(20, exportButton, leaveButton); + closeTradeButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.leaveChannel")); + closeTradeButton.setDefaultButton(true); + HBox buttons = new HBox(20, exportButton, closeTradeButton); buttons.setAlignment(Pos.BOTTOM_RIGHT); VBox.setMargin(buttons, new Insets(0, 0, 20, 0)); @@ -189,7 +189,7 @@ protected void onViewAttached() { tradeCompletedTable.getOpenTxExplorerButton().setOnAction(e -> controller.openExplorer()); tradeCompletedTable.getCopyTxExplorerLinkButton().setOnAction(e -> controller.copyExplorerLink()); } - leaveButton.setOnAction(e -> controller.onLeaveChannel()); + closeTradeButton.setOnAction(e -> controller.onCloseCompletedTrade()); exportButton.setOnAction(e -> controller.onExportTrade()); } @@ -198,7 +198,7 @@ protected void onViewDetached() { super.onViewDetached(); tradeCompletedTable.dispose(); - leaveButton.setOnAction(null); + closeTradeButton.setOnAction(null); exportButton.setOnAction(null); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState3a.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState3a.java index 2b49f745b7..8a3a832ab7 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState3a.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState3a.java @@ -165,24 +165,24 @@ private void onConfirmedBtcSent() { } String userName = model.getChannel().getMyUserIdentity().getUserName(); - String name = paymentRail.name(); - String proof = Res.get("bisqEasy.tradeState.info.seller.phase3a.tradeLogMessage.paymentProof." + name); + String btcRailName = paymentRail.name(); + String proofType = Res.get("bisqEasy.tradeState.info.seller.phase3a.tradeLogMessage.paymentProof." + btcRailName); if (isValid) { - confirmedBtcSent(paymentProof, userName, proof); + confirmedBtcSent(paymentProof, userName, proofType); } else { - new Popup().warning(Res.get("bisqEasy.tradeState.info.seller.phase3a.paymentProof.warning." + name)) + new Popup().warning(Res.get("bisqEasy.tradeState.info.seller.phase3a.paymentProof.warning." + btcRailName)) .actionButtonText(Res.get("bisqEasy.tradeState.info.seller.phase3a.paymentProof.warning.proceed")) - .onAction(() -> confirmedBtcSent(paymentProof, userName, proof)) + .onAction(() -> confirmedBtcSent(paymentProof, userName, proofType)) .show(); } } - private void confirmedBtcSent(String paymentProof, String userName, String proof) { + private void confirmedBtcSent(String paymentProof, String userName, String proofType) { if (paymentProof == null) { sendTradeLogMessage(Res.encode("bisqEasy.tradeState.info.seller.phase3a.tradeLogMessage.noProofProvided", userName)); } else { sendTradeLogMessage(Res.encode("bisqEasy.tradeState.info.seller.phase3a.tradeLogMessage", - userName, proof, paymentProof)); + userName, proofType, paymentProof)); } bisqEasyTradeService.sellerConfirmBtcSent(model.getBisqEasyTrade(), Optional.ofNullable(paymentProof)); } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState4.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState4.java index 2efdd0e2ff..be69c3131f 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState4.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/SellerState4.java @@ -101,7 +101,7 @@ public void onDeactivate() { super.onDeactivate(); } - private void onLeaveChannel() { + private void onCloseCompletedTrade() { new Popup().feedback(Res.get("bisqEasy.openTrades.closeTrade.warning.completed")) .actionButtonText(Res.get("bisqEasy.openTrades.confirmCloseTrade")) .onAction(() -> { @@ -153,7 +153,7 @@ protected Model(BisqEasyTrade bisqEasyTrade, BisqEasyOpenTradeChannel channel) { } public static class View extends BaseState.View { - private final Button leaveButton, exportButton; + private final Button closeTradeButton, exportButton; private final TradeCompletedTable tradeCompletedTable; private View(Model model, Controller controller) { @@ -162,9 +162,9 @@ private View(Model model, Controller controller) { tradeCompletedTable = new TradeCompletedTable(); exportButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.exportTrade")); - leaveButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.leaveChannel")); - leaveButton.setDefaultButton(true); - HBox buttons = new HBox(20, exportButton, leaveButton); + closeTradeButton = new Button(Res.get("bisqEasy.tradeState.info.phase4.leaveChannel")); + closeTradeButton.setDefaultButton(true); + HBox buttons = new HBox(20, exportButton, closeTradeButton); buttons.setAlignment(Pos.BOTTOM_RIGHT); VBox.setMargin(buttons, new Insets(0, 0, 20, 0)); @@ -190,7 +190,7 @@ protected void onViewAttached() { tradeCompletedTable.getOpenTxExplorerButton().setOnAction(e -> controller.openExplorer()); tradeCompletedTable.getCopyTxExplorerLinkButton().setOnAction(e -> controller.copyExplorerLink()); } - leaveButton.setOnAction(e -> controller.onLeaveChannel()); + closeTradeButton.setOnAction(e -> controller.onCloseCompletedTrade()); exportButton.setOnAction(e -> controller.onExportTrade()); } @@ -199,7 +199,7 @@ protected void onViewDetached() { super.onViewDetached(); tradeCompletedTable.dispose(); - leaveButton.setOnAction(null); + closeTradeButton.setOnAction(null); exportButton.setOnAction(null); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/StateMainChain3b.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/StateMainChain3b.java index 634ec379c6..d02def8049 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/StateMainChain3b.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/open_trades/trade_state/states/StateMainChain3b.java @@ -283,12 +283,17 @@ public static abstract class View getNetworkMessageResolver() // API /////////////////////////////////////////////////////////////////////////////////////////// - public String getText() { + public String getTextOrNA() { return text.orElse(Res.get("data.na")); } public boolean wasMentioned(UserIdentity userIdentity) { - return getText().contains("@" + userIdentity.getUserName()); + return getTextOrNA().contains("@" + userIdentity.getUserName()); } public boolean wasCited(UserIdentity userIdentity) { diff --git a/chat/src/main/java/bisq/chat/notifications/ChatNotificationService.java b/chat/src/main/java/bisq/chat/notifications/ChatNotificationService.java index 48ba1ac4a7..bd299fb853 100644 --- a/chat/src/main/java/bisq/chat/notifications/ChatNotificationService.java +++ b/chat/src/main/java/bisq/chat/notifications/ChatNotificationService.java @@ -471,7 +471,7 @@ private ChatNotification createNotification(String id, String userName = senderUserProfile.map(UserProfile::getUserName).orElse(Res.get("data.na")); String channelInfo = ChatUtil.getChannelNavigationPath(chatChannel); title = StringUtils.truncate(userName, 20) + " (" + channelInfo + ")"; - String text = chatMessage.getText(); + String text = chatMessage.getTextOrNA(); if (chatMessage instanceof BisqEasyOpenTradeMessage && chatMessage.getChatMessageType() == ChatMessageType.PROTOCOL_LOG_MESSAGE) { // We have encoded the i18n key so that we can show log messages in the users language. diff --git a/http-api/src/main/java/bisq/http_api/rest_api/BaseRestApiResourceConfig.java b/http-api/src/main/java/bisq/http_api/rest_api/BaseRestApiResourceConfig.java index 261b5d4e96..42a3e94791 100644 --- a/http-api/src/main/java/bisq/http_api/rest_api/BaseRestApiResourceConfig.java +++ b/http-api/src/main/java/bisq/http_api/rest_api/BaseRestApiResourceConfig.java @@ -2,7 +2,6 @@ import bisq.http_api.rest_api.error.CustomExceptionMapper; import bisq.http_api.rest_api.error.RestApiException; -import bisq.http_api.rest_api.util.SerializationModule; import bisq.http_api.rest_api.util.SwaggerResolution; import com.fasterxml.jackson.databind.ObjectMapper; import org.glassfish.jersey.internal.inject.AbstractBinder; @@ -12,7 +11,6 @@ public abstract class BaseRestApiResourceConfig extends ResourceConfig { public BaseRestApiResourceConfig(String swaggerBaseUrl) { super(); ObjectMapper mapper = new ObjectMapper(); - mapper.registerModule(new SerializationModule()); register(CustomExceptionMapper.class) .register(RestApiException.Mapper.class) diff --git a/http-api/src/main/java/bisq/http_api/rest_api/util/SerializationModule.java b/http-api/src/main/java/bisq/http_api/rest_api/util/SerializationModule.java deleted file mode 100644 index b7977a93c1..0000000000 --- a/http-api/src/main/java/bisq/http_api/rest_api/util/SerializationModule.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq 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. - * - * Bisq 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 Bisq. If not, see . - */ - -package bisq.http_api.rest_api.util; - -import bisq.security.keys.JsonSerialization; -import com.fasterxml.jackson.databind.module.SimpleModule; - -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; - -public class SerializationModule extends SimpleModule { - public SerializationModule() { - addSerializer(KeyPair.class, new JsonSerialization.KeyPair.Serializer()); - addSerializer(PublicKey.class, new JsonSerialization.PublicKey.Serializer()); - addDeserializer(PublicKey.class, new JsonSerialization.PublicKey.Deserializer()); - addSerializer(PrivateKey.class, new JsonSerialization.PrivateKey.Serializer()); - addDeserializer(PrivateKey.class, new JsonSerialization.PrivateKey.Deserializer()); - } -} diff --git a/i18n/src/main/resources/bisq_easy.properties b/i18n/src/main/resources/bisq_easy.properties index ef89c6d9f2..4424aeb5a8 100644 --- a/i18n/src/main/resources/bisq_easy.properties +++ b/i18n/src/main/resources/bisq_easy.properties @@ -856,10 +856,14 @@ bisqEasy.tradeState.info.buyer.phase3b.info.ln=Transfers via the Lightning Netwo Occasionally, payments may fail and need to be retried. bisqEasy.tradeState.info.buyer.phase3b.confirmButton.ln=Confirm receipt bisqEasy.tradeState.info.buyer.phase3b.tradeLogMessage.ln={0} has confirmed to have received the Bitcoin payment +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.buyer.phase3b.headline.MAIN_CHAIN=The seller has started the Bitcoin payment +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.buyer.phase3b.info.MAIN_CHAIN=As soon the Bitcoin transaction is visible in the Bitcoin network you will see the payment. \ After 1 blockchain confirmation the payment can be considered as completed. +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.buyer.phase3b.balance=Received Bitcoin +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.buyer.phase3b.balance.prompt=Waiting for blockchain data... # Trade State Info: Seller @@ -884,9 +888,13 @@ bisqEasy.tradeState.info.seller.phase3a.sendBtc=Send {0} to the buyer bisqEasy.tradeState.info.seller.phase3a.baseAmount=Amount to send bisqEasy.tradeState.info.seller.phase3a.qrCodeDisplay.openWindow=Open larger display bisqEasy.tradeState.info.seller.phase3a.qrCodeDisplay.window.title=Scan QR Code for trade ''{0}'' +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.seller.phase3b.headline.MAIN_CHAIN=Waiting for blockchain confirmation +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.seller.phase3b.info.MAIN_CHAIN=The Bitcoin payment require at least 1 blockchain confirmation to be considered complete. +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.seller.phase3b.balance=Bitcoin payment +# suppress inspection "UnusedProperty" bisqEasy.tradeState.info.seller.phase3b.balance.prompt=Waiting for blockchain data... #################################################################### diff --git a/network/network-identity/src/main/java/bisq/network/identity/NetworkIdWithKeyPair.java b/network/network-identity/src/main/java/bisq/network/identity/NetworkIdWithKeyPair.java index 8416d2f127..a653f78aea 100644 --- a/network/network-identity/src/main/java/bisq/network/identity/NetworkIdWithKeyPair.java +++ b/network/network-identity/src/main/java/bisq/network/identity/NetworkIdWithKeyPair.java @@ -17,10 +17,7 @@ package bisq.network.identity; -import bisq.security.keys.JsonSerialization; import bisq.security.keys.PubKey; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Getter; import lombok.ToString; @@ -31,8 +28,6 @@ @ToString public final class NetworkIdWithKeyPair { private final NetworkId networkId; - @JsonSerialize(using = JsonSerialization.KeyPair.Serializer.class) - @JsonDeserialize(using = JsonSerialization.KeyPair.Deserializer.class) private final KeyPair keyPair; public NetworkIdWithKeyPair(NetworkId networkId, KeyPair keyPair) { diff --git a/security/src/main/java/bisq/security/keys/JsonSerialization.java b/security/src/main/java/bisq/security/keys/JsonSerialization.java deleted file mode 100644 index b3a84e5a32..0000000000 --- a/security/src/main/java/bisq/security/keys/JsonSerialization.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq 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. - * - * Bisq 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 Bisq. If not, see . - */ - -package bisq.security.keys; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.*; - -import java.io.IOException; -import java.util.Base64; - -public class JsonSerialization { - public static class KeyPair { - public static class Deserializer extends JsonDeserializer { - @Override - public java.security.KeyPair deserialize(JsonParser parser, DeserializationContext context) throws IOException { - var node = parser.getCodec().readTree(parser); - try { - JsonNode privateKeyJsonNode = (JsonNode) node.get("privateKey"); - JsonNode publicKeyJsonNode = (JsonNode) node.get("publicKey"); - String privateKeyEncoded = privateKeyJsonNode.asText(); - String publicKeyEncoded = publicKeyJsonNode.asText(); - java.security.PrivateKey privateKey = KeyGeneration.generatePrivate(Base64.getDecoder().decode(privateKeyEncoded)); - java.security.PublicKey publicKey = KeyGeneration.generatePublic(Base64.getDecoder().decode(publicKeyEncoded)); - return new java.security.KeyPair(publicKey, privateKey); - } catch (Exception e) { - throw new IOException("Failed to deserialize KeyPair", e); - } - } - } - - public static class Serializer extends JsonSerializer { - @Override - public void serialize(java.security.KeyPair keyPair, - JsonGenerator generator, - SerializerProvider serializers) throws IOException { - generator.writeStartObject(); - generator.writeStringField("privateKey", Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded())); - generator.writeStringField("publicKey", Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded())); - generator.writeEndObject(); - } - } - } - - public static class PrivateKey { - public static class Deserializer extends JsonDeserializer { - @Override - public java.security.PrivateKey deserialize(JsonParser parser, - DeserializationContext context) throws IOException { - try { - byte[] bytes = Base64.getDecoder().decode(parser.getText()); - return KeyGeneration.generatePrivate(bytes); - } catch (Exception e) { - throw new IOException("Failed to deserialize publicKey", e); - } - } - } - - public static class Serializer extends JsonSerializer { - @Override - public void serialize(java.security.PrivateKey value, - JsonGenerator generator, - SerializerProvider serializers) throws IOException { - generator.writeString(Base64.getEncoder().encodeToString(value.getEncoded())); - } - } - } - - public static class PublicKey { - public static class Deserializer extends JsonDeserializer { - @Override - public java.security.PublicKey deserialize(JsonParser parser, - DeserializationContext context) throws IOException { - try { - byte[] bytes = Base64.getDecoder().decode(parser.getText()); - return KeyGeneration.generatePublic(bytes); - } catch (Exception e) { - throw new IOException("Failed to deserialize publicKey", e); - } - } - } - - public static class Serializer extends JsonSerializer { - @Override - public void serialize(java.security.PublicKey value, - JsonGenerator generator, - SerializerProvider serializers) throws IOException { - generator.writeString(Base64.getEncoder().encodeToString(value.getEncoded())); - } - } - } -} diff --git a/security/src/main/java/bisq/security/keys/KeyBundle.java b/security/src/main/java/bisq/security/keys/KeyBundle.java index 8b3b1b2e3e..7a0ad945e4 100644 --- a/security/src/main/java/bisq/security/keys/KeyBundle.java +++ b/security/src/main/java/bisq/security/keys/KeyBundle.java @@ -2,8 +2,6 @@ import bisq.common.proto.PersistableProto; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; @@ -16,8 +14,6 @@ public class KeyBundle implements PersistableProto { @EqualsAndHashCode.Exclude @ToString.Exclude - @JsonSerialize(using = JsonSerialization.KeyPair.Serializer.class) - @JsonDeserialize(using = JsonSerialization.KeyPair.Deserializer.class) private final KeyPair keyPair; private final TorKeyPair torKeyPair; private final String keyId; diff --git a/security/src/main/java/bisq/security/keys/PubKey.java b/security/src/main/java/bisq/security/keys/PubKey.java index 56f0c30c60..99547eb653 100644 --- a/security/src/main/java/bisq/security/keys/PubKey.java +++ b/security/src/main/java/bisq/security/keys/PubKey.java @@ -22,8 +22,6 @@ import bisq.common.validation.NetworkDataValidation; import bisq.security.DigestUtil; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.protobuf.ByteString; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -41,8 +39,6 @@ public final class PubKey implements NetworkProto { // Therefor we can include it for @EqualsAndHashCode. @Getter @ToString.Exclude - @JsonSerialize(using = JsonSerialization.PublicKey.Serializer.class) - @JsonDeserialize(using = JsonSerialization.PublicKey.Deserializer.class) private final PublicKey publicKey; @Getter private final String keyId; diff --git a/settings/src/main/java/bisq/settings/ChatMessageType.java b/settings/src/main/java/bisq/settings/ChatMessageType.java index 28632b0e7d..444bfd94b2 100644 --- a/settings/src/main/java/bisq/settings/ChatMessageType.java +++ b/settings/src/main/java/bisq/settings/ChatMessageType.java @@ -20,6 +20,7 @@ import bisq.common.proto.ProtoEnum; import bisq.common.proto.ProtobufUtils; +//todo rename to not conflict with chat.ChatMessageType public enum ChatMessageType implements ProtoEnum { ALL, OFFER, diff --git a/support/src/main/java/bisq/support/mediation/MediationRequest.java b/support/src/main/java/bisq/support/mediation/MediationRequest.java index fbe515acb3..5d7ffc2b3d 100644 --- a/support/src/main/java/bisq/support/mediation/MediationRequest.java +++ b/support/src/main/java/bisq/support/mediation/MediationRequest.java @@ -126,7 +126,7 @@ private List maybePrune(List StringBuilder sb = new StringBuilder(); List result = chatMessages.stream() .filter(message -> { - sb.append(message.getText()); + sb.append(message.getTextOrNA()); return sb.toString().length() < 10_000; }) .collect(Collectors.toList()); diff --git a/trade/src/main/java/bisq/trade/Trade.java b/trade/src/main/java/bisq/trade/Trade.java index f98a3ca3a5..c038609849 100644 --- a/trade/src/main/java/bisq/trade/Trade.java +++ b/trade/src/main/java/bisq/trade/Trade.java @@ -66,6 +66,8 @@ private static TradeRole createRole(boolean isBuyer, boolean isTaker) { private final Observable errorStackTrace = new Observable<>(); private final Observable peersErrorMessage = new Observable<>(); private final Observable peersErrorStackTrace = new Observable<>(); + + // Set at protocol creation and not updated later, thus no need to be observable private final Observable protocolVersion = new Observable<>(); public Trade(C contract, @@ -122,13 +124,14 @@ public void setErrorMessage(String errorMessage) { this.errorMessage.set(errorMessage); } + public String getErrorMessage() { + return errorMessage.get(); + } + public ReadOnlyObservable errorMessageObservable() { return errorMessage; } - public String getErrorMessage() { - return errorMessage.get(); - } public void setErrorStackTrace(String peersErrorStacktrace) { this.errorStackTrace.set(peersErrorStacktrace); @@ -138,18 +141,23 @@ public String getErrorStackTrace() { return errorStackTrace.get(); } - public void setPeersErrorMessage(String errorMessage) { - this.peersErrorMessage.set(errorMessage); + public ReadOnlyObservable errorStackTraceObservable() { + return errorStackTrace; } - public ReadOnlyObservable peersErrorMessageObservable() { - return peersErrorMessage; + + public void setPeersErrorMessage(String errorMessage) { + this.peersErrorMessage.set(errorMessage); } public String getPeersErrorMessage() { return peersErrorMessage.get(); } + public ReadOnlyObservable peersErrorMessageObservable() { + return peersErrorMessage; + } + public void setPeersErrorStackTrace(String peersErrorStackTrace) { this.peersErrorStackTrace.set(peersErrorStackTrace); } @@ -158,6 +166,11 @@ public String getPeersErrorStackTrace() { return peersErrorStackTrace.get(); } + public ReadOnlyObservable peersErrorStackTraceObservable() { + return peersErrorStackTrace; + } + + public void setProtocolVersion(String protocolVersion) { this.protocolVersion.set(protocolVersion); } @@ -166,6 +179,7 @@ public String getProtocolVersion() { return this.protocolVersion.get(); } + /////////////////////////////////////////////////////////////////////////////////////////////////// // Delegates /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/trade/src/main/java/bisq/trade/bisq_easy/BisqEasyTrade.java b/trade/src/main/java/bisq/trade/bisq_easy/BisqEasyTrade.java index 144392004b..c5e8122e05 100644 --- a/trade/src/main/java/bisq/trade/bisq_easy/BisqEasyTrade.java +++ b/trade/src/main/java/bisq/trade/bisq_easy/BisqEasyTrade.java @@ -52,6 +52,7 @@ public final class BisqEasyTrade extends Trade interruptTradeInitiator = new Observable<>(); + // Wrapper for stateObservable which is not handled as generic in Fsm private final transient Observable tradeState = new Observable<>(); public BisqEasyTrade(BisqEasyContract contract,