Adapt navigational structure and offerbook handling to buy and sell different assets

Still missing correct create and take offer handling
This commit is contained in:
Christoph Atteneder 2022-04-01 10:04:38 +02:00
parent 298806150b
commit 98f355d3fa
No known key found for this signature in database
GPG key ID: CD5DC1C529CDFD3B
27 changed files with 1115 additions and 205 deletions

View file

@ -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<TradeCurrency> 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<String> getAcceptedBanks(PaymentAccount paymentAccount) {
List<String> acceptedBanks = null;

View file

@ -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<String> ignoreTradersList) {
prefPayload.setIgnoreTradersList(ignoreTradersList);
requestPersistence();

View file

@ -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(),

View file

@ -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}

View file

@ -323,6 +323,7 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
};
buyTableRowSelectionListener = (observable, oldValue, newValue) -> {
model.preferences.setSellScreenCurrencyCode(model.getCurrencyCode());
navigation.navigateTo(MainView.class, SellOfferView.class);
};

View file

@ -43,7 +43,6 @@ public class BuyOfferView extends OfferView {
super(viewLoader,
navigation,
preferences,
arbitratorManager,
user,
p2PService,
OfferDirection.BUY);

View file

@ -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<TabPane, Void> {
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<TabPane, Void> {
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<TabPane, Void> {
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<TabPane, Void> {
this.user = user;
this.p2PService = p2PService;
this.direction = direction;
this.arbitratorManager = arbitratorManager;
}
@Override
@ -117,8 +114,30 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
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<TabPane, Void> {
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<TabPane, Void> {
if (takeOfferViewOpen) {
root.getTabs().remove(takeOfferTab);
}
if (canCreateOrTakeOffer(CurrencyUtil.getTradeCurrency(offer.getCurrencyCode()).get())) {
Optional<TradeCurrency> optionalTradeCurrency = CurrencyUtil.getTradeCurrency(offer.getCurrencyCode());
if (optionalTradeCurrency.isPresent() && canCreateOrTakeOffer(optionalTradeCurrency.get())) {
openTakeOffer(offer);
}
}
@ -179,8 +205,8 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
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, Void> {
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<TabPane, Void> {
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<TabPane, Void> {
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<TabPane, Void> {
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 {

View file

@ -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);

View file

@ -1031,7 +1031,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> 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<M extends MutableOfferViewModel<?>> exten
GridPane.setMargin(advancedOptionsBox, new Insets(Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
gridPane.getChildren().add(advancedOptionsBox);
Tuple2<AutoTooltipButton, HBox> buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(
navigation, preferences);
Tuple2<AutoTooltipButton, HBox> buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(navigation);
buyBsqBox = buyBsqButtonBox.second;
buyBsqBox.setManaged(false);
buyBsqBox.setVisible(false);

View file

@ -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<AutoTooltipButton, HBox> createBuyBsqButtonBox(Navigation navigation,
Preferences preferences) {
public static Tuple2<AutoTooltipButton, HBox> 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);
}
}

View file

@ -307,7 +307,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
paymentAccountsComboBox.setItems(model.getPossiblePaymentAccounts());
paymentAccountsComboBox.getSelectionModel().select(lastPaymentAccount);
model.onPaymentAccountSelected(lastPaymentAccount);
paymentAccountTitledGroupBg.setText(Res.get("shared.selectTradingAccount"));
paymentAccountTitledGroupBg.setText(Res.get("Buy BTC with EUR (using SEPA)"));
}
balanceTextField.setTargetAmount(model.dataModel.getTotalToPayAsCoin().get());
@ -882,8 +882,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
GridPane.setMargin(advancedOptionsBox, new Insets(Layout.COMPACT_FIRST_ROW_AND_GROUP_DISTANCE, 0, 0, 0));
gridPane.getChildren().add(advancedOptionsBox);
Tuple2<AutoTooltipButton, HBox> buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(
navigation, model.dataModel.preferences);
Tuple2<AutoTooltipButton, HBox> buyBsqButtonBox = OfferViewUtil.createBuyBsqButtonBox(navigation);
buyBsqBox = buyBsqButtonBox.second;
buyBsqBox.setManaged(false);
buyBsqBox.setVisible(false);

View file

@ -19,7 +19,7 @@
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="bisq.desktop.main.offer.offerbook.OfferBookView"
<GridPane fx:id="root" fx:controller="bisq.desktop.main.offer.offerbook.BsqOfferBookView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<GridPane, BsqOfferBookViewModel> {
@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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<PaymentMethod> filterPaymentMethods(ObservableList<PaymentMethod> list,
TradeCurrency selectedTradeCurrency) {
return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isAltcoin).collect(Collectors.toList()));
}
@Override
void fillCurrencies(ObservableList<TradeCurrency> tradeCurrencies,
ObservableList<TradeCurrency> allCurrencies) {
tradeCurrencies.add(BSQ);
allCurrencies.add(BSQ);
}
@Override
Predicate<OfferBookListItem> 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();
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="bisq.desktop.main.offer.offerbook.BtcOfferBookView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
</GridPane>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<GridPane, BtcOfferBookViewModel> {
@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");
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<PaymentMethod> filterPaymentMethods(ObservableList<PaymentMethod> 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<TradeCurrency> tradeCurrencies,
ObservableList<TradeCurrency> 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<OfferBookListItem> 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();
}
}

View file

@ -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<GridPane, OfferBookViewModel> {
abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewModel> extends ActivatableViewAndModel<R, M> {
private final Navigation navigation;
private final OfferDetailsWindow offerDetailsWindow;
@ -137,7 +130,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private final SignedWitnessService signedWitnessService;
private TitledGroupBg titledGroupBg;
private AutocompleteComboBox<TradeCurrency> currencyComboBox;
protected AutocompleteComboBox<TradeCurrency> currencyComboBox;
private AutocompleteComboBox<PaymentMethod> paymentMethodComboBox;
private AutoTooltipButton createOfferButton;
private AutoTooltipSlideToggleButton matchingOffersToggle;
@ -157,19 +150,19 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private Subscription currencySelectionSubscriber;
private static final int SHOW_ALL = 0;
private Label disabledCreateOfferButtonTooltip;
protected VBox currencyComboBoxContainer;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor, lifecycle
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
OfferBookView(OfferBookViewModel model,
OfferBookView(M model,
Navigation navigation,
OfferDetailsWindow offerDetailsWindow,
BsqSwapOfferDetailsWindow bsqSwapOfferDetailsWindow,
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
CoinFormatter formatter,
PrivateNotificationManager privateNotificationManager,
@Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys,
boolean useDevPrivilegeKeys,
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService) {
super(model);
@ -192,7 +185,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
root,
gridRow,
2,
Res.get("offerbook.availableOffers")
""
);
titledGroupBg.getStyleClass().add("last");
@ -203,6 +196,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
Tuple3<VBox, Label, AutocompleteComboBox<TradeCurrency>> 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<GridPane, OfferBookVi
matchingOffersToggle.setText(Res.get("offerbook.matchingOffers"));
HBox.setMargin(matchingOffersToggle, new Insets(7, 0, -9, -15));
createOfferButton = new AutoTooltipButton();
createOfferButton = new AutoTooltipButton(Res.get("offerbook.createNewOffer"));
createOfferButton.setMinHeight(40);
createOfferButton.setGraphicTextGap(10);
@ -340,8 +334,11 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
priceFeedUpdateCounterListener = (observable, oldValue, newValue) -> 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<GridPane, OfferBookVi
if (currencyComboBox.getEditor().getText().isEmpty())
currencyComboBox.getSelectionModel().select(SHOW_ALL);
model.onSetTradeCurrency(currencyComboBox.getSelectionModel().getSelectedItem());
paymentMethodComboBox.setAutocompleteItems(model.getPaymentMethods());
updatePaymentMethodComboBoxEditor();
});
updateCurrencyComboBoxFromModel();
@ -401,18 +400,13 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
updateSigningStateColumn();
});
if (model.showAllPaymentMethods)
paymentMethodComboBox.getSelectionModel().select(SHOW_ALL);
else
paymentMethodComboBox.getSelectionModel().select(model.selectedPaymentMethod);
paymentMethodComboBox.getEditor().setText(new PaymentMethodStringConverter(paymentMethodComboBox).toString(paymentMethodComboBox.getSelectionModel().getSelectedItem()));
updatePaymentMethodComboBoxEditor();
createOfferButton.setOnAction(e -> onCreateOffer());
MonadicBinding<Void> 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<GridPane, OfferBookVi
model.priceFeedService.updateCounterProperty().addListener(priceFeedUpdateCounterListener);
}
private void updateCurrencyComboBoxFromModel() {
private void updatePaymentMethodComboBoxEditor() {
if (model.showAllPaymentMethods)
paymentMethodComboBox.getSelectionModel().select(SHOW_ALL);
else
paymentMethodComboBox.getSelectionModel().select(model.selectedPaymentMethod);
paymentMethodComboBox.getEditor().setText(new PaymentMethodStringConverter(paymentMethodComboBox).toString(paymentMethodComboBox.getSelectionModel().getSelectedItem()));
}
protected void updateCurrencyComboBoxFromModel() {
if (model.showAllTradeCurrenciesProperty.get()) {
currencyComboBox.getSelectionModel().select(SHOW_ALL);
} else {
@ -588,36 +590,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
iconView.setId(direction == OfferDirection.SELL ? "image-sell-white" : "image-buy-white");
createOfferButton.setId(direction == OfferDirection.SELL ? "sell-button-big" : "buy-button-big");
avatarColumn.setTitle(direction == OfferDirection.SELL ? Res.get("shared.buyerUpperCase") : Res.get("shared.sellerUpperCase"));
setDirectionTitles();
}
private void setDirectionTitles() {
TradeCurrency selectedTradeCurrency = model.getSelectedTradeCurrency();
if (selectedTradeCurrency != null) {
OfferDirection direction = model.getDirection();
String offerButtonText;
String code = selectedTradeCurrency.getCode();
if (model.showAllTradeCurrenciesProperty.get()) {
offerButtonText = direction == OfferDirection.BUY ?
Res.get("offerbook.createOfferToBuy",
Res.getBaseCurrencyCode()) :
Res.get("offerbook.createOfferToSell",
Res.getBaseCurrencyCode());
} else if (selectedTradeCurrency instanceof FiatCurrency) {
offerButtonText = direction == OfferDirection.BUY ?
Res.get("offerbook.createOfferToBuy.withFiat",
Res.getBaseCurrencyCode(), code) :
Res.get("offerbook.createOfferToSell.forFiat", Res.getBaseCurrencyCode(), code);
} else {
offerButtonText = direction == OfferDirection.BUY ?
Res.get("offerbook.createOfferToBuy.withCrypto",
code, Res.getBaseCurrencyCode()) :
Res.get("offerbook.createOfferToSell.forCrypto", code, Res.getBaseCurrencyCode());
}
createOfferButton.updateText(offerButtonText);
}
}
public void setOfferActionHandler(OfferView.OfferActionHandler offerActionHandler) {
@ -1181,19 +1153,11 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
button2.setManaged(true);
button2.setVisible(true);
} else {
boolean isSellOffer = offer.getDirection() == OfferDirection.SELL;
boolean isSellOffer = OfferViewUtil.isShownAsSellOffer(offer);
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");
button.setId(isSellOffer ? "buy-button" : "sell-button");
button.setStyle("-fx-text-fill: white");
if (isSellOffer) {
title = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ?
Res.get("offerbook.takeOfferToBuy", offer.getBaseCurrencyCode()) :
Res.get("offerbook.takeOfferToSell", offer.getCurrencyCode());
} else {
title = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ?
Res.get("offerbook.takeOfferToSell", offer.getBaseCurrencyCode()) :
Res.get("offerbook.takeOfferToBuy", offer.getCurrencyCode());
}
title = Res.get("offerbook.takeOffer");
button.setTooltip(new Tooltip(Res.get("offerbook.takeOfferButton.tooltip", model.getDirectionLabelTooltip(offer))));
button.setOnAction(e -> onTakeOffer(offer));
button2.setManaged(false);

View file

@ -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<PaymentMethod> filterPaymentMethods(ObservableList<PaymentMethod> 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<TradeCurrency> tradeCurrencies,
ObservableList<TradeCurrency> allCurrencies);
///////////////////////////////////////////////////////////////////////////////////////////
// Checks
@ -594,23 +588,13 @@ class OfferBookViewModel extends ActivatableViewModel {
private void filterOffers() {
Predicate<OfferBookListItem> predicate = useOffersMatchingMyAccountsFilter ?
getCurrencyAndMethodPredicate().and(getOffersMatchingMyAccountsPredicate()) :
getCurrencyAndMethodPredicate();
getCurrencyAndMethodPredicate(direction, selectedTradeCurrency).and(getOffersMatchingMyAccountsPredicate()) :
getCurrencyAndMethodPredicate(direction, selectedTradeCurrency);
filteredItems.setPredicate(predicate);
}
private Predicate<OfferBookListItem> 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<OfferBookListItem> getCurrencyAndMethodPredicate(OfferDirection direction,
TradeCurrency selectedTradeCurrency);
private Predicate<OfferBookListItem> 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);
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="bisq.desktop.main.offer.offerbook.OtherOfferBookView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
</GridPane>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<GridPane, OtherOfferBookViewModel> {
@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");
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<PaymentMethod> filterPaymentMethods(ObservableList<PaymentMethod> list,
TradeCurrency selectedTradeCurrency) {
return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isBlockchain).collect(Collectors.toList()));
}
@Override
void fillCurrencies(ObservableList<TradeCurrency> tradeCurrencies,
ObservableList<TradeCurrency> 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<OfferBookListItem> 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<CryptoCurrency> withoutBSQAndTopAltcoin() {
return cryptoCurrency ->
!cryptoCurrency.equals(BsqOfferBookViewModel.BSQ) &&
!cryptoCurrency.equals(TopAltcoinOfferBookViewModel.TOP_ALTCOIN);
}
}

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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 <http://www.gnu.org/licenses/>.
-->
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="bisq.desktop.main.offer.offerbook.TopAltcoinOfferBookView"
hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml">
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
</GridPane>

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<GridPane, TopAltcoinOfferBookViewModel> {
@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);
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<PaymentMethod> filterPaymentMethods(ObservableList<PaymentMethod> list,
TradeCurrency selectedTradeCurrency) {
return FXCollections.observableArrayList(list.stream().filter(PaymentMethod::isBlockchain).collect(Collectors.toList()));
}
@Override
void fillCurrencies(ObservableList<TradeCurrency> tradeCurrencies,
ObservableList<TradeCurrency> allCurrencies) {
tradeCurrencies.add(TOP_ALTCOIN);
allCurrencies.add(TOP_ALTCOIN);
}
@Override
Predicate<OfferBookListItem> 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();
}
}

View file

@ -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),

View file

@ -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 {