From 98f355d3fa98f79ade3db39e522995de085e52f9 Mon Sep 17 00:00:00 2001 From: Christoph Atteneder Date: Fri, 1 Apr 2022 10:04:38 +0200 Subject: [PATCH] Adapt navigational structure and offerbook handling to buy and sell different assets Still missing correct create and take offer handling --- .../bisq/core/payment/PaymentAccountUtil.java | 39 +++++ .../main/java/bisq/core/user/Preferences.java | 10 ++ .../bisq/core/user/PreferencesPayload.java | 8 + .../resources/i18n/displayStrings.properties | 20 +-- .../market/offerbook/OfferBookChartView.java | 1 + .../bisq/desktop/main/offer/BuyOfferView.java | 1 - .../bisq/desktop/main/offer/OfferView.java | 146 +++++++++++------- .../desktop/main/offer/SellOfferView.java | 3 - .../main/offer/bisq_v1/MutableOfferView.java | 5 +- .../main/offer/bisq_v1/OfferViewUtil.java | 22 +-- .../bisq_v1/takeoffer/TakeOfferView.java | 5 +- ...ferBookView.fxml => BsqOfferBookView.fxml} | 2 +- .../offer/offerbook/BsqOfferBookView.java | 74 +++++++++ .../offerbook/BsqOfferBookViewModel.java | 115 ++++++++++++++ .../offer/offerbook/BtcOfferBookView.fxml | 30 ++++ .../offer/offerbook/BtcOfferBookView.java | 64 ++++++++ .../offerbook/BtcOfferBookViewModel.java | 133 ++++++++++++++++ .../main/offer/offerbook/OfferBookView.java | 90 ++++------- .../offer/offerbook/OfferBookViewModel.java | 56 +++---- .../offer/offerbook/OtherOfferBookView.fxml | 30 ++++ .../offer/offerbook/OtherOfferBookView.java | 62 ++++++++ .../offerbook/OtherOfferBookViewModel.java | 141 +++++++++++++++++ .../offerbook/TopAltcoinOfferBookView.fxml | 30 ++++ .../offerbook/TopAltcoinOfferBookView.java | 72 +++++++++ .../TopAltcoinOfferBookViewModel.java | 115 ++++++++++++++ .../offerbook/OfferBookViewModelTest.java | 44 +++--- proto/src/main/proto/pb.proto | 2 + 27 files changed, 1115 insertions(+), 205 deletions(-) rename desktop/src/main/java/bisq/desktop/main/offer/offerbook/{OfferBookView.fxml => BsqOfferBookView.fxml} (97%) create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookViewModel.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.fxml create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookViewModel.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.fxml create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookViewModel.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.fxml create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java create mode 100644 desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookViewModel.java diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java index fc810b017d..34936b4812 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java @@ -19,6 +19,7 @@ package bisq.core.payment; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.locale.Country; +import bisq.core.locale.TradeCurrency; import bisq.core.offer.Offer; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PaymentMethod; @@ -29,6 +30,7 @@ import javafx.collections.ObservableList; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; @@ -38,6 +40,10 @@ import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; +import static bisq.core.locale.CurrencyUtil.*; +import static bisq.core.payment.payload.PaymentMethod.*; +import static java.util.Comparator.comparing; + @Slf4j public class PaymentAccountUtil { @@ -106,6 +112,39 @@ public class PaymentAccountUtil { return acceptedCountryCodes; } + public static List getTradeCurrencies(PaymentMethod paymentMethod) { + switch (paymentMethod.getId()) { + case ADVANCED_CASH_ID: + return getAllAdvancedCashCurrencies(); + case AMAZON_GIFT_CARD_ID: + return getAllAmazonGiftCardCurrencies(); + case CAPITUAL_ID: + return getAllCapitualCurrencies(); + case MONEY_GRAM_ID: + return getAllMoneyGramCurrencies(); + case PAXUM_ID: + return getAllPaxumCurrencies(); + case PAYSERA_ID: + return getAllPayseraCurrencies(); + case REVOLUT_ID: + return getAllRevolutCurrencies(); + case SWIFT_ID: + return new ArrayList<>(getAllSortedFiatCurrencies( + comparing(TradeCurrency::getCode))); + case TRANSFERWISE_ID: + return getAllTransferwiseCurrencies(); + case UPHOLD_ID: + return getAllUpholdCurrencies(); + default: + return Collections.emptyList(); + } + } + + public static boolean supportsCurrency(PaymentMethod paymentMethod, TradeCurrency selectedTradeCurrency) { + return getTradeCurrencies(paymentMethod).stream() + .anyMatch(tradeCurrency -> tradeCurrency.equals(selectedTradeCurrency)); + } + @Nullable public static List getAcceptedBanks(PaymentAccount paymentAccount) { List acceptedBanks = null; diff --git a/core/src/main/java/bisq/core/user/Preferences.java b/core/src/main/java/bisq/core/user/Preferences.java index 78c9f6b0b3..d5191738cc 100644 --- a/core/src/main/java/bisq/core/user/Preferences.java +++ b/core/src/main/java/bisq/core/user/Preferences.java @@ -592,6 +592,16 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid requestPersistence(); } + public void setBuyScreenCryptoCurrencyCode(String buyScreenCurrencyCode) { + prefPayload.setBuyScreenCryptoCurrencyCode(buyScreenCurrencyCode); + requestPersistence(); + } + + public void setSellScreenCryptoCurrencyCode(String sellScreenCurrencyCode) { + prefPayload.setSellScreenCryptoCurrencyCode(sellScreenCurrencyCode); + requestPersistence(); + } + public void setIgnoreTradersList(List ignoreTradersList) { prefPayload.setIgnoreTradersList(ignoreTradersList); requestPersistence(); diff --git a/core/src/main/java/bisq/core/user/PreferencesPayload.java b/core/src/main/java/bisq/core/user/PreferencesPayload.java index c7b5e1650d..4544cbeba4 100644 --- a/core/src/main/java/bisq/core/user/PreferencesPayload.java +++ b/core/src/main/java/bisq/core/user/PreferencesPayload.java @@ -78,6 +78,10 @@ public final class PreferencesPayload implements PersistableEnvelope { private String buyScreenCurrencyCode; @Nullable private String sellScreenCurrencyCode; + @Nullable + private String buyScreenCryptoCurrencyCode; + @Nullable + private String sellScreenCryptoCurrencyCode; private int tradeStatisticsTickUnitIndex = 3; private boolean resyncSpvRequested; private boolean sortMarketCurrenciesNumerically = true; @@ -213,6 +217,8 @@ public final class PreferencesPayload implements PersistableEnvelope { Optional.ofNullable(tradeChartsScreenCurrencyCode).ifPresent(builder::setTradeChartsScreenCurrencyCode); Optional.ofNullable(buyScreenCurrencyCode).ifPresent(builder::setBuyScreenCurrencyCode); Optional.ofNullable(sellScreenCurrencyCode).ifPresent(builder::setSellScreenCurrencyCode); + Optional.ofNullable(buyScreenCryptoCurrencyCode).ifPresent(builder::setBuyScreenCryptoCurrencyCode); + Optional.ofNullable(sellScreenCryptoCurrencyCode).ifPresent(builder::setSellScreenCryptoCurrencyCode); Optional.ofNullable(selectedPaymentAccountForCreateOffer).ifPresent( account -> builder.setSelectedPaymentAccountForCreateOffer(selectedPaymentAccountForCreateOffer.toProtoMessage())); Optional.ofNullable(bridgeAddresses).ifPresent(builder::addAllBridgeAddresses); @@ -261,6 +267,8 @@ public final class PreferencesPayload implements PersistableEnvelope { ProtoUtil.stringOrNullFromProto(proto.getTradeChartsScreenCurrencyCode()), ProtoUtil.stringOrNullFromProto(proto.getBuyScreenCurrencyCode()), ProtoUtil.stringOrNullFromProto(proto.getSellScreenCurrencyCode()), + ProtoUtil.stringOrNullFromProto(proto.getBuyScreenCryptoCurrencyCode()), + ProtoUtil.stringOrNullFromProto(proto.getSellScreenCryptoCurrencyCode()), proto.getTradeStatisticsTickUnitIndex(), proto.getResyncSpvRequested(), proto.getSortMarketCurrenciesNumerically(), diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 14679978e7..9d7a696924 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -233,8 +233,8 @@ shared.enabled=Enabled #################################################################### mainView.menu.market=Market -mainView.menu.buyBtc=Buy BTC -mainView.menu.sellBtc=Sell BTC +mainView.menu.buyBtc=Buy +mainView.menu.sellBtc=Sell mainView.menu.portfolio=Portfolio mainView.menu.funds=Funds mainView.menu.support=Support @@ -337,17 +337,16 @@ market.trades.showVolumeInUSD=Show volume in USD offerbook.createOffer=Create offer offerbook.takeOffer=Take offer offerbook.takeOffer.createAccount=Create account and take offer -offerbook.takeOfferToBuy=Take offer to buy {0} -offerbook.takeOfferToSell=Take offer to sell {0} offerbook.trader=Trader offerbook.offerersBankId=Maker''s bank ID (BIC/SWIFT): {0} offerbook.offerersBankName=Maker''s bank name: {0} offerbook.offerersBankSeat=Maker''s seat of bank country: {0} offerbook.offerersAcceptedBankSeatsEuro=Accepted seat of bank countries (taker): All Euro countries offerbook.offerersAcceptedBankSeats=Accepted seat of bank countries (taker):\n {0} -offerbook.availableOffers=Available offers -offerbook.filterByCurrency=Filter by currency -offerbook.filterByPaymentMethod=Filter by payment method +offerbook.availableOffersToBuy=Buy {0} with {1} +offerbook.availableOffersToSell=Sell {0} for {1} +offerbook.filterByCurrency=Choose currency +offerbook.filterByPaymentMethod=Choose payment method offerbook.matchingOffers=Offers matching my accounts offerbook.timeSinceSigning=Account info offerbook.timeSinceSigning.info.arbitrator=signed by an arbitrator and can sign peer accounts @@ -380,12 +379,7 @@ offerbook.volume={0} (min - max) offerbook.deposit=Deposit BTC (%) offerbook.deposit.help=Deposit paid by each trader to guarantee the trade. Will be returned when the trade is completed. -offerbook.createOfferToBuy=Create new offer to buy {0} -offerbook.createOfferToSell=Create new offer to sell {0} -offerbook.createOfferToBuy.withFiat=Create new offer to buy {0} with {1} -offerbook.createOfferToSell.forFiat=Create new offer to sell {0} for {1} -offerbook.createOfferToBuy.withCrypto=Create new offer to sell {0} (buy {1}) -offerbook.createOfferToSell.forCrypto=Create new offer to buy {0} (sell {1}) +offerbook.createNewOffer=Create new offer offerbook.createOfferDisabled.tooltip=You can only create one offer at a time offerbook.takeOfferButton.tooltip=Take offer for {0} diff --git a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java index c15860f385..bfe705ccc1 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java @@ -323,6 +323,7 @@ public class OfferBookChartView extends ActivatableViewAndModel { + model.preferences.setSellScreenCurrencyCode(model.getCurrencyCode()); navigation.navigateTo(MainView.class, SellOfferView.class); }; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/BuyOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/BuyOfferView.java index f473ec7146..e72e44b4a7 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/BuyOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/BuyOfferView.java @@ -43,7 +43,6 @@ public class BuyOfferView extends OfferView { super(viewLoader, navigation, preferences, - arbitratorManager, user, p2PService, OfferDirection.BUY); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java index 1aad98f66a..caf7de6439 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/OfferView.java @@ -26,20 +26,21 @@ import bisq.desktop.main.offer.bisq_v1.createoffer.CreateOfferView; import bisq.desktop.main.offer.bisq_v1.takeoffer.TakeOfferView; import bisq.desktop.main.offer.bsq_swap.create_offer.BsqSwapCreateOfferView; import bisq.desktop.main.offer.bsq_swap.take_offer.BsqSwapTakeOfferView; +import bisq.desktop.main.offer.offerbook.BsqOfferBookView; +import bisq.desktop.main.offer.offerbook.BtcOfferBookView; import bisq.desktop.main.offer.offerbook.OfferBookView; -import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.main.offer.offerbook.OtherOfferBookView; +import bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookView; import bisq.desktop.util.GUIUtil; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.GlobalSettings; -import bisq.core.locale.LanguageUtil; import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; import bisq.core.offer.bsq_swap.BsqSwapOfferPayload; import bisq.core.payment.payload.PaymentMethod; -import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.user.Preferences; import bisq.core.user.User; @@ -55,19 +56,18 @@ import javafx.collections.ListChangeListener; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import javax.annotation.Nullable; public abstract class OfferView extends ActivatableView { - private OfferBookView offerBookView; + private OfferBookView btcOfferBookView, bsqOfferBookView, topAltcoinOfferBookView, otherOfferBookView; private CreateOfferView createOfferView; private BsqSwapCreateOfferView bsqSwapCreateOfferView; private TakeOfferView takeOfferView; private BsqSwapTakeOfferView bsqSwapTakeOfferView; private AnchorPane createOfferPane, takeOfferPane; - private Tab takeOfferTab, createOfferTab, offerBookTab; + private Tab takeOfferTab, createOfferTab, btcOfferBookTab, bsqOfferBookTab, topAltcoinOfferBookTab, otherOfferBookTab; private final ViewLoader viewLoader; private final Navigation navigation; @@ -75,7 +75,6 @@ public abstract class OfferView extends ActivatableView { private final User user; private final P2PService p2PService; private final OfferDirection direction; - private final ArbitratorManager arbitratorManager; private Offer offer; private TradeCurrency tradeCurrency; @@ -88,7 +87,6 @@ public abstract class OfferView extends ActivatableView { protected OfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, - ArbitratorManager arbitratorManager, User user, P2PService p2PService, OfferDirection direction) { @@ -98,7 +96,6 @@ public abstract class OfferView extends ActivatableView { this.user = user; this.p2PService = p2PService; this.direction = direction; - this.arbitratorManager = arbitratorManager; } @Override @@ -117,8 +114,30 @@ public abstract class OfferView extends ActivatableView { takeOfferView.onTabSelected(true); } else if (newValue.equals(takeOfferTab) && bsqSwapTakeOfferView != null) { bsqSwapTakeOfferView.onTabSelected(true); - } else if (newValue.equals(offerBookTab) && offerBookView != null) { - offerBookView.onTabSelected(true); + } else if (newValue.equals(btcOfferBookTab)) { + if (btcOfferBookView != null) { + btcOfferBookView.onTabSelected(true); + } else { + loadView(BtcOfferBookView.class, null); + } + } else if (newValue.equals(bsqOfferBookTab)) { + if (bsqOfferBookView != null) { + bsqOfferBookView.onTabSelected(true); + } else { + loadView(BsqOfferBookView.class, null); + } + } else if (newValue.equals(topAltcoinOfferBookTab)) { + if (topAltcoinOfferBookView != null) { + topAltcoinOfferBookView.onTabSelected(true); + } else { + loadView(TopAltcoinOfferBookView.class, null); + } + } else if (newValue.equals(otherOfferBookTab)) { + if (otherOfferBookView != null) { + otherOfferBookView.onTabSelected(true); + } else { + loadView(OtherOfferBookView.class, null); + } } } if (oldValue != null) { @@ -130,8 +149,14 @@ public abstract class OfferView extends ActivatableView { takeOfferView.onTabSelected(false); } else if (oldValue.equals(takeOfferTab) && bsqSwapTakeOfferView != null) { bsqSwapTakeOfferView.onTabSelected(false); - } else if (oldValue.equals(offerBookTab) && offerBookView != null) { - offerBookView.onTabSelected(false); + } else if (oldValue.equals(btcOfferBookTab) && btcOfferBookView != null) { + btcOfferBookView.onTabSelected(false); + } else if (oldValue.equals(bsqOfferBookTab) && bsqOfferBookView != null) { + bsqOfferBookView.onTabSelected(false); + } else if (oldValue.equals(topAltcoinOfferBookTab) && topAltcoinOfferBookView != null) { + topAltcoinOfferBookView.onTabSelected(false); + } else if (oldValue.equals(otherOfferBookTab) && otherOfferBookView != null) { + otherOfferBookView.onTabSelected(false); } } }; @@ -162,7 +187,8 @@ public abstract class OfferView extends ActivatableView { if (takeOfferViewOpen) { root.getTabs().remove(takeOfferTab); } - if (canCreateOrTakeOffer(CurrencyUtil.getTradeCurrency(offer.getCurrencyCode()).get())) { + Optional optionalTradeCurrency = CurrencyUtil.getTradeCurrency(offer.getCurrencyCode()); + if (optionalTradeCurrency.isPresent() && canCreateOrTakeOffer(optionalTradeCurrency.get())) { openTakeOffer(offer); } } @@ -179,8 +205,8 @@ public abstract class OfferView extends ActivatableView { root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); root.getTabs().addListener(tabListChangeListener); navigation.addListener(navigationListener); - if (offerBookView == null) { - navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); + if (btcOfferBookView == null) { + navigation.navigateTo(MainView.class, this.getClass(), BtcOfferBookView.class); } } @@ -205,22 +231,55 @@ public abstract class OfferView extends ActivatableView { TabPane tabPane = root; tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.ALL_TABS); View view; - boolean isBuy = direction == OfferDirection.BUY; - if (viewClass == OfferBookView.class) { - if (offerBookTab != null && offerBookView != null) { - tabPane.getSelectionModel().select(offerBookTab); + if (OfferBookView.class.isAssignableFrom(viewClass)) { + + if (viewClass == BtcOfferBookView.class && btcOfferBookTab != null && btcOfferBookView != null) { + tabPane.getSelectionModel().select(btcOfferBookTab); + } else if (viewClass == BsqOfferBookView.class && bsqOfferBookTab != null && bsqOfferBookView != null) { + tabPane.getSelectionModel().select(bsqOfferBookTab); + } else if (viewClass == TopAltcoinOfferBookView.class && topAltcoinOfferBookTab != null && topAltcoinOfferBookView != null) { + tabPane.getSelectionModel().select(topAltcoinOfferBookTab); + } else if (viewClass == OtherOfferBookView.class && otherOfferBookTab != null && otherOfferBookView != null) { + tabPane.getSelectionModel().select(topAltcoinOfferBookTab); } else { - view = viewLoader.load(viewClass); - // Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens. - offerBookTab = new Tab(isBuy ? Res.get("shared.buyBitcoin").toUpperCase() : Res.get("shared.sellBitcoin").toUpperCase()); - offerBookTab.setClosable(false); - offerBookTab.setContent(view.getRoot()); - tabPane.getTabs().add(offerBookTab); - offerBookView = (OfferBookView) view; - offerBookView.onTabSelected(true); - offerBookView.setOfferActionHandler(offerActionHandler); - offerBookView.setDirection(direction); + if (btcOfferBookTab == null) { + btcOfferBookTab = new Tab("BTC"); + btcOfferBookTab.setClosable(false); + bsqOfferBookTab = new Tab("BSQ"); + bsqOfferBookTab.setClosable(false); + topAltcoinOfferBookTab = new Tab("XMR"); + topAltcoinOfferBookTab.setClosable(false); + otherOfferBookTab = new Tab("OTHER"); + otherOfferBookTab.setClosable(false); + + tabPane.getTabs().addAll(btcOfferBookTab, bsqOfferBookTab, topAltcoinOfferBookTab, otherOfferBookTab); + } + if (viewClass == BtcOfferBookView.class) { + btcOfferBookView = (OfferBookView) viewLoader.load(BtcOfferBookView.class); + btcOfferBookTab.setContent(btcOfferBookView.getRoot()); + btcOfferBookView.setOfferActionHandler(offerActionHandler); + btcOfferBookView.setDirection(direction); + btcOfferBookView.onTabSelected(true); + } else if (viewClass == BsqOfferBookView.class) { + bsqOfferBookView = (OfferBookView) viewLoader.load(BsqOfferBookView.class); + bsqOfferBookView.setOfferActionHandler(offerActionHandler); + bsqOfferBookView.setDirection(direction); + bsqOfferBookTab.setContent(bsqOfferBookView.getRoot()); + bsqOfferBookView.onTabSelected(true); + } else if (viewClass == TopAltcoinOfferBookView.class) { + topAltcoinOfferBookView = (OfferBookView) viewLoader.load(TopAltcoinOfferBookView.class); + topAltcoinOfferBookView.setOfferActionHandler(offerActionHandler); + topAltcoinOfferBookView.setDirection(direction); + topAltcoinOfferBookTab.setContent(topAltcoinOfferBookView.getRoot()); + topAltcoinOfferBookView.onTabSelected(true); + } else if (viewClass == OtherOfferBookView.class) { + otherOfferBookView = (OfferBookView) viewLoader.load(OtherOfferBookView.class); + otherOfferBookView.setOfferActionHandler(offerActionHandler); + otherOfferBookView.setDirection(direction); + otherOfferBookTab.setContent(otherOfferBookView.getRoot()); + otherOfferBookView.onTabSelected(true); + } } } else if (viewClass == CreateOfferView.class && createOfferView == null) { view = viewLoader.load(viewClass); @@ -286,23 +345,6 @@ public abstract class OfferView extends ActivatableView { GUIUtil.canCreateOrTakeOfferOrShowPopup(user, navigation, tradeCurrency); } - private void showNoArbitratorForUserLocaleWarning() { - String key = "NoArbitratorForUserLocaleWarning"; - new Popup().information(Res.get("offerbook.info.noArbitrationInUserLanguage", - getArbitrationLanguages(), LanguageUtil.getDisplayName(preferences.getUserLanguage()))) - .closeButtonText(Res.get("shared.ok")) - .dontShowAgainId(key) - .show(); - } - - private String getArbitrationLanguages() { - return arbitratorManager.getObservableMap().values().stream() - .flatMap(arbitrator -> arbitrator.getLanguageCodes().stream()) - .distinct() - .map(LanguageUtil::getDisplayName) - .collect(Collectors.joining(", ")); - } - private void openTakeOffer(Offer offer) { takeOfferViewOpen = true; this.offer = offer; @@ -332,9 +374,9 @@ public abstract class OfferView extends ActivatableView { if (bsqSwapCreateOfferView != null) { bsqSwapCreateOfferView = null; } - offerBookView.enableCreateOfferButton(); - - navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); + btcOfferBookView.enableCreateOfferButton(); + //TODO: go to last selected tab + navigation.navigateTo(MainView.class, this.getClass(), BtcOfferBookView.class); } private void onTakeOfferViewRemoved() { @@ -347,8 +389,8 @@ public abstract class OfferView extends ActivatableView { if (bsqSwapTakeOfferView != null) { bsqSwapTakeOfferView = null; } - - navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); + //TODO: go to last selected tab + navigation.navigateTo(MainView.class, this.getClass(), BtcOfferBookView.class); } public interface OfferActionHandler { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/SellOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/SellOfferView.java index bbd1617814..7d48e0a987 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/SellOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/SellOfferView.java @@ -22,7 +22,6 @@ import bisq.desktop.common.view.FxmlView; import bisq.desktop.common.view.ViewLoader; import bisq.core.offer.OfferDirection; -import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.user.Preferences; import bisq.core.user.User; @@ -37,13 +36,11 @@ public class SellOfferView extends OfferView { public SellOfferView(ViewLoader viewLoader, Navigation navigation, Preferences preferences, - ArbitratorManager arbitratorManager, User user, P2PService p2PService) { super(viewLoader, navigation, preferences, - arbitratorManager, user, p2PService, OfferDirection.SELL); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java index 6363347063..e8f9c89842 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/MutableOfferView.java @@ -1031,7 +1031,7 @@ public abstract class MutableOfferView> exten } private void addPaymentGroup() { - paymentTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, Res.get("shared.selectTradingAccount")); + paymentTitledGroupBg = addTitledGroupBg(gridPane, gridRow, 1, "Buy BTC with Fiat"); GridPane.setColumnSpan(paymentTitledGroupBg, 2); HBox paymentGroupBox = new HBox(); @@ -1106,8 +1106,7 @@ public abstract class MutableOfferView> exten GridPane.setMargin(advancedOptionsBox, new Insets(Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0)); gridPane.getChildren().add(advancedOptionsBox); - Tuple2 buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox( - navigation, preferences); + Tuple2 buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(navigation); buyBsqBox = buyBsqButtonBox.second; buyBsqBox.setManaged(false); buyBsqBox.setVisible(false); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java index 712a8fdd20..dcff764764 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/OfferViewUtil.java @@ -23,11 +23,13 @@ import bisq.desktop.components.AutoTooltipLabel; import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.main.MainView; import bisq.desktop.main.offer.SellOfferView; -import bisq.desktop.main.offer.offerbook.OfferBookView; +import bisq.desktop.main.offer.offerbook.BsqOfferBookView; import bisq.desktop.main.overlays.popups.Popup; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.user.Preferences; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferDirection; import bisq.common.UserThread; import bisq.common.util.Tuple2; @@ -84,14 +86,13 @@ public class OfferViewUtil { infoGridPane.getChildren().addAll(label, textField); } - public static Tuple2 createBuyBsqButtonBox(Navigation navigation, - Preferences preferences) { + public static Tuple2 createBuyBsqButtonBox(Navigation navigation) { String buyBsqText = Res.get("shared.buyCurrency", "BSQ"); var buyBsqButton = new AutoTooltipButton(buyBsqText); buyBsqButton.getStyleClass().add("action-button"); buyBsqButton.getStyleClass().add("tiny-button"); buyBsqButton.setMinWidth(60); - buyBsqButton.setOnAction(e -> openBuyBsqOfferBook(navigation, preferences) + buyBsqButton.setOnAction(e -> openBuyBsqOfferBook(navigation) ); var info = new AutoTooltipLabel("BSQ is colored BTC that helps fund Bisq developers."); @@ -100,7 +101,7 @@ public class OfferViewUtil { .information(Res.get("createOffer.buyBsq.popupMessage")) .actionButtonText(buyBsqText) .buttonAlignment(HPos.CENTER) - .onAction(() -> openBuyBsqOfferBook(navigation, preferences)).show()); + .onAction(() -> openBuyBsqOfferBook(navigation)).show()); learnMore.setMinWidth(100); HBox buyBsqBox = new HBox(buyBsqButton, info, learnMore); @@ -111,9 +112,12 @@ public class OfferViewUtil { return new Tuple2<>(buyBsqButton, buyBsqBox); } - private static void openBuyBsqOfferBook(Navigation navigation, Preferences preferences) { - preferences.setSellScreenCurrencyCode("BSQ"); + private static void openBuyBsqOfferBook(Navigation navigation) { navigation.navigateTo( - MainView.class, SellOfferView.class, OfferBookView.class); + MainView.class, SellOfferView.class, BsqOfferBookView.class); + } + + public static boolean isShownAsSellOffer(Offer offer) { + return CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) == (offer.getDirection() == OfferDirection.SELL); } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java index 057547912f..728b55109f 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/bisq_v1/takeoffer/TakeOfferView.java @@ -307,7 +307,7 @@ public class TakeOfferView extends ActivatableViewAndModel buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox( - navigation, model.dataModel.preferences); + Tuple2 buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(navigation); buyBsqBox = buyBsqButtonBox.second; buyBsqBox.setManaged(false); buyBsqBox.setVisible(false); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.fxml b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.fxml similarity index 97% rename from desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.fxml rename to desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.fxml index 87c9745e24..ae1fd7b244 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.fxml +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.fxml @@ -19,7 +19,7 @@ - diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java new file mode 100644 index 0000000000..ef4d5d30c3 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookView.java @@ -0,0 +1,74 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.common.view.FxmlView; +import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; +import bisq.desktop.main.overlays.windows.OfferDetailsWindow; + +import bisq.core.account.sign.SignedWitnessService; +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.alert.PrivateNotificationManager; +import bisq.core.locale.Res; +import bisq.core.offer.OfferDirection; +import bisq.core.user.Preferences; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; + +import bisq.common.config.Config; + +import javax.inject.Inject; +import javax.inject.Named; + +import javafx.scene.layout.GridPane; + +@FxmlView +public class BsqOfferBookView extends OfferBookView { + + @Inject + BsqOfferBookView(BsqOfferBookViewModel model, + Navigation navigation, + OfferDetailsWindow offerDetailsWindow, + BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, + PrivateNotificationManager privateNotificationManager, + @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys, + AccountAgeWitnessService accountAgeWitnessService, + SignedWitnessService signedWitnessService, + Preferences preferences) { + super(model, navigation, offerDetailsWindow, bsqSwapOfferDetailsWindow, formatter, privateNotificationManager, useDevPrivilegeKeys, accountAgeWitnessService, signedWitnessService); + } + + @Override + protected String getMarketTitle() { + return model.getDirection().equals(OfferDirection.BUY) ? + Res.get("offerbook.availableOffersToBuy", "BSQ", "BTC") : + Res.get("offerbook.availableOffersToSell", "BSQ", "BTC"); + } + + @Override + protected void activate() { + model.onSetTradeCurrency(BsqOfferBookViewModel.BSQ); + + super.activate(); + + currencyComboBoxContainer.setVisible(false); + currencyComboBoxContainer.setManaged(false); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookViewModel.java new file mode 100644 index 0000000000..ee9c02beeb --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BsqOfferBookViewModel.java @@ -0,0 +1,115 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.api.CoreApi; +import bisq.core.btc.setup.WalletsSetup; +import bisq.core.btc.wallet.BsqWalletService; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.TradeCurrency; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferDirection; +import bisq.core.offer.OfferFilterService; +import bisq.core.offer.OpenOfferManager; +import bisq.core.payment.payload.PaymentMethod; +import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.ClosedTradableManager; +import bisq.core.user.Preferences; +import bisq.core.user.User; +import bisq.core.util.FormattingUtils; +import bisq.core.util.PriceUtil; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; + +import bisq.network.p2p.P2PService; + +import com.google.inject.Inject; + +import javax.inject.Named; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class BsqOfferBookViewModel extends OfferBookViewModel { + + + public static final TradeCurrency BSQ = CurrencyUtil.getTradeCurrency("BSQ").get(); + + @Inject + public BsqOfferBookViewModel(User user, + OpenOfferManager openOfferManager, + OfferBook offerBook, + Preferences preferences, + WalletsSetup walletsSetup, + P2PService p2PService, + PriceFeedService priceFeedService, + ClosedTradableManager closedTradableManager, + AccountAgeWitnessService accountAgeWitnessService, + Navigation navigation, + PriceUtil priceUtil, + OfferFilterService offerFilterService, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + BsqFormatter bsqFormatter, + BsqWalletService bsqWalletService, CoreApi coreApi) { + super(user, openOfferManager, offerBook, preferences, walletsSetup, p2PService, priceFeedService, closedTradableManager, accountAgeWitnessService, navigation, priceUtil, offerFilterService, btcFormatter, bsqFormatter, bsqWalletService, coreApi); + } + + @Override + void saveSelectedCurrencyCodeInPreferences(OfferDirection direction, String code) { + // No need to store anything as it is just BSQ offers anyway + } + + @Override + protected ObservableList filterPaymentMethods(ObservableList list, + TradeCurrency selectedTradeCurrency) { + return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isAltcoin).collect(Collectors.toList())); + } + + @Override + void fillCurrencies(ObservableList tradeCurrencies, + ObservableList allCurrencies) { + tradeCurrencies.add(BSQ); + allCurrencies.add(BSQ); + } + + @Override + Predicate getCurrencyAndMethodPredicate(OfferDirection direction, + TradeCurrency selectedTradeCurrency) { + return offerBookListItem -> { + Offer offer = offerBookListItem.getOffer(); + // BUY Altcoin is actually SELL Bitcoin + boolean directionResult = offer.getDirection() == direction; + boolean currencyResult = offer.getCurrencyCode().equals(BSQ.getCode()); + boolean paymentMethodResult = showAllPaymentMethods || + offer.getPaymentMethod().equals(selectedPaymentMethod); + boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook(); + return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated; + }; + } + + @Override + String getCurrencyCodeFromPreferences(OfferDirection direction) { + return BSQ.getCode(); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.fxml b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.fxml new file mode 100644 index 0000000000..a66cbf57d1 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java new file mode 100644 index 0000000000..480a7d0579 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookView.java @@ -0,0 +1,64 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.common.view.FxmlView; +import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; +import bisq.desktop.main.overlays.windows.OfferDetailsWindow; + +import bisq.core.account.sign.SignedWitnessService; +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.alert.PrivateNotificationManager; +import bisq.core.locale.Res; +import bisq.core.offer.OfferDirection; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; + +import bisq.common.config.Config; + +import javax.inject.Inject; +import javax.inject.Named; + +import javafx.scene.layout.GridPane; + +@FxmlView +public class BtcOfferBookView extends OfferBookView { + + @Inject + BtcOfferBookView(BtcOfferBookViewModel model, + Navigation navigation, + OfferDetailsWindow offerDetailsWindow, + BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, + PrivateNotificationManager privateNotificationManager, + @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys, + AccountAgeWitnessService accountAgeWitnessService, + SignedWitnessService signedWitnessService) { + super(model, navigation, offerDetailsWindow, bsqSwapOfferDetailsWindow, formatter, privateNotificationManager, useDevPrivilegeKeys, accountAgeWitnessService, signedWitnessService); + } + + @Override + protected String getMarketTitle() { + return model.getDirection().equals(OfferDirection.BUY) ? + Res.get("offerbook.availableOffersToBuy", "BTC", "Fiat") : + Res.get("offerbook.availableOffersToSell", "BTC", "Fiat"); + + + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookViewModel.java new file mode 100644 index 0000000000..427bf59e86 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/BtcOfferBookViewModel.java @@ -0,0 +1,133 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.util.GUIUtil; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.api.CoreApi; +import bisq.core.btc.setup.WalletsSetup; +import bisq.core.btc.wallet.BsqWalletService; +import bisq.core.locale.CryptoCurrency; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.TradeCurrency; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferDirection; +import bisq.core.offer.OfferFilterService; +import bisq.core.offer.OpenOfferManager; +import bisq.core.payment.PaymentAccountUtil; +import bisq.core.payment.payload.PaymentMethod; +import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.ClosedTradableManager; +import bisq.core.user.Preferences; +import bisq.core.user.User; +import bisq.core.util.FormattingUtils; +import bisq.core.util.PriceUtil; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; + +import bisq.network.p2p.P2PService; + +import com.google.inject.Inject; + +import javax.inject.Named; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class BtcOfferBookViewModel extends OfferBookViewModel { + + @Inject + public BtcOfferBookViewModel(User user, + OpenOfferManager openOfferManager, + OfferBook offerBook, + Preferences preferences, + WalletsSetup walletsSetup, + P2PService p2PService, + PriceFeedService priceFeedService, + ClosedTradableManager closedTradableManager, + AccountAgeWitnessService accountAgeWitnessService, + Navigation navigation, + PriceUtil priceUtil, + OfferFilterService offerFilterService, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + BsqFormatter bsqFormatter, + BsqWalletService bsqWalletService, CoreApi coreApi) { + super(user, openOfferManager, offerBook, preferences, walletsSetup, p2PService, priceFeedService, closedTradableManager, accountAgeWitnessService, navigation, priceUtil, offerFilterService, btcFormatter, bsqFormatter, bsqWalletService, coreApi); + } + + @Override + void saveSelectedCurrencyCodeInPreferences(OfferDirection direction, String code) { + if (direction == OfferDirection.BUY) { + preferences.setBuyScreenCurrencyCode(code); + } else { + preferences.setSellScreenCurrencyCode(code); + } + } + + @Override + protected ObservableList filterPaymentMethods(ObservableList list, + TradeCurrency selectedTradeCurrency) { + return FXCollections.observableArrayList(list.stream() + .filter(paymentMethod -> { + if (showAllTradeCurrenciesProperty.get()) { + return paymentMethod.isFiat(); + } + return paymentMethod.isFiat() && + PaymentAccountUtil.supportsCurrency(paymentMethod, selectedTradeCurrency); + }) + .collect(Collectors.toList())); + } + + @Override + void fillCurrencies(ObservableList tradeCurrencies, + ObservableList allCurrencies) { + // Used for ignoring filter (show all) + tradeCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); + tradeCurrencies.addAll(preferences.getFiatCurrenciesAsObservable()); + tradeCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); + + allCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); + allCurrencies.addAll(CurrencyUtil.getAllSortedFiatCurrencies()); + allCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); + } + + @Override + Predicate getCurrencyAndMethodPredicate(OfferDirection direction, + TradeCurrency selectedTradeCurrency) { + return offerBookListItem -> { + Offer offer = offerBookListItem.getOffer(); + boolean directionResult = offer.getDirection() != direction; + boolean currencyResult = (showAllTradeCurrenciesProperty.get() && CurrencyUtil.isFiatCurrency(offer.getCurrencyCode())) || + offer.getCurrencyCode().equals(selectedTradeCurrency.getCode()); + boolean paymentMethodResult = showAllPaymentMethods || + offer.getPaymentMethod().equals(selectedPaymentMethod); + boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook(); + return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated; + }; + } + + @Override + String getCurrencyCodeFromPreferences(OfferDirection direction) { + return direction == OfferDirection.BUY ? preferences.getBuyScreenCurrencyCode() : preferences.getSellScreenCurrencyCode(); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index 2065068f8e..833cb83920 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -19,7 +19,6 @@ package bisq.desktop.main.offer.offerbook; import bisq.desktop.Navigation; import bisq.desktop.common.view.ActivatableViewAndModel; -import bisq.desktop.common.view.FxmlView; import bisq.desktop.components.AccountStatusTooltipLabel; import bisq.desktop.components.AutoTooltipButton; import bisq.desktop.components.AutoTooltipLabel; @@ -38,6 +37,7 @@ import bisq.desktop.main.account.content.fiataccounts.FiatAccountsView; import bisq.desktop.main.funds.FundsView; import bisq.desktop.main.funds.withdrawal.WithdrawalView; import bisq.desktop.main.offer.OfferView; +import bisq.desktop.main.offer.bisq_v1.OfferViewUtil; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; @@ -52,7 +52,6 @@ import bisq.core.account.sign.SignedWitnessService; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.alert.PrivateNotificationManager; import bisq.core.locale.CurrencyUtil; -import bisq.core.locale.FiatCurrency; import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; import bisq.core.monetary.Price; @@ -64,20 +63,15 @@ import bisq.core.offer.OpenOffer; import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentMethod; import bisq.core.user.DontShowAgainLookup; -import bisq.core.util.FormattingUtils; import bisq.core.util.coin.CoinFormatter; import bisq.network.p2p.NodeAddress; import bisq.common.app.DevEnv; -import bisq.common.config.Config; import bisq.common.util.Tuple3; import org.bitcoinj.core.Coin; -import javax.inject.Inject; -import javax.inject.Named; - import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -124,8 +118,7 @@ import org.jetbrains.annotations.NotNull; import static bisq.desktop.util.FormBuilder.addTitledGroupBg; -@FxmlView -public class OfferBookView extends ActivatableViewAndModel { +abstract public class OfferBookView extends ActivatableViewAndModel { private final Navigation navigation; private final OfferDetailsWindow offerDetailsWindow; @@ -137,7 +130,7 @@ public class OfferBookView extends ActivatableViewAndModel currencyComboBox; + protected AutocompleteComboBox currencyComboBox; private AutocompleteComboBox paymentMethodComboBox; private AutoTooltipButton createOfferButton; private AutoTooltipSlideToggleButton matchingOffersToggle; @@ -157,19 +150,19 @@ public class OfferBookView extends ActivatableViewAndModel> currencyBoxTuple = FormBuilder.addTopLabelAutocompleteComboBox( Res.get("offerbook.filterByCurrency")); + currencyComboBoxContainer = currencyBoxTuple.first; currencyComboBox = currencyBoxTuple.third; currencyComboBox.setPrefWidth(270); @@ -216,7 +210,7 @@ public class OfferBookView extends ActivatableViewAndModel tableView.sort(); } + abstract protected String getMarketTitle(); + @Override protected void activate() { + titledGroupBg.setText(getMarketTitle()); titledGroupBg.setHelpUrl(model.getDirection() == OfferDirection.SELL ? "https://bisq.wiki/Introduction#In_a_nutshell" : "https://bisq.wiki/Taking_an_offer"); @@ -360,6 +357,8 @@ public class OfferBookView extends ActivatableViewAndModel onCreateOffer()); MonadicBinding currencySelectionBinding = EasyBind.combine( model.showAllTradeCurrenciesProperty, model.tradeCurrencyCode, (showAll, code) -> { - setDirectionTitles(); if (showAll) { volumeColumn.setTitleWithHelpText(Res.get("shared.amountMinMax"), Res.get("shared.amountHelp")); priceColumn.setTitle(Res.get("shared.price")); @@ -444,7 +438,15 @@ public class OfferBookView extends ActivatableViewAndModel onTakeOffer(offer)); button2.setManaged(false); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java index df3ff85659..9becffd25d 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -68,10 +68,6 @@ import bisq.common.handlers.ResultHandler; import org.bitcoinj.core.Coin; -import com.google.inject.Inject; - -import javax.inject.Named; - import com.google.common.base.Joiner; import javafx.beans.property.BooleanProperty; @@ -102,7 +98,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; @Slf4j -class OfferBookViewModel extends ActivatableViewModel { +abstract class OfferBookViewModel extends ActivatableViewModel { private final OpenOfferManager openOfferManager; private final User user; private final OfferBook offerBook; @@ -156,7 +152,6 @@ class OfferBookViewModel extends ActivatableViewModel { // Constructor, lifecycle /////////////////////////////////////////////////////////////////////////////////////////// - @Inject public OfferBookViewModel(User user, OpenOfferManager openOfferManager, OfferBook offerBook, @@ -170,7 +165,7 @@ class OfferBookViewModel extends ActivatableViewModel { Navigation navigation, PriceUtil priceUtil, OfferFilterService offerFilterService, - @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + CoinFormatter btcFormatter, BsqFormatter bsqFormatter, BsqWalletService bsqWalletService, CoreApi coreApi) { @@ -297,13 +292,12 @@ class OfferBookViewModel extends ActivatableViewModel { setMarketPriceFeedCurrency(); filterOffers(); - if (direction == OfferDirection.BUY) - preferences.setBuyScreenCurrencyCode(code); - else - preferences.setSellScreenCurrencyCode(code); + saveSelectedCurrencyCodeInPreferences(direction, code); } } + abstract void saveSelectedCurrencyCodeInPreferences(OfferDirection direction, String code); + void onSetPaymentMethod(PaymentMethod paymentMethod) { if (paymentMethod == null) return; @@ -381,11 +375,16 @@ class OfferBookViewModel extends ActivatableViewModel { } } + list = filterPaymentMethods(list, selectedTradeCurrency); + list.sort(Comparator.naturalOrder()); list.add(0, getShowAllEntryForPaymentMethod()); return list; } + protected abstract ObservableList filterPaymentMethods(ObservableList list, + TradeCurrency selectedTradeCurrency); + String getAmount(OfferBookListItem item) { return formatAmount(item.getOffer(), true); } @@ -557,18 +556,13 @@ class OfferBookViewModel extends ActivatableViewModel { private void fillCurrencies() { tradeCurrencies.clear(); - // Used for ignoring filter (show all) - tradeCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); - tradeCurrencies.addAll(preferences.getTradeCurrenciesAsObservable()); - tradeCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); - allCurrencies.clear(); - allCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); - allCurrencies.addAll(CurrencyUtil.getAllSortedFiatCurrencies()); - allCurrencies.addAll(CurrencyUtil.getAllSortedCryptoCurrencies()); - allCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); + + fillCurrencies(tradeCurrencies, allCurrencies); } + abstract void fillCurrencies(ObservableList tradeCurrencies, + ObservableList allCurrencies); /////////////////////////////////////////////////////////////////////////////////////////// // Checks @@ -594,23 +588,13 @@ class OfferBookViewModel extends ActivatableViewModel { private void filterOffers() { Predicate predicate = useOffersMatchingMyAccountsFilter ? - getCurrencyAndMethodPredicate().and(getOffersMatchingMyAccountsPredicate()) : - getCurrencyAndMethodPredicate(); + getCurrencyAndMethodPredicate(direction, selectedTradeCurrency).and(getOffersMatchingMyAccountsPredicate()) : + getCurrencyAndMethodPredicate(direction, selectedTradeCurrency); filteredItems.setPredicate(predicate); } - private Predicate getCurrencyAndMethodPredicate() { - return offerBookListItem -> { - Offer offer = offerBookListItem.getOffer(); - boolean directionResult = offer.getDirection() != direction; - boolean currencyResult = (showAllTradeCurrenciesProperty.get()) || - offer.getCurrencyCode().equals(selectedTradeCurrency.getCode()); - boolean paymentMethodResult = showAllPaymentMethods || - offer.getPaymentMethod().equals(selectedPaymentMethod); - boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook(); - return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated; - }; - } + abstract Predicate getCurrencyAndMethodPredicate(OfferDirection direction, + TradeCurrency selectedTradeCurrency); private Predicate getOffersMatchingMyAccountsPredicate() { // This code duplicates code in the view at the button column. We need there the different results for @@ -706,7 +690,7 @@ class OfferBookViewModel extends ActivatableViewModel { } private void updateSelectedTradeCurrency() { - String code = direction == OfferDirection.BUY ? preferences.getBuyScreenCurrencyCode() : preferences.getSellScreenCurrencyCode(); + String code = getCurrencyCodeFromPreferences(direction); if (code != null && !code.isEmpty() && !isShowAllEntry(code) && CurrencyUtil.getTradeCurrency(code).isPresent()) { showAllTradeCurrenciesProperty.set(false); @@ -718,6 +702,8 @@ class OfferBookViewModel extends ActivatableViewModel { tradeCurrencyCode.set(selectedTradeCurrency.getCode()); } + abstract String getCurrencyCodeFromPreferences(OfferDirection direction); + public OpenOffer getOpenOffer(Offer offer) { return openOfferManager.getOpenOfferById(offer.getId()).orElse(null); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.fxml b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.fxml new file mode 100644 index 0000000000..697fcac560 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java new file mode 100644 index 0000000000..7ccb4f7497 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookView.java @@ -0,0 +1,62 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.common.view.FxmlView; +import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; +import bisq.desktop.main.overlays.windows.OfferDetailsWindow; + +import bisq.core.account.sign.SignedWitnessService; +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.alert.PrivateNotificationManager; +import bisq.core.locale.Res; +import bisq.core.offer.OfferDirection; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; + +import bisq.common.config.Config; + +import javax.inject.Inject; +import javax.inject.Named; + +import javafx.scene.layout.GridPane; + +@FxmlView +public class OtherOfferBookView extends OfferBookView { + + @Inject + OtherOfferBookView(OtherOfferBookViewModel model, + Navigation navigation, + OfferDetailsWindow offerDetailsWindow, + BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, + PrivateNotificationManager privateNotificationManager, + @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys, + AccountAgeWitnessService accountAgeWitnessService, + SignedWitnessService signedWitnessService) { + super(model, navigation, offerDetailsWindow, bsqSwapOfferDetailsWindow, formatter, privateNotificationManager, useDevPrivilegeKeys, accountAgeWitnessService, signedWitnessService); + } + + @Override + protected String getMarketTitle() { + return model.getDirection().equals(OfferDirection.BUY) ? + Res.get("offerbook.availableOffersToBuy", "Other assets", "BTC") : + Res.get("offerbook.availableOffersToSell", "Other assets", "BTC"); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookViewModel.java new file mode 100644 index 0000000000..ca0560230f --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OtherOfferBookViewModel.java @@ -0,0 +1,141 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.util.GUIUtil; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.api.CoreApi; +import bisq.core.btc.setup.WalletsSetup; +import bisq.core.btc.wallet.BsqWalletService; +import bisq.core.locale.CryptoCurrency; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.TradeCurrency; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferDirection; +import bisq.core.offer.OfferFilterService; +import bisq.core.offer.OpenOfferManager; +import bisq.core.payment.payload.PaymentMethod; +import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.ClosedTradableManager; +import bisq.core.user.Preferences; +import bisq.core.user.User; +import bisq.core.util.FormattingUtils; +import bisq.core.util.PriceUtil; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; + +import bisq.network.p2p.P2PService; + +import com.google.inject.Inject; + +import javax.inject.Named; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.jetbrains.annotations.NotNull; + +public class OtherOfferBookViewModel extends OfferBookViewModel { + + @Inject + public OtherOfferBookViewModel(User user, + OpenOfferManager openOfferManager, + OfferBook offerBook, + Preferences preferences, + WalletsSetup walletsSetup, + P2PService p2PService, + PriceFeedService priceFeedService, + ClosedTradableManager closedTradableManager, + AccountAgeWitnessService accountAgeWitnessService, + Navigation navigation, + PriceUtil priceUtil, + OfferFilterService offerFilterService, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + BsqFormatter bsqFormatter, + BsqWalletService bsqWalletService, CoreApi coreApi) { + super(user, openOfferManager, offerBook, preferences, walletsSetup, p2PService, priceFeedService, closedTradableManager, accountAgeWitnessService, navigation, priceUtil, offerFilterService, btcFormatter, bsqFormatter, bsqWalletService, coreApi); + } + + @Override + void saveSelectedCurrencyCodeInPreferences(OfferDirection direction, String code) { + if (direction == OfferDirection.BUY) { + preferences.setBuyScreenCryptoCurrencyCode(code); + } else { + preferences.setSellScreenCryptoCurrencyCode(code); + } + } + + @Override + protected ObservableList filterPaymentMethods(ObservableList list, + TradeCurrency selectedTradeCurrency) { + return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isBlockchain).collect(Collectors.toList())); + } + + @Override + void fillCurrencies(ObservableList tradeCurrencies, + ObservableList allCurrencies) { + + tradeCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); + tradeCurrencies.addAll(preferences.getCryptoCurrenciesAsObservable().stream() + .filter(withoutBSQAndTopAltcoin()) + .collect(Collectors.toList())); + tradeCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); + + allCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, "")); + allCurrencies.addAll(CurrencyUtil.getAllSortedCryptoCurrencies().stream() + .filter(withoutBSQAndTopAltcoin()) + .collect(Collectors.toList())); + allCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, "")); + } + + @Override + Predicate getCurrencyAndMethodPredicate(OfferDirection direction, + TradeCurrency selectedTradeCurrency) { + return offerBookListItem -> { + Offer offer = offerBookListItem.getOffer(); + // BUY Altcoin is actually SELL Bitcoin + boolean directionResult = offer.getDirection() == direction; + boolean currencyResult = CurrencyUtil.isCryptoCurrency(offer.getCurrencyCode()) && + ((showAllTradeCurrenciesProperty.get() && + !offer.getCurrencyCode().equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode()) && + !offer.getCurrencyCode().equals(BsqOfferBookViewModel.BSQ.getCode())) || + offer.getCurrencyCode().equals(selectedTradeCurrency.getCode())); + boolean paymentMethodResult = showAllPaymentMethods || + offer.getPaymentMethod().equals(selectedPaymentMethod); + boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook(); + return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated; + }; + } + + @Override + String getCurrencyCodeFromPreferences(OfferDirection direction) { + return direction == OfferDirection.BUY ? preferences.getBuyScreenCryptoCurrencyCode() : preferences.getSellScreenCryptoCurrencyCode(); + } + + @NotNull + private Predicate withoutBSQAndTopAltcoin() { + return cryptoCurrency -> + !cryptoCurrency.equals(BsqOfferBookViewModel.BSQ) && + !cryptoCurrency.equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.fxml b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.fxml new file mode 100644 index 0000000000..332e6ecfe8 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.fxml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java new file mode 100644 index 0000000000..076b83cad5 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookView.java @@ -0,0 +1,72 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; +import bisq.desktop.common.view.FxmlView; +import bisq.desktop.main.overlays.windows.BsqSwapOfferDetailsWindow; +import bisq.desktop.main.overlays.windows.OfferDetailsWindow; + +import bisq.core.account.sign.SignedWitnessService; +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.alert.PrivateNotificationManager; +import bisq.core.locale.Res; +import bisq.core.offer.OfferDirection; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; + +import bisq.common.config.Config; + +import javax.inject.Inject; +import javax.inject.Named; + +import javafx.scene.layout.GridPane; + +@FxmlView +public class TopAltcoinOfferBookView extends OfferBookView { + + @Inject + TopAltcoinOfferBookView(TopAltcoinOfferBookViewModel model, + Navigation navigation, + OfferDetailsWindow offerDetailsWindow, + BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, + PrivateNotificationManager privateNotificationManager, + @Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys, + AccountAgeWitnessService accountAgeWitnessService, + SignedWitnessService signedWitnessService) { + super(model, navigation, offerDetailsWindow, bsqSwapOfferDetailsWindow, formatter, privateNotificationManager, useDevPrivilegeKeys, accountAgeWitnessService, signedWitnessService); + } + + @Override + protected String getMarketTitle() { + return model.getDirection().equals(OfferDirection.BUY) ? + Res.get("offerbook.availableOffersToBuy", TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode(), "BTC") : + Res.get("offerbook.availableOffersToSell", TopAltcoinOfferBookViewModel.TOP_ALTCOIN.getCode(), "BTC"); + } + + @Override + protected void activate() { + model.onSetTradeCurrency(TopAltcoinOfferBookViewModel.TOP_ALTCOIN); + + super.activate(); + + currencyComboBoxContainer.setVisible(false); + currencyComboBoxContainer.setManaged(false); + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookViewModel.java new file mode 100644 index 0000000000..6135e59e25 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/TopAltcoinOfferBookViewModel.java @@ -0,0 +1,115 @@ +/* + * 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.offer.offerbook; + +import bisq.desktop.Navigation; + +import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.api.CoreApi; +import bisq.core.btc.setup.WalletsSetup; +import bisq.core.btc.wallet.BsqWalletService; +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.TradeCurrency; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferDirection; +import bisq.core.offer.OfferFilterService; +import bisq.core.offer.OpenOfferManager; +import bisq.core.payment.payload.PaymentMethod; +import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.ClosedTradableManager; +import bisq.core.user.Preferences; +import bisq.core.user.User; +import bisq.core.util.FormattingUtils; +import bisq.core.util.PriceUtil; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; + +import bisq.network.p2p.P2PService; + +import com.google.inject.Inject; + +import javax.inject.Named; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class TopAltcoinOfferBookViewModel extends OfferBookViewModel { + + public static final TradeCurrency TOP_ALTCOIN = CurrencyUtil.getTradeCurrency("XMR").get(); + + @Inject + public TopAltcoinOfferBookViewModel(User user, + OpenOfferManager openOfferManager, + OfferBook offerBook, + Preferences preferences, + WalletsSetup walletsSetup, + P2PService p2PService, + PriceFeedService priceFeedService, + ClosedTradableManager closedTradableManager, + AccountAgeWitnessService accountAgeWitnessService, + Navigation navigation, + PriceUtil priceUtil, + OfferFilterService offerFilterService, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, + BsqFormatter bsqFormatter, + BsqWalletService bsqWalletService, + CoreApi coreApi) { + super(user, openOfferManager, offerBook, preferences, walletsSetup, p2PService, priceFeedService, closedTradableManager, accountAgeWitnessService, navigation, priceUtil, offerFilterService, btcFormatter, bsqFormatter, bsqWalletService, coreApi); + } + + @Override + void saveSelectedCurrencyCodeInPreferences(OfferDirection direction, String code) { + // No need to store anything as it is just one Altcoin offers anyway + } + + @Override + protected ObservableList filterPaymentMethods(ObservableList list, + TradeCurrency selectedTradeCurrency) { + return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isBlockchain).collect(Collectors.toList())); + } + + @Override + void fillCurrencies(ObservableList tradeCurrencies, + ObservableList allCurrencies) { + tradeCurrencies.add(TOP_ALTCOIN); + allCurrencies.add(TOP_ALTCOIN); + } + + @Override + Predicate getCurrencyAndMethodPredicate(OfferDirection direction, + TradeCurrency selectedTradeCurrency) { + return offerBookListItem -> { + Offer offer = offerBookListItem.getOffer(); + // BUY Altcoin is actually SELL Bitcoin + boolean directionResult = offer.getDirection() == direction; + boolean currencyResult = offer.getCurrencyCode().equals(TOP_ALTCOIN.getCode()); + boolean paymentMethodResult = showAllPaymentMethods || + offer.getPaymentMethod().equals(selectedPaymentMethod); + boolean notMyOfferOrShowMyOffersActivated = !isMyOffer(offerBookListItem.getOffer()) || preferences.isShowOwnOffersInOfferBook(); + return directionResult && currencyResult && paymentMethodResult && notMyOfferOrShowMyOffersActivated; + }; + } + + @Override + String getCurrencyCodeFromPreferences(OfferDirection direction) { + return TOP_ALTCOIN.getCode(); + } +} diff --git a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java index cffe57e297..01288ca0f2 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java @@ -238,8 +238,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, null, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); assertEquals(0, model.maxPlacesForAmount.intValue()); } @@ -252,8 +252,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(6, model.maxPlacesForAmount.intValue()); @@ -270,8 +270,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(15, model.maxPlacesForAmount.intValue()); @@ -289,8 +289,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, null, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); assertEquals(0, model.maxPlacesForVolume.intValue()); } @@ -303,8 +303,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(5, model.maxPlacesForVolume.intValue()); @@ -321,8 +321,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(9, model.maxPlacesForVolume.intValue()); @@ -340,8 +340,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, null, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); assertEquals(0, model.maxPlacesForPrice.intValue()); } @@ -354,8 +354,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(7, model.maxPlacesForPrice.intValue()); @@ -372,8 +372,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, null, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); assertEquals(0, model.maxPlacesForMarketPriceMargin.intValue()); } @@ -407,8 +407,8 @@ public class OfferBookViewModelTest { item4.getOffer().setPriceFeedService(priceFeedService); offerBookListItems.addAll(item1, item2); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, priceFeedService, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, priceFeedService, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); model.activate(); assertEquals(8, model.maxPlacesForMarketPriceMargin.intValue()); //" (1.97%)" @@ -428,8 +428,8 @@ public class OfferBookViewModelTest { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); when(priceFeedService.getMarketPrice(anyString())).thenReturn(new MarketPrice("USD", 12684.0450, Instant.now().getEpochSecond(), true)); - final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, - null, null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); + final OfferBookViewModel model = new BtcOfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, null, + null, null, null, getPriceUtil(), null, coinFormatter, new BsqFormatter(), null, null); final OfferBookListItem item = make(btcBuyItem.but( with(useMarketBasedPrice, true), diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 8a63d6a1c1..d5c4e0b3f0 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1952,6 +1952,8 @@ message PreferencesPayload { bool notify_on_pre_release = 61; bool use_full_mode_dao_monitor = 62; int32 clear_data_after_days = 63; + string buy_screen_crypto_currency_code = 64; + string sell_screen_crypto_currency_code = 65; } message AutoConfirmSettings {