diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/components/table/BisqTableView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/components/table/BisqTableView.java index bc473d93cf..e36d90ceaf 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/components/table/BisqTableView.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/components/table/BisqTableView.java @@ -218,6 +218,7 @@ protected void updateItem(T item, boolean empty) { selectedPin.unsubscribe(); selectedPin = null; } + setId(null); } } }; diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/components/AmountComponent.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/components/AmountComponent.java index f1c7929069..845be0c131 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/components/AmountComponent.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/components/AmountComponent.java @@ -427,7 +427,7 @@ private void applySliderTrackStyle() { maxRangeMonetary != null) { double repAmount = reputationBasedQuoteSideAmount.getValue() - minRangeMonetary.getValue(); double range = model.getMaxRangeMonetary().get().getValue() - minRangeMonetary.getValue(); - double reputationBasedAmountOnSlider = repAmount / range; + double reputationBasedAmountOnSlider = range != 0 ? repAmount / range : 0; String rightSideColor = "-bisq-dark-grey-50"; model.getSliderTrackStyle().set(String.format( "-track-color: linear-gradient(to right, " + diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/TakeOfferController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/TakeOfferController.java index ad27e8ef0e..7184191eb0 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/TakeOfferController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/TakeOfferController.java @@ -54,11 +54,11 @@ public class TakeOfferController extends NavigationController implements InitWit @ToString public static class InitData { private final BisqEasyOffer bisqEasyOffer; - private final Optional takerAsSellersMaxAllowedAmount; + private final Optional reputationBasedQuoteSideAmount; - public InitData(BisqEasyOffer bisqEasyOffer, Optional takerAsSellersMaxAllowedAmount) { + public InitData(BisqEasyOffer bisqEasyOffer, Optional reputationBasedQuoteSideAmount) { this.bisqEasyOffer = bisqEasyOffer; - this.takerAsSellersMaxAllowedAmount = takerAsSellersMaxAllowedAmount; + this.reputationBasedQuoteSideAmount = reputationBasedQuoteSideAmount; } } @@ -94,7 +94,7 @@ public boolean useCaching() { @Override public void initWithData(InitData initData) { BisqEasyOffer bisqEasyOffer = initData.getBisqEasyOffer(); - takeOfferAmountController.init(bisqEasyOffer,initData.getTakerAsSellersMaxAllowedAmount()); + takeOfferAmountController.init(bisqEasyOffer, initData.getReputationBasedQuoteSideAmount()); takeOfferPaymentController.init(bisqEasyOffer); takeOfferReviewController.init(bisqEasyOffer); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountController.java index 9d2d2c9704..835eb58dda 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountController.java @@ -20,16 +20,14 @@ import bisq.bisq_easy.BisqEasyTradeAmountLimits; import bisq.bonded_roles.market_price.MarketPriceService; import bisq.common.currency.Market; -import bisq.common.currency.MarketRepository; -import bisq.common.monetary.Fiat; import bisq.common.monetary.Monetary; import bisq.desktop.ServiceProvider; import bisq.desktop.common.Browser; +import bisq.desktop.common.utils.KeyHandlerUtil; import bisq.desktop.common.view.Controller; import bisq.desktop.main.content.bisq_easy.components.AmountComponent; import bisq.i18n.Res; import bisq.offer.Direction; -import bisq.offer.amount.OfferAmountFormatter; import bisq.offer.amount.OfferAmountUtil; import bisq.offer.bisq_easy.BisqEasyOffer; import bisq.offer.price.PriceUtil; @@ -43,7 +41,6 @@ import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; -import java.util.Map; import java.util.Optional; @Slf4j @@ -66,7 +63,7 @@ public TakeOfferAmountController(ServiceProvider serviceProvider) { view = new TakeOfferAmountView(model, this, amountComponent.getView().getRoot()); } - public void init(BisqEasyOffer bisqEasyOffer, Optional takerAsSellersMaxAllowedAmount) { + public void init(BisqEasyOffer bisqEasyOffer, Optional optionalReputationBasedQuoteSideAmount) { model.setBisqEasyOffer(bisqEasyOffer); Direction takersDirection = bisqEasyOffer.getTakersDirection(); @@ -78,42 +75,41 @@ public void init(BisqEasyOffer bisqEasyOffer, Optional takerAsSellersM PriceUtil.findQuote(marketPriceService, bisqEasyOffer.getPriceSpec(), bisqEasyOffer.getMarket()) .ifPresent(amountComponent::setQuote); - Optional optionalQuoteSideMinOrFixedAmount = OfferAmountUtil.findQuoteSideMinOrFixedAmount(marketPriceService, bisqEasyOffer); - Optional optionalQuoteSideMaxOrFixedAmount = OfferAmountUtil.findQuoteSideMaxOrFixedAmount(marketPriceService, bisqEasyOffer); - - if (optionalQuoteSideMinOrFixedAmount.isPresent() && takerAsSellersMaxAllowedAmount.isPresent()) { - //todo - Monetary maxAmount = takerAsSellersMaxAllowedAmount.get().round(0); - Monetary reputationBasedQuoteSideAmount = takerAsSellersMaxAllowedAmount.get().round(0); - Monetary quoteSideMinOrFixedAmount = optionalQuoteSideMinOrFixedAmount.get().round(0); - amountComponent.setReputationBasedQuoteSideAmount(reputationBasedQuoteSideAmount); - applyQuoteSideMinMaxRange(quoteSideMinOrFixedAmount, maxAmount); - - long sellersScore = reputationService.getReputationScore(userIdentityService.getSelectedUserIdentity().getUserProfile()).getTotalScore(); - amountComponent.setDescription(Res.get("bisqEasy.takeOffer.amount.description.limitedByTakersReputation", - sellersScore, - OfferAmountFormatter.formatQuoteSideMinAmount(marketPriceService, bisqEasyOffer, false), - AmountFormatter.formatAmountWithCode(maxAmount))); - } else if (optionalQuoteSideMinOrFixedAmount.isPresent() && optionalQuoteSideMaxOrFixedAmount.isPresent()) { - //todo - Monetary maxAmount = optionalQuoteSideMaxOrFixedAmount.get().round(0); - Monetary reputationBasedQuoteSideAmount = optionalQuoteSideMaxOrFixedAmount.get(); - Monetary quoteSideMinOrFixedAmount = optionalQuoteSideMinOrFixedAmount.get().round(0); - applyQuoteSideMinMaxRange(quoteSideMinOrFixedAmount, maxAmount); - - amountComponent.setDescription(Res.get("bisqEasy.takeOffer.amount.description", - OfferAmountFormatter.formatQuoteSideMinAmount(marketPriceService, bisqEasyOffer, false), - AmountFormatter.formatAmountWithCode(maxAmount))); - } else { - log.error("optionalQuoteSideMinOrFixedAmount or optionalQuoteSideMaxOrFixedAmount is not present"); + Optional OptionalQuoteSideMinAmount = OfferAmountUtil.findQuoteSideMinAmount(marketPriceService, bisqEasyOffer); + if (OptionalQuoteSideMinAmount.isPresent()) { + Monetary quoteSideMinAmount = OptionalQuoteSideMinAmount.get().round(0); + Monetary offersQuoteSideMaxOrFixedAmount = OfferAmountUtil.findQuoteSideMaxOrFixedAmount(marketPriceService, bisqEasyOffer).orElseThrow().round(0); + String formattedMinAmount = AmountFormatter.formatAmount(quoteSideMinAmount); + Monetary maxAmount; + if (optionalReputationBasedQuoteSideAmount.isPresent()) { + // Range amounts seller case with provided reputationBasedQuoteSideAmount + Monetary reputationBasedQuoteSideAmount = optionalReputationBasedQuoteSideAmount.get(); + maxAmount = reputationBasedQuoteSideAmount.isGreaterThan(offersQuoteSideMaxOrFixedAmount) + ? offersQuoteSideMaxOrFixedAmount + : reputationBasedQuoteSideAmount; + amountComponent.setReputationBasedQuoteSideAmount(maxAmount); + applyQuoteSideMinMaxRange(quoteSideMinAmount, maxAmount); + + long sellersScore = reputationService.getReputationScore(userIdentityService.getSelectedUserIdentity().getUserProfile()).getTotalScore(); + amountComponent.setDescription(Res.get("bisqEasy.takeOffer.amount.description.limitedByTakersReputation", + sellersScore, + formattedMinAmount, + AmountFormatter.formatAmountWithCode(maxAmount))); + } else { + // Range amounts buyer case + maxAmount = offersQuoteSideMaxOrFixedAmount; + applyQuoteSideMinMaxRange(quoteSideMinAmount, maxAmount); + amountComponent.setDescription(Res.get("bisqEasy.takeOffer.amount.description", + formattedMinAmount, + AmountFormatter.formatAmountWithCode(maxAmount))); + } + String btcAmount = takersDirection.isBuy() + ? Res.get("bisqEasy.component.amount.baseSide.tooltip.buyer.btcAmount") + : Res.get("bisqEasy.component.amount.baseSide.tooltip.seller.btcAmount"); + Optional priceQuoteOptional = PriceUtil.findQuote(marketPriceService, model.getBisqEasyOffer()) + .map(priceQuote -> "\n" + Res.get("bisqEasy.component.amount.baseSide.tooltip.taker.offerPrice", PriceFormatter.formatWithCode(priceQuote))); + priceQuoteOptional.ifPresent(priceQuote -> amountComponent.setTooltip(String.format("%s%s", btcAmount, priceQuote))); } - - String btcAmount = takersDirection.isBuy() - ? Res.get("bisqEasy.component.amount.baseSide.tooltip.buyer.btcAmount") - : Res.get("bisqEasy.component.amount.baseSide.tooltip.seller.btcAmount"); - Optional priceQuoteOptional = PriceUtil.findQuote(marketPriceService, model.getBisqEasyOffer()) - .map(priceQuote -> "\n" + Res.get("bisqEasy.component.amount.baseSide.tooltip.taker.offerPrice", PriceFormatter.formatWithCode(priceQuote))); - priceQuoteOptional.ifPresent(priceQuote -> amountComponent.setTooltip(String.format("%s%s", btcAmount, priceQuote))); } public ReadOnlyObjectProperty getTakersQuoteSideAmount() { @@ -141,20 +137,28 @@ public void onActivate() { public void onDeactivate() { baseSideAmountPin.unsubscribe(); quoteSideAmountPin.unsubscribe(); + view.getRoot().setOnKeyPressed(null); model.getIsWarningIconVisible().set(false); model.getIsAmountLimitInfoOverlayVisible().set(false); + model.setSellersReputationBasedQuoteSideAmount(null); } void onSetReputationBasedAmount() { - amountComponent.setQuoteSideAmount(amountComponent.getReputationBasedQuoteSideAmount()); + amountComponent.setQuoteSideAmount(amountComponent.getReputationBasedQuoteSideAmount().round(0)); } void onShowAmountLimitInfoOverlay() { model.getIsAmountLimitInfoOverlayVisible().set(true); + view.getRoot().setOnKeyPressed(keyEvent -> { + KeyHandlerUtil.handleEnterKeyEvent(keyEvent, () -> { + }); + KeyHandlerUtil.handleEscapeKeyEvent(keyEvent, this::onCloseAmountLimitInfoOverlay); + }); } void onCloseAmountLimitInfoOverlay() { model.getIsAmountLimitInfoOverlayVisible().set(false); + view.getRoot().setOnKeyPressed(null); } void onOpenWiki(String url) { @@ -170,12 +174,20 @@ private void applyQuoteSideMinMaxRange(Monetary minRangeValue, Monetary maxRange model.setLinkToWikiText(Res.get("bisqEasy.takeOffer.amount.buyer.limitInfo.overlay.linkToWikiText")); model.getAmountLimitInfoAmount().set(""); - long sellersReputationScore = reputationService.getReputationScore(bisqEasyOffer.getMakersUserProfileId()).getTotalScore(); - Monetary reputationBasedQuoteSideAmount = BisqEasyTradeAmountLimits.getMaxQuoteSideTradeAmount(marketPriceService, bisqEasyOffer.getMarket(), sellersReputationScore) - .orElse(Fiat.fromFaceValue(0, "USD")).round(0); + if (model.getSellersReputationBasedQuoteSideAmount() == null) { + long sellersReputationScore = reputationService.getReputationScore(bisqEasyOffer.getMakersUserProfileId()).getTotalScore(); + model.setSellersReputationScore(sellersReputationScore); + Monetary reputationBasedQuoteSideAmount = BisqEasyTradeAmountLimits.getReputationBasedQuoteSideAmount(marketPriceService, bisqEasyOffer.getMarket(), sellersReputationScore) + .orElseThrow().round(0); + model.setSellersReputationBasedQuoteSideAmount(reputationBasedQuoteSideAmount); + } + long sellersReputationScore = model.getSellersReputationScore(); + Monetary reputationBasedQuoteSideAmount = model.getSellersReputationBasedQuoteSideAmount(); + if (reputationBasedQuoteSideAmount.isLessThan(maxRangeValue)) { model.getIsAmountLimitInfoVisible().set(true); amountComponent.setReputationBasedQuoteSideAmount(reputationBasedQuoteSideAmount); + amountComponent.setQuoteSideAmount(reputationBasedQuoteSideAmount); String formattedAmount = AmountFormatter.formatAmountWithCode(reputationBasedQuoteSideAmount); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.takeOffer.amount.buyer.limitInfo.overlay.info", sellersReputationScore, formattedAmount) + "\n\n"); if (reputationBasedQuoteSideAmount.isLessThan(minRangeValue)) { @@ -194,10 +206,11 @@ private void applyQuoteSideMinMaxRange(Monetary minRangeValue, Monetary maxRange model.setLinkToWikiText(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfo.overlay.linkToWikiText")); String myProfileId = userIdentityService.getSelectedUserIdentity().getUserProfile().getId(); long myReputationScore = reputationService.getReputationScore(myProfileId).getTotalScore(); - BisqEasyTradeAmountLimits.getMaxQuoteSideTradeAmount(marketPriceService, bisqEasyOffer.getMarket(), myReputationScore) - .ifPresent(reputationBasedQuoteSideAmount -> { - amountComponent.setReputationBasedQuoteSideAmount(reputationBasedQuoteSideAmount); - String formattedAmount = AmountFormatter.formatAmountWithCode(reputationBasedQuoteSideAmount); + BisqEasyTradeAmountLimits.getReputationBasedQuoteSideAmount(marketPriceService, bisqEasyOffer.getMarket(), myReputationScore) + .ifPresent(myReputationBasedQuoteSideAmount -> { + model.getIsAmountHyperLinkDisabled().set(myReputationBasedQuoteSideAmount.isGreaterThan(maxRangeValue)); + amountComponent.setReputationBasedQuoteSideAmount(myReputationBasedQuoteSideAmount); + String formattedAmount = AmountFormatter.formatAmountWithCode(myReputationBasedQuoteSideAmount); model.getIsAmountLimitInfoVisible().set(true); model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfo", myReputationScore)); model.getAmountLimitInfoAmount().set(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfoAmount", formattedAmount)); @@ -209,38 +222,13 @@ private void applyQuoteSideMinMaxRange(Monetary minRangeValue, Monetary maxRange } private void applyReputationBasedQuoteSideAmount() { - // Reduce by 1 USD to avoid rounding issues, but use at least 25 USD (MAX_USD_TRADE_AMOUNT_WITHOUT_REPUTATION) - long value = amountComponent.getReputationBasedQuoteSideAmount().getValue() - 10000; - value = Math.max(BisqEasyTradeAmountLimits.MAX_USD_TRADE_AMOUNT_WITHOUT_REPUTATION.getValue(), value); - amountComponent.setQuoteSideAmount(Fiat.fromValue(value, "USD")); + amountComponent.setQuoteSideAmount(amountComponent.getReputationBasedQuoteSideAmount().round(0)); } private void maxOrFixedQuoteSideAmountChanged(Monetary value) { if (amountComponent.getReputationBasedQuoteSideAmount() == null) { return; } - double reputationBasedAmountFaceValue = Monetary.valueToFaceValue(amountComponent.getReputationBasedQuoteSideAmount(), 0); - double faceValue = Monetary.valueToFaceValue(value, 0); - model.getIsWarningIconVisible().set(faceValue > reputationBasedAmountFaceValue); - - long highestScore = reputationService.getScoreByUserProfileId().entrySet().stream() - .filter(e -> userIdentityService.findUserIdentity(e.getKey()).isEmpty()) - .mapToLong(Map.Entry::getValue) - .max() - .orElse(0L); - /* Monetary highestPossibleUsdAmount = BisqEasyTradeAmountLimits.getUsdAmountFromReputationScore(highestScore); - // We reduce by 1 USD to avoid rounding issues - Fiat oneUsd = Fiat.fromFaceValue(1d, "USD"); - highestPossibleUsdAmount = Monetary.from(highestPossibleUsdAmount, highestPossibleUsdAmount.getValue() - oneUsd.getValue());*/ - Market usdBitcoinMarket = MarketRepository.getUSDBitcoinMarket(); - long requiredReputationScore = BisqEasyTradeAmountLimits.findRequiredReputationScoreByFiatAmount(marketPriceService, usdBitcoinMarket, value).orElse(0L); - long numPotentialTakers = reputationService.getScoreByUserProfileId().entrySet().stream() - .filter(e -> userIdentityService.findUserIdentity(e.getKey()).isEmpty()) - .filter(e -> e.getValue() >= requiredReputationScore || requiredReputationScore <= BisqEasyTradeAmountLimits.MIN_REPUTAION_SCORE) - .count(); - if (model.getBisqEasyOffer().getTakersDirection().isBuy()) { - // model.getAmountLimitInfoLeft().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfoLeft", numPotentialTakers, AmountFormatter.formatAmountWithCode(value))); - // model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.info", AmountFormatter.formatAmountWithCode(value), requiredReputationScore)); - } + model.getIsWarningIconVisible().set(value.round(0).getValue() > amountComponent.getReputationBasedQuoteSideAmount().round(0).getValue()); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountModel.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountModel.java index 4287d2bea6..2cab679d74 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountModel.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountModel.java @@ -34,9 +34,14 @@ public class TakeOfferAmountModel implements Model { private final StringProperty amountLimitInfoAmount = new SimpleStringProperty(); private final StringProperty amountLimitInfoOverlayInfo = new SimpleStringProperty(); private final BooleanProperty isWarningIconVisible = new SimpleBooleanProperty(); + private final BooleanProperty isAmountHyperLinkDisabled = new SimpleBooleanProperty(); private final BooleanProperty isAmountLimitInfoOverlayVisible = new SimpleBooleanProperty(); private final BooleanProperty isAmountLimitInfoVisible = new SimpleBooleanProperty(); @Setter + private Monetary sellersReputationBasedQuoteSideAmount; + @Setter + private long sellersReputationScore; + @Setter private String amountLimitInfoLink; @Setter private String linkToWikiText; diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountView.java index 974224d41c..7ebd04d8c7 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountView.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/take_offer/amount/TakeOfferAmountView.java @@ -102,6 +102,7 @@ protected void onViewAttached() { amountLimitInfo.textProperty().bind(model.getAmountLimitInfo()); amountLimitInfoAmount.textProperty().bind(model.getAmountLimitInfoAmount()); amountLimitInfoOverlayInfo.textProperty().bind(model.getAmountLimitInfoOverlayInfo()); + amountLimitInfoAmount.disableProperty().bind(model.getIsAmountHyperLinkDisabled()); amountLimitInfoAmount.managedProperty().bind(model.getIsAmountLimitInfoVisible().and(model.getAmountLimitInfoAmount().isEmpty().not())); amountLimitInfoAmount.visibleProperty().bind(amountLimitInfoAmount.managedProperty()); @@ -136,6 +137,8 @@ protected void onViewDetached() { amountLimitInfo.textProperty().unbind(); amountLimitInfoAmount.textProperty().unbind(); amountLimitInfoOverlayInfo.textProperty().unbind(); + amountLimitInfoAmount.disableProperty().unbind(); + amountLimitInfoAmount.managedProperty().unbind(); amountLimitInfoAmount.visibleProperty().unbind(); showOverlayHyperLink.managedProperty().unbind(); diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/amount/TradeWizardAmountController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/amount/TradeWizardAmountController.java index fb4f08f8ad..151da357a6 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/amount/TradeWizardAmountController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/amount/TradeWizardAmountController.java @@ -32,6 +32,7 @@ import bisq.desktop.ServiceProvider; import bisq.desktop.common.Browser; import bisq.desktop.common.threading.UIThread; +import bisq.desktop.common.utils.KeyHandlerUtil; import bisq.desktop.common.view.Controller; import bisq.desktop.components.overlay.Popup; import bisq.desktop.main.content.bisq_easy.components.AmountComponent; @@ -346,6 +347,7 @@ public void onDeactivate() { minAmountCompBaseSideAmountPin.unsubscribe(); minAmountCompQuoteSideAmountPin.unsubscribe(); priceTooltipPin.unsubscribe(); + view.getRoot().setOnKeyPressed(null); model.getIsAmountLimitInfoOverlayVisible().set(false); } @@ -355,9 +357,15 @@ void onSetReputationBasedAmount() { void onShowAmountLimitInfoOverlay() { model.getIsAmountLimitInfoOverlayVisible().set(true); + view.getRoot().setOnKeyPressed(keyEvent -> { + KeyHandlerUtil.handleEnterKeyEvent(keyEvent, () -> { + }); + KeyHandlerUtil.handleEscapeKeyEvent(keyEvent, this::onCloseAmountLimitInfoOverlay); + }); } void onCloseAmountLimitInfoOverlay() { + view.getRoot().setOnKeyPressed(null); model.getIsAmountLimitInfoOverlayVisible().set(false); } @@ -520,9 +528,9 @@ private Optional getMarketPriceQuote() { } private void quoteSideAmountsChanged(boolean maxAmountChanged) { - Monetary minQuoteSideAmount = minAmountComponent.getQuoteSideAmount().get().round(0); - Monetary maxOrFixedQuoteSideAmount = maxOrFixAmountComponent.getQuoteSideAmount().get().round(0); - boolean insecureValue = maxOrFixedQuoteSideAmount.isGreaterThan(maxOrFixAmountComponent.getReputationBasedQuoteSideAmount().round(0)); + Monetary minQuoteSideAmount = minAmountComponent.getQuoteSideAmount().get(); + Monetary maxOrFixedQuoteSideAmount = maxOrFixAmountComponent.getQuoteSideAmount().get(); + boolean insecureValue = maxOrFixedQuoteSideAmount.isGreaterThan(maxOrFixAmountComponent.getReputationBasedQuoteSideAmount()); model.getIsWarningIconVisible().set(insecureValue); long highestScore = reputationService.getScoreByUserProfileId().entrySet().stream() @@ -543,8 +551,7 @@ private void quoteSideAmountsChanged(boolean maxAmountChanged) { .count(); model.getAmountLimitInfoLeadLine().set(null); Monetary amountWithoutReputationNeeded = BisqEasyTradeAmountLimits.usdToFiat(marketPriceService, model.getMarket(), MAX_USD_TRADE_AMOUNT_WITHOUT_REPUTATION) - .orElseThrow() - .round(0); + .orElseThrow(); boolean noReputationNeededForMaxOrFixedAmount = maxOrFixedQuoteSideAmount.isLessThanOrEqual(amountWithoutReputationNeeded); if (model.getDirection().isBuy()) { String formattedAmountWithoutReputationNeeded = formatAmountWithCode(amountWithoutReputationNeeded); @@ -561,18 +568,21 @@ private void quoteSideAmountsChanged(boolean maxAmountChanged) { // min < 25 USD, max > 25 USD model.getAmountLimitInfoLeadLine().set(Res.get("bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo.leadLine", formattedAmountWithoutReputationNeeded)); + String numSellers = Res.get("bisqEasy.tradeWizard.amount.buyer.numSellers." + Math.min(numPotentialTakersForMaxOrFixedAmount, 2), numPotentialTakersForMaxOrFixedAmount); model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo", - formattedMaxOrFixedAmount, numPotentialTakersForMaxOrFixedAmount)); + formattedMaxOrFixedAmount, numSellers)); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo.overlay.info", formattedMinAmount, formattedAmountWithoutReputationNeeded, formattedMaxOrFixedAmount, requiredReputationScoreForMaxOrFixedAmount) + "\n\n"); } else { // min > 25 USD model.getIsWarningIconVisible().set(numPotentialTakersForMaxOrFixedAmount == 0); if (maxAmountChanged) { - model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numPotentialTakersForMaxOrFixedAmount, formattedMaxOrFixedAmount)); + String numSellers = Res.get("bisqEasy.tradeWizard.amount.buyer.numSellers." + Math.min(numPotentialTakersForMaxOrFixedAmount, 2), numPotentialTakersForMaxOrFixedAmount); + model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numSellers, formattedMaxOrFixedAmount)); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.info", formattedMaxOrFixedAmount, requiredReputationScoreForMaxOrFixedAmount) + "\n\n"); } else { - model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numPotentialTakersForMinAmount, formattedMinAmount)); + String numSellers = Res.get("bisqEasy.tradeWizard.amount.buyer.numSellers." + Math.min(numPotentialTakersForMinAmount, 2), numPotentialTakersForMinAmount); + model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numSellers, formattedMinAmount)); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.info", formattedMinAmount, requiredReputationScoreForMinAmount) + "\n\n"); } } @@ -584,7 +594,8 @@ private void quoteSideAmountsChanged(boolean maxAmountChanged) { model.getIsWarningIconVisible().set(true); } else { // min > 25 USD - model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numPotentialTakersForMaxOrFixedAmount, formattedMaxOrFixedAmount)); + String numSellers = Res.get("bisqEasy.tradeWizard.amount.buyer.numSellers." + Math.min(numPotentialTakersForMaxOrFixedAmount, 2), numPotentialTakersForMaxOrFixedAmount); + model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo", numSellers, formattedMaxOrFixedAmount)); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.info", formattedMaxOrFixedAmount, requiredReputationScoreForMaxOrFixedAmount) + "\n\n"); model.getIsWarningIconVisible().set(numPotentialTakersForMaxOrFixedAmount == 0); } @@ -592,11 +603,11 @@ private void quoteSideAmountsChanged(boolean maxAmountChanged) { } else { long myReputationScore = model.getMyReputationScore(); String formattedReputationBasedMaxAmount = formatAmountWithCode(model.getReputationBasedMaxAmount()); + String formattedAmountWithoutReputationNeeded = formatAmountWithCode(amountWithoutReputationNeeded); if (noReputationNeededForMaxOrFixedAmount) { - String formattedAmountWithoutReputationNeeded = formatAmountWithCode(amountWithoutReputationNeeded); model.getAmountLimitInfoAmount().set(""); model.getAmountLimitInfoOverlayInfo().set(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfo.noReputationNeededForMaxOrFixedAmount.overlay.info", - myReputationScore, formattedReputationBasedMaxAmount)); + formattedAmountWithoutReputationNeeded, myReputationScore, formattedReputationBasedMaxAmount)); model.getAmountLimitInfo().set(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfo.noReputationNeededForMaxOrFixedAmount", formattedAmountWithoutReputationNeeded)); } else { model.getAmountLimitInfoAmount().set(Res.get("bisqEasy.tradeWizard.amount.seller.limitInfoAmount", formattedReputationBasedMaxAmount)); @@ -607,16 +618,18 @@ private void quoteSideAmountsChanged(boolean maxAmountChanged) { } private void applyQuoteSideMinMaxRange() { - Monetary maxRangeValue = BisqEasyTradeAmountLimits.usdToFiat(marketPriceService, model.getMarket(), BisqEasyTradeAmountLimits.MAX_USD_TRADE_AMOUNT).orElseThrow().round(0); - Monetary minRangeValue = BisqEasyTradeAmountLimits.usdToFiat(marketPriceService, model.getMarket(), BisqEasyTradeAmountLimits.DEFAULT_MIN_USD_TRADE_AMOUNT).orElseThrow().round(0); + Monetary maxRangeValue = BisqEasyTradeAmountLimits.usdToFiat(marketPriceService, model.getMarket(), BisqEasyTradeAmountLimits.MAX_USD_TRADE_AMOUNT) + .orElseThrow().round(0); + Monetary minRangeValue = BisqEasyTradeAmountLimits.usdToFiat(marketPriceService, model.getMarket(), BisqEasyTradeAmountLimits.DEFAULT_MIN_USD_TRADE_AMOUNT) + .orElseThrow().round(0); if (model.getReputationBasedMaxAmount() == null) { String myProfileId = userIdentityService.getSelectedUserIdentity().getUserProfile().getId(); long myReputationScore = reputationService.getReputationScore(myProfileId).getTotalScore(); model.setMyReputationScore(myReputationScore); - model.setReputationBasedMaxAmount(BisqEasyTradeAmountLimits.getMaxQuoteSideTradeAmount(marketPriceService, model.getMarket(), myReputationScore) + model.setReputationBasedMaxAmount(BisqEasyTradeAmountLimits.getReputationBasedQuoteSideAmount(marketPriceService, model.getMarket(), myReputationScore) .orElse(Fiat.fromValue(0, model.getMarket().getQuoteCurrencyCode())) - .round(0)); + ); } minAmountComponent.setMinMaxRange(minRangeValue, maxRangeValue); @@ -664,6 +677,6 @@ private void applyQuoteSideMinMaxRange() { } private void applyReputationBasedQuoteSideAmount() { - maxOrFixAmountComponent.setQuoteSideAmount( maxOrFixAmountComponent.getReputationBasedQuoteSideAmount().round(0)); + maxOrFixAmountComponent.setQuoteSideAmount(maxOrFixAmountComponent.getReputationBasedQuoteSideAmount()); } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/direction/TradeWizardDirectionController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/direction/TradeWizardDirectionController.java index c063f697bd..00ae2a4ffb 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/direction/TradeWizardDirectionController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/direction/TradeWizardDirectionController.java @@ -19,6 +19,7 @@ import bisq.bisq_easy.NavigationTarget; import bisq.desktop.ServiceProvider; +import bisq.desktop.common.utils.KeyHandlerUtil; import bisq.desktop.common.view.Controller; import bisq.offer.Direction; import bisq.user.identity.UserIdentityService; @@ -73,6 +74,7 @@ public void onActivate() { @Override public void onDeactivate() { + view.getRoot().setOnKeyPressed(null); } void onSelectDirection(Direction direction) { @@ -112,6 +114,13 @@ private void applyShowReputationInfo() { if (!reputationScore.hasReputation()) { navigationButtonsVisibleHandler.accept(false); model.getShowReputationInfo().set(true); + view.getRoot().setOnKeyPressed(keyEvent -> { + KeyHandlerUtil.handleEnterKeyEvent(keyEvent, () -> { + }); + KeyHandlerUtil.handleEscapeKeyEvent(keyEvent, this::onCloseReputationInfo); + }); + } else { + view.getRoot().setOnKeyPressed(null); } } } diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/price/TradeWizardPriceController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/price/TradeWizardPriceController.java index f33ccffa6b..ff58754257 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/price/TradeWizardPriceController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/price/TradeWizardPriceController.java @@ -21,6 +21,7 @@ import bisq.common.currency.Market; import bisq.common.monetary.PriceQuote; import bisq.desktop.ServiceProvider; +import bisq.desktop.common.utils.KeyHandlerUtil; import bisq.desktop.common.view.Controller; import bisq.desktop.components.overlay.Popup; import bisq.desktop.main.content.bisq_easy.components.PriceInput; @@ -138,6 +139,7 @@ public void onDeactivate() { isPriceInvalidPin.unsubscribe(); priceSpecPin.unsubscribe(); percentageInputPin.unsubscribe(); + view.getRoot().setOnKeyPressed(null); } void onPercentageFocussed(boolean focussed) { @@ -222,10 +224,16 @@ void usePercentagePrice() { void showLearnWhySection() { model.getShouldShowLearnWhyOverlay().set(true); + view.getRoot().setOnKeyPressed(keyEvent -> { + KeyHandlerUtil.handleEnterKeyEvent(keyEvent, () -> { + }); + KeyHandlerUtil.handleEscapeKeyEvent(keyEvent, this::closeLearnWhySection); + }); } void closeLearnWhySection() { model.getShouldShowLearnWhyOverlay().set(false); + view.getRoot().setOnKeyPressed(null); } private void applyPriceSpec() { diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/select_offer/TradeWizardSelectOfferView.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/select_offer/TradeWizardSelectOfferView.java index d721399e07..4829cc4141 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/select_offer/TradeWizardSelectOfferView.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/bisq_easy/trade_wizard/select_offer/TradeWizardSelectOfferView.java @@ -327,7 +327,7 @@ public ListItem(BisqEasyOffer bisqEasyOffer, model.getQuoteSideAmountSpec(), bisqEasyOffer.getPriceSpec(), bisqEasyOffer.getMarket()) - .orElse(Monetary.from(0, model.getMarket().getBaseCurrencyCode())); + .orElseThrow(); baseAmountAsLong = baseAmountAsMonetary.getValue(); baseAmountDisplayString = AmountFormatter.formatAmountWithCode(baseAmountAsMonetary, false); reputationScore = authorUserProfile.flatMap(reputationService::findReputationScore) diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessagesListController.java b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessagesListController.java index 63bcb1e909..ed7a931c63 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessagesListController.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/main/content/chat/message_container/list/ChatMessagesListController.java @@ -368,10 +368,10 @@ public void onTakeOffer(BisqEasyOfferbookMessage bisqEasyOfferbookMessage) { .warning(Res.get("chat.message.takeOffer.seller.myReputationScoreTooLow.warning", sellersScore, requiredReputationScoreForMinAmount, minFiatAmount)).show(); } else { - Optional myMaxAllowedAmount = BisqEasyTradeAmountLimits.getMaxQuoteSideTradeAmount(marketPriceService, bisqEasyOffer.getMarket(), sellersScore); + Optional reputationBasedQuoteSideAmount = BisqEasyTradeAmountLimits.getReputationBasedQuoteSideAmount(marketPriceService, bisqEasyOffer.getMarket(), sellersScore); Monetary offersMaxAmount = OfferAmountUtil.findQuoteSideMaxOrFixedAmount(marketPriceService, bisqEasyOffer).orElseThrow(); - if (myMaxAllowedAmount.isPresent() && offersMaxAmount.isGreaterThan(myMaxAllowedAmount.get())) { - Navigation.navigateTo(NavigationTarget.TAKE_OFFER, new TakeOfferController.InitData(bisqEasyOffer, myMaxAllowedAmount)); + if (reputationBasedQuoteSideAmount.isPresent() && offersMaxAmount.isGreaterThan(reputationBasedQuoteSideAmount.get())) { + Navigation.navigateTo(NavigationTarget.TAKE_OFFER, new TakeOfferController.InitData(bisqEasyOffer, reputationBasedQuoteSideAmount)); } else { Navigation.navigateTo(NavigationTarget.TAKE_OFFER, new TakeOfferController.InitData(bisqEasyOffer, Optional.empty())); } diff --git a/apps/desktop/desktop/src/main/resources/css/bisq_easy.css b/apps/desktop/desktop/src/main/resources/css/bisq_easy.css index 14b8490f05..c7ad0befd3 100644 --- a/apps/desktop/desktop/src/main/resources/css/bisq_easy.css +++ b/apps/desktop/desktop/src/main/resources/css/bisq_easy.css @@ -973,10 +973,18 @@ .trade-wizard-amount-limit-info-overlay-link.hyperlink:hover:visited { -fx-text-fill: -bisq2-green; } + .trade-wizard-amount-limit-info-overlay-link.hyperlink:visited { -fx-text-fill: -bisq2-green; } +.trade-wizard-amount-limit-info-overlay-link.hyperlink:disabled { + -fx-opacity: 1; + -fx-text-fill: -fx-mid-text-color; + -fx-underline: false; + -fx-cursor: none; +} + .trade-wizard-review-details-headline { -fx-fill: -fx-mid-text-color; -fx-text-fill: -fx-mid-text-color; diff --git a/bisq-easy/src/main/java/bisq/bisq_easy/BisqEasyTradeAmountLimits.java b/bisq-easy/src/main/java/bisq/bisq_easy/BisqEasyTradeAmountLimits.java index 575e1a7779..223c06740f 100644 --- a/bisq-easy/src/main/java/bisq/bisq_easy/BisqEasyTradeAmountLimits.java +++ b/bisq-easy/src/main/java/bisq/bisq_easy/BisqEasyTradeAmountLimits.java @@ -54,9 +54,9 @@ public static Optional getMinQuoteSideTradeAmount(MarketPriceService m .map(priceQuote -> priceQuote.toQuoteSideMonetary(defaultMinBtcTradeAmount))); } - public static Optional getMaxQuoteSideTradeAmount(MarketPriceService marketPriceService, - Market market, - long myReputationScore) { + public static Optional getReputationBasedQuoteSideAmount(MarketPriceService marketPriceService, + Market market, + long myReputationScore) { Fiat maxUsdTradeAmount = getMaxUsdTradeAmount(myReputationScore); return marketPriceService.findMarketPriceQuote(MarketRepository.getUSDBitcoinMarket()) .map(priceQuote -> priceQuote.toBaseSideMonetary(maxUsdTradeAmount)) diff --git a/i18n/src/main/resources/bisq_easy.properties b/i18n/src/main/resources/bisq_easy.properties index cdd2536136..e3dff3ab90 100644 --- a/i18n/src/main/resources/bisq_easy.properties +++ b/i18n/src/main/resources/bisq_easy.properties @@ -170,19 +170,24 @@ bisqEasy.tradeWizard.amount.seller.limitInfo.noReputationNeededForMaxOrFixedAmou For offers exceeding this amount, buyers will receive a warning about potential risks when taking your offer.\n\n\ You can find information on how to increase your reputation at ''Reputation/Build Reputation''. bisqEasy.tradeWizard.amount.buyer.limitInfo.learnMore=Learn more - -bisqEasy.tradeWizard.amount.buyer.limitInfo=There are {0} sellers in the network with sufficient reputation to accept an offer of {1}. +# suppress inspection "UnusedProperty" +bisqEasy.tradeWizard.amount.buyer.numSellers.0=is no seller +# suppress inspection "UnusedProperty" +bisqEasy.tradeWizard.amount.buyer.numSellers.1=is one seller +# suppress inspection "UnusedProperty" +bisqEasy.tradeWizard.amount.buyer.numSellers.2=are {0} sellers +bisqEasy.tradeWizard.amount.buyer.limitInfo=There {0} in the network with sufficient reputation to take an offer of {1}. bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.info=A seller who wants to take your offer of {0}, must have a reputation score of at least {1}.\n\ By reducing the maximum trade amount, you make your offer accessible to more sellers. -bisqEasy.tradeWizard.amount.buyer.limitInfo.noReputationNeededForMaxOrFixedAmount=For amounts up to {0} the reputation requirements are relaxed and anyone can take your offer. -bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.noReputationNeededForMaxOrFixedAmount.info=Given the low amount of {0}, the reputation requirements are relaxed.\n\ +bisqEasy.tradeWizard.amount.buyer.limitInfo.noReputationNeededForMaxOrFixedAmount=For amounts up to {0}, reputation requirements are relaxed, allowing anyone to take your offer. +bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.noReputationNeededForMaxOrFixedAmount.info=Given the low amount of {0}, reputation requirements are relaxed.\n\ For amounts up to {1}, sellers with insufficient or no reputation can take the offer. -bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.linkToWikiText=You can learn more about the reputation system at: +bisqEasy.tradeWizard.amount.buyer.limitInfo.overlay.linkToWikiText=To learn more about the reputation system, visit: -bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo.leadLine=Your min. amount is below {0} which does not require reputation from sellers. -bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo=For the max. amount of {0} there are {1} traders with enough reputation to take your offer. +bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo.leadLine=Since your min. amount is below {0}, sellers don't need to have a reputation. +bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo=For the max. amount of {0} there {1} with enough reputation to take your offer. bisqEasy.tradeWizard.amount.buyer.noReputationNeededForMinAmount.limitInfo.overlay.info=Given the low min. amount of {0}, the reputation requirements are relaxed. \ For amounts up to {1}, sellers with insufficient or no reputation can take your offer.\n\n\ Sellers who wants to take your offer with the max. amount of {2}, must have a reputation score of at least {3}.\n\n\ @@ -327,7 +332,7 @@ bisqEasy.takeOffer.amount.buyer.limitInfo.tooHighMin=Seller''s reputation score bisqEasy.takeOffer.amount.buyer.limitInfo.learnMore=Learn more bisqEasy.takeOffer.amount.buyer.limitInfo.overlay.info=Seller''s reputation score of {0} provides security for up to {1}.\n\n\ If you decide to trade above that amount, be sure to fully understand the risks. It is recommended to trade smaller amounts or repeat trades to lower potential risks. -bisqEasy.takeOffer.amount.buyer.limitInfo.overlay.linkToWikiText=You can learn more about the reputation system at: +bisqEasy.takeOffer.amount.buyer.limitInfo.overlay.linkToWikiText=To learn more about the reputation system, visit: bisqEasy.takeOffer.paymentMethods.headline.fiat=Which payment method do you want to use? bisqEasy.takeOffer.paymentMethods.headline.fiatAndBitcoin=Which payment and settlement method do you want to use? diff --git a/i18n/src/main/resources/chat.properties b/i18n/src/main/resources/chat.properties index 9ee0066382..93a4397d89 100644 --- a/i18n/src/main/resources/chat.properties +++ b/i18n/src/main/resources/chat.properties @@ -240,13 +240,13 @@ chat.message.contextMenu.reportUser=Report user to moderator chat.message.takeOffer.seller.myReputationScoreTooLow.headline=Your reputation score is too low for taking that offer chat.message.takeOffer.seller.myReputationScoreTooLow.warning=Your reputation score is {0} and below the required reputation score of {1} for the trade amount of {2}.\n\n\ The security model of Bisq Easy is based on the seller's reputation.\n\ - You can learn more about the reputation system at: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ + To learn more about the reputation system, visit: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ You can read more about how to build up your reputation at ''Reputation/Build Reputation''. chat.message.takeOffer.buyer.makersReputationScoreTooLow.headline=Security warning chat.message.takeOffer.buyer.makersReputationScoreTooLow.warning=The seller''s reputation score is {0} and below the required reputation score of {1} for a trade amount of {2}.\n\n\ The security model of Bisq Easy is based on the seller's reputation.\n\ - You can learn more about the reputation system at: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ + To learn more about the reputation system, visit: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ Do you want to continue and take that offer? chat.message.takeOffer.buyer.makersReputationScoreTooLow.yes=Yes, I understand the risk and want to continue chat.message.takeOffer.buyer.makersReputationScoreTooLow.no=No, I look for another offer @@ -255,7 +255,7 @@ chat.message.takeOffer.buyer.makersReputationTooLowButInLowAmountTolerance.headl chat.message.takeOffer.buyer.makersReputationTooLowButInLowAmountTolerance.warning=The maker''s reputation score is {0} and below the required reputation score of {1} for a trade amount of {2}.\n\n\ As the trade amount is very low you still can take the offer, but be sure to fully understand the risks.\n\n\ The security model of Bisq Easy is based on the seller's reputation.\n\ - You can learn more about the reputation system at: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ + To learn more about the reputation system, visit: [HYPERLINK:https://bisq.wiki/Reputation].\n\n\ Do you still want to take the offer? chat.message.takeOffer.buyer.makersReputationTooLowButInLowAmountTolerance.yes=Yes, I understand the risk and want to continue chat.message.takeOffer.buyer.makersReputationTooLowButInLowAmountTolerance.no=No, I look for another offer