Merge pull request #5344 from jmacxx/add_warning_risk_sell

Pop-up warning for trading with risky payment methods
This commit is contained in:
Christoph Atteneder 2021-03-23 15:11:42 +01:00 committed by GitHub
commit e59f6afd91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 1 deletions

View file

@ -3293,6 +3293,18 @@ payment.accountType=Account type
payment.checking=Checking payment.checking=Checking
payment.savings=Savings payment.savings=Savings
payment.personalId=Personal ID payment.personalId=Personal ID
payment.makeOfferToUnsignedAccount.warning=With the recent rise in BTC price, beware that selling 0.01 BTC or less incurs higher risk than before.\n\n\
It is highly recommended to either:\n\
- make offers >0.01 BTC, so you only deal with signed/trusted buyers\n\
- keep any offers to sell <0.01 BTC to around ~100 USD in value, as this value has (historically) discouraged scammers\n\n\
Bisq developers are working on better ways to secure the payment account model for such smaller trades. \
Join the discussion here: [HYPERLINK:https://github.com/bisq-network/bisq/discussions/5339].
payment.takeOfferFromUnsignedAccount.warning=With the recent rise in BTC price, beware that selling 0.01 BTC or less incurs higher risk than before.\n\n\
It is highly recommended to either:\n\
- take offers from signed buyers only\n\
- keep trades with unsigned/untrusted buyers to around ~100 USD in value, as this value has (historically) discouraged scammers\n\n\
Bisq developers are working on better ways to secure the payment account model for such smaller trades. \
Join the discussion here: [HYPERLINK:https://github.com/bisq-network/bisq/discussions/5339].
payment.clearXchange.info=Zelle is a money transfer service that works best *through* another bank.\n\n\ payment.clearXchange.info=Zelle is a money transfer service that works best *through* another bank.\n\n\
1. Check this page to see if (and how) your bank works with Zelle: [HYPERLINK:https://www.zellepay.com/get-started]\n\n\ 1. Check this page to see if (and how) your bank works with Zelle: [HYPERLINK:https://www.zellepay.com/get-started]\n\n\
2. Take special note of your transfer limits—sending limits vary by bank, and banks often specify separate daily, weekly, and monthly limits.\n\n\ 2. Take special note of your transfer limits—sending limits vary by bank, and banks often specify separate daily, weekly, and monthly limits.\n\n\

View file

@ -49,6 +49,7 @@ import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferRestrictions; import bisq.core.offer.OfferRestrictions;
import bisq.core.offer.OfferUtil; import bisq.core.offer.OfferUtil;
import bisq.core.payment.PaymentAccount; import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.provider.fee.FeeService; import bisq.core.provider.fee.FeeService;
import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.MarketPrice;
import bisq.core.provider.price.PriceFeedService; import bisq.core.provider.price.PriceFeedService;
@ -660,6 +661,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(dataModel.getTradeCurrencyCode().get())); btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(dataModel.getTradeCurrencyCode().get()));
btcValidator.setMaxTradeLimit(Coin.valueOf(dataModel.getMaxTradeLimit())); btcValidator.setMaxTradeLimit(Coin.valueOf(dataModel.getMaxTradeLimit()));
maybeShowMakeOfferToUnsignedAccountWarning();
securityDepositValidator.setPaymentAccount(paymentAccount); securityDepositValidator.setPaymentAccount(paymentAccount);
} }
@ -776,6 +778,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
} else { } else {
syncMinAmountWithAmount = true; syncMinAmountWithAmount = true;
} }
maybeShowMakeOfferToUnsignedAccountWarning();
} }
} }
@ -1218,6 +1222,16 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
} }
} }
private void maybeShowMakeOfferToUnsignedAccountWarning() {
if (dataModel.getDirection() == OfferPayload.Direction.SELL &&
PaymentMethod.hasChargebackRisk(dataModel.getPaymentAccount().getPaymentMethod(), dataModel.getTradeCurrency().getCode())) {
Coin checkAmount = dataModel.getMinAmount().get() == null ? dataModel.getAmount().get() : dataModel.getMinAmount().get();
if (checkAmount != null && !checkAmount.isGreaterThan(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT)) {
GUIUtil.showMakeOfferToUnsignedAccountWarning();
}
}
}
private InputValidator.ValidationResult isBtcInputValid(String input) { private InputValidator.ValidationResult isBtcInputValid(String input) {
return btcValidator.validate(input); return btcValidator.validate(input);
} }

View file

@ -161,7 +161,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
isOfferAvailableSubscription; isOfferAvailableSubscription;
private int gridRow = 0; private int gridRow = 0;
private boolean offerDetailsWindowDisplayed, clearXchangeWarningDisplayed, fasterPaymentsWarningDisplayed; private boolean offerDetailsWindowDisplayed, clearXchangeWarningDisplayed, fasterPaymentsWarningDisplayed, takeOfferFromUnsignedAccountWarningDisplayed;
private SimpleBooleanProperty errorPopupDisplayed; private SimpleBooleanProperty errorPopupDisplayed;
private ChangeListener<Boolean> amountFocusedListener, getShowWalletFundedNotificationListener; private ChangeListener<Boolean> amountFocusedListener, getShowWalletFundedNotificationListener;
@ -304,6 +304,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
balanceTextField.setTargetAmount(model.dataModel.getTotalToPayAsCoin().get()); balanceTextField.setTargetAmount(model.dataModel.getTotalToPayAsCoin().get());
maybeShowTakeOfferFromUnsignedAccountWarning(model.dataModel.getOffer());
maybeShowClearXchangeWarning(lastPaymentAccount); maybeShowClearXchangeWarning(lastPaymentAccount);
maybeShowFasterPaymentsWarning(lastPaymentAccount); maybeShowFasterPaymentsWarning(lastPaymentAccount);
@ -1243,6 +1244,14 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
.show(); .show();
} }
private void maybeShowTakeOfferFromUnsignedAccountWarning(Offer offer) {
// warn if you are selling BTC to unsigned account (#5343)
if (model.isSellingToAnUnsignedAccount(offer) && !takeOfferFromUnsignedAccountWarningDisplayed) {
takeOfferFromUnsignedAccountWarningDisplayed = true;
UserThread.runAfter(GUIUtil::showTakeOfferFromUnsignedAccountWarning, 500, TimeUnit.MILLISECONDS);
}
}
private void maybeShowClearXchangeWarning(PaymentAccount paymentAccount) { private void maybeShowClearXchangeWarning(PaymentAccount paymentAccount) {
if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.CLEAR_X_CHANGE_ID) && if (paymentAccount.getPaymentMethod().getId().equals(PaymentMethod.CLEAR_X_CHANGE_ID) &&
!clearXchangeWarningDisplayed) { !clearXchangeWarningDisplayed) {

View file

@ -644,6 +644,17 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
return dataModel.getDirection() == OfferPayload.Direction.BUY; return dataModel.getDirection() == OfferPayload.Direction.BUY;
} }
public boolean isSellingToAnUnsignedAccount(Offer offer) {
if (offer.getDirection() == OfferPayload.Direction.BUY &&
PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode())) {
// considered risky when either UNSIGNED, PEER_INITIAL, or BANNED (see #5343)
return accountAgeWitnessService.getSignState(offer) == AccountAgeWitnessService.SignState.UNSIGNED ||
accountAgeWitnessService.getSignState(offer) == AccountAgeWitnessService.SignState.PEER_INITIAL ||
accountAgeWitnessService.getSignState(offer) == AccountAgeWitnessService.SignState.BANNED;
}
return false;
}
private InputValidator.ValidationResult isBtcInputValid(String input) { private InputValidator.ValidationResult isBtcInputValid(String input) {
return btcValidator.validate(input); return btcValidator.validate(input);
} }

View file

@ -698,6 +698,24 @@ public class GUIUtil {
return t.cast(parent); return t.cast(parent);
} }
public static void showTakeOfferFromUnsignedAccountWarning() {
String key = "confirmTakeOfferFromUnsignedAccount";
new Popup().warning(Res.get("payment.takeOfferFromUnsignedAccount.warning"))
.width(900)
.closeButtonText(Res.get("shared.iConfirm"))
.dontShowAgainId(key)
.show();
}
public static void showMakeOfferToUnsignedAccountWarning() {
String key = "confirmMakeOfferToUnsignedAccount";
new Popup().warning(Res.get("payment.makeOfferToUnsignedAccount.warning"))
.width(900)
.closeButtonText(Res.get("shared.iConfirm"))
.dontShowAgainId(key)
.show();
}
public static void showClearXchangeWarning() { public static void showClearXchangeWarning() {
String key = "confirmClearXchangeRequirements"; String key = "confirmClearXchangeRequirements";
final String currencyName = Config.baseCurrencyNetwork().getCurrencyName(); final String currencyName = Config.baseCurrencyNetwork().getCurrencyName();