Skip to content

Commit

Permalink
Use different security deposit for fiat-crypto and crypto-crypto trades
Browse files Browse the repository at this point in the history
  • Loading branch information
ripcurlx committed Apr 18, 2019
1 parent 2119872 commit ba5804b
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 31 deletions.
1 change: 1 addition & 0 deletions common/src/main/proto/pb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ message PreferencesPayload {
string take_offer_selected_payment_account_id = 49;
double buyer_security_deposit_as_percent = 50;
int32 ignore_dust_threshold = 51;
double buyer_security_deposit_as_percent_for_crypto = 52;
}

///////////////////////////////////////////////////////////////////////////////////////////
Expand Down
22 changes: 16 additions & 6 deletions core/src/main/java/bisq/core/btc/wallet/Restrictions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package bisq.core.btc.wallet;

import bisq.core.app.BisqEnvironment;
import bisq.core.locale.CurrencyUtil;

import org.bitcoinj.core.Coin;

Expand Down Expand Up @@ -50,16 +51,25 @@ public static Coin getMinTradeAmount() {
return MIN_TRADE_AMOUNT;
}

public static double getDefaultBuyerSecurityDepositAsPercent() {
return 0.1; // 10% of trade amount.
public static double getDefaultBuyerSecurityDepositAsPercent(String currencyCode) {
if (CurrencyUtil.isCryptoCurrency(currencyCode))
return 0.02; // 2% of trade amount.
else
return 0.1; // 10% of trade amount.
}

public static double getMinBuyerSecurityDepositAsPercent() {
return 0.05; // 5% of trade amount.
public static double getMinBuyerSecurityDepositAsPercent(String currencyCode) {
if (CurrencyUtil.isCryptoCurrency(currencyCode))
return 0.005; // 0.5% of trade amount.
else
return 0.05; // 5% of trade amount.
}

public static double getMaxBuyerSecurityDepositAsPercent() {
return 0.5; // 50% of trade amount. For a 1 BTC trade it is about 800 USD @ 4000 USD/BTC
public static double getMaxBuyerSecurityDepositAsPercent(String currencyCode) {
if (CurrencyUtil.isCryptoCurrency(currencyCode))
return 0.2; // 20% of trade amount. For a 1 BTC trade it is about 800 USD @ 4000 USD/BTC
else
return 0.5; // 50% of trade amount. For a 1 BTC trade it is about 2000 USD @ 4000 USD/BTC
}

// We use MIN_BUYER_SECURITY_DEPOSIT as well as lower bound in case of small trade amounts.
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/java/bisq/core/offer/OfferUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -353,12 +353,12 @@ public static void validateOfferData(FilterManager filterManager,
Coin makerFeeAsCoin) {
checkNotNull(makerFeeAsCoin, "makerFee must not be null");
checkNotNull(p2PService.getAddress(), "Address must not be null");
checkArgument(buyerSecurityDeposit <= Restrictions.getMaxBuyerSecurityDepositAsPercent(),
checkArgument(buyerSecurityDeposit <= Restrictions.getMaxBuyerSecurityDepositAsPercent(currencyCode),
"securityDeposit must not exceed " +
Restrictions.getMaxBuyerSecurityDepositAsPercent());
checkArgument(buyerSecurityDeposit >= Restrictions.getMinBuyerSecurityDepositAsPercent(),
Restrictions.getMaxBuyerSecurityDepositAsPercent(currencyCode));
checkArgument(buyerSecurityDeposit >= Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode),
"securityDeposit must not be less than " +
Restrictions.getMinBuyerSecurityDepositAsPercent());
Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode));
checkArgument(!filterManager.isCurrencyBanned(currencyCode),
Res.get("offerbook.warning.currencyBanned"));
checkArgument(!filterManager.isPaymentMethodBanned(paymentAccount.getPaymentMethod()),
Expand Down
25 changes: 15 additions & 10 deletions core/src/main/java/bisq/core/user/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -493,10 +493,14 @@ public void setWithdrawalTxFeeInBytes(long withdrawalTxFeeInBytes) {
withdrawalTxFeeInBytesProperty.set(withdrawalTxFeeInBytes);
}

public void setBuyerSecurityDepositAsPercent(double buyerSecurityDepositAsPercent) {
double max = Restrictions.getMaxBuyerSecurityDepositAsPercent();
double min = Restrictions.getMinBuyerSecurityDepositAsPercent();
prefPayload.setBuyerSecurityDepositAsPercent(Math.min(max, Math.max(min, buyerSecurityDepositAsPercent)));
public void setBuyerSecurityDepositAsPercent(double buyerSecurityDepositAsPercent, String currencyCode) {
double max = Restrictions.getMaxBuyerSecurityDepositAsPercent(currencyCode);
double min = Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode);

if (CurrencyUtil.isCryptoCurrency(currencyCode))
prefPayload.setBuyerSecurityDepositAsPercentForCrypto(Math.min(max, Math.max(min, buyerSecurityDepositAsPercent)));
else
prefPayload.setBuyerSecurityDepositAsPercent(Math.min(max, Math.max(min, buyerSecurityDepositAsPercent)));
persist();
}

Expand Down Expand Up @@ -715,15 +719,16 @@ public LongProperty withdrawalTxFeeInBytesProperty() {
return withdrawalTxFeeInBytesProperty;
}

public double getBuyerSecurityDepositAsPercent() {
double value = prefPayload.getBuyerSecurityDepositAsPercent();
public double getBuyerSecurityDepositAsPercent(String currencyCode) {
double value = CurrencyUtil.isCryptoCurrency(currencyCode) ?
prefPayload.getBuyerSecurityDepositAsPercentForCrypto() : prefPayload.getBuyerSecurityDepositAsPercent();

if (value < Restrictions.getMinBuyerSecurityDepositAsPercent()) {
value = Restrictions.getMinBuyerSecurityDepositAsPercent();
setBuyerSecurityDepositAsPercent(value);
if (value < Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode)) {
value = Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode);
setBuyerSecurityDepositAsPercent(value, currencyCode);
}

return value == 0 ? Restrictions.getDefaultBuyerSecurityDepositAsPercent() : value;
return value == 0 ? Restrictions.getDefaultBuyerSecurityDepositAsPercent(currencyCode) : value;
}

//TODO remove and use isPayFeeInBtc instead
Expand Down
14 changes: 10 additions & 4 deletions core/src/main/java/bisq/core/user/PreferencesPayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package bisq.core.user;

import bisq.core.app.BisqEnvironment;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.locale.Country;
import bisq.core.locale.CryptoCurrency;
Expand Down Expand Up @@ -120,8 +121,10 @@ public final class PreferencesPayload implements PersistableEnvelope {
String rpcPw;
@Nullable
String takeOfferSelectedPaymentAccountId;
private double buyerSecurityDepositAsPercent = Restrictions.getDefaultBuyerSecurityDepositAsPercent();
private double buyerSecurityDepositAsPercent = Restrictions.getDefaultBuyerSecurityDepositAsPercent(null);
private int ignoreDustThreshold = 600;
private double buyerSecurityDepositAsPercentForCrypto = Restrictions.getDefaultBuyerSecurityDepositAsPercent(
BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode());


///////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -178,8 +181,9 @@ public Message toProtoMessage() {
.setUsePriceNotifications(usePriceNotifications)
.setUseStandbyMode(useStandbyMode)
.setIsDaoFullNode(isDaoFullNode)
.setBuyerSecurityDepositAsPercent(buyerSecurityDepositAsPercent).
setIgnoreDustThreshold(ignoreDustThreshold);
.setBuyerSecurityDepositAsPercent(buyerSecurityDepositAsPercent)
.setIgnoreDustThreshold(ignoreDustThreshold)
.setBuyerSecurityDepositAsPercentForCrypto(buyerSecurityDepositAsPercentForCrypto);
Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
Expand Down Expand Up @@ -262,6 +266,8 @@ public static PersistableEnvelope fromProto(PB.PreferencesPayload proto, CorePro
proto.getRpcPw().isEmpty() ? null : proto.getRpcPw(),
proto.getTakeOfferSelectedPaymentAccountId().isEmpty() ? null : proto.getTakeOfferSelectedPaymentAccountId(),
proto.getBuyerSecurityDepositAsPercent(),
proto.getIgnoreDustThreshold());
proto.getIgnoreDustThreshold(),
proto.getBuyerSecurityDepositAsPercentForCrypto());

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public MutableOfferDataModel(OpenOfferManager openOfferManager,
addressEntry = btcWalletService.getOrCreateAddressEntry(offerId, AddressEntry.Context.OFFER_FUNDING);

useMarketBasedPrice.set(preferences.isUsePercentageBasedPrice());
buyerSecurityDeposit.set(preferences.getBuyerSecurityDepositAsPercent());
buyerSecurityDeposit.set(preferences.getBuyerSecurityDepositAsPercent(null));
sellerSecurityDeposit.set(Restrictions.getSellerSecurityDepositAsPercent());

btcBalanceListener = new BalanceListener(getAddressEntry().getAddress()) {
Expand Down Expand Up @@ -454,6 +454,8 @@ else if (!paymentAccount.getTradeCurrencies().isEmpty())

checkNotNull(tradeCurrency, "tradeCurrency must not be null");
tradeCurrencyCode.set(tradeCurrency.getCode());

buyerSecurityDeposit.set(preferences.getBuyerSecurityDepositAsPercent(tradeCurrencyCode.get()));
}

void onCurrencySelected(TradeCurrency tradeCurrency) {
Expand Down Expand Up @@ -710,7 +712,7 @@ protected void setVolume(Volume volume) {

void setBuyerSecurityDeposit(double value) {
this.buyerSecurityDeposit.set(value);
preferences.setBuyerSecurityDepositAsPercent(value);
preferences.setBuyerSecurityDepositAsPercent(value, tradeCurrencyCode.get());
}

protected boolean isUseMarketBasedPriceValue() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ boolean initWithData(OfferPayload.Direction direction, TradeCurrency tradeCurren
amountDescription = Res.get("createOffer.amountPriceBox.amountDescription",
isBuy ? Res.get("shared.buy") : Res.get("shared.sell"));

securityDepositValidator.setCurrencyCode(tradeCurrency.getCode());
buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
buyerSecurityDepositLabel.set(getSecurityDepositLabel());

Expand Down Expand Up @@ -663,13 +664,18 @@ public void onPaymentAccountSelected(PaymentAccount paymentAccount) {

btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(dataModel.getTradeCurrencyCode().get()));
btcValidator.setMaxTradeLimit(Coin.valueOf(dataModel.getMaxTradeLimit()));

securityDepositValidator.setCurrencyCode(dataModel.tradeCurrencyCode.get());
}

public void onCurrencySelected(TradeCurrency tradeCurrency) {
dataModel.onCurrencySelected(tradeCurrency);

marketPrice = priceFeedService.getMarketPrice(dataModel.getTradeCurrencyCode().get());
marketPriceAvailableProperty.set(marketPrice == null || !marketPrice.isExternallyProvidedPrice() ? 0 : 1);

securityDepositValidator.setCurrencyCode(dataModel.tradeCurrencyCode.get());

updateButtonDisableState();
}

Expand Down Expand Up @@ -853,7 +859,7 @@ void onFocusOutBuyerSecurityDepositTextField(boolean oldValue, boolean newValue)
InputValidator.ValidationResult result = securityDepositValidator.validate(buyerSecurityDeposit.get());
buyerSecurityDepositValidationResult.set(result);
if (result.isValid) {
double defaultSecurityDeposit = Restrictions.getDefaultBuyerSecurityDepositAsPercent();
double defaultSecurityDeposit = Restrictions.getDefaultBuyerSecurityDepositAsPercent(tradeCurrencyCode.get());
String key = "buyerSecurityDepositIsLowerAsDefault";
double depositAsDouble = btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get());
if (preferences.showAgain(key) && depositAsDouble < defaultSecurityDeposit) {
Expand Down Expand Up @@ -1121,7 +1127,7 @@ private void setBuyerSecurityDepositToModel() {
if (buyerSecurityDeposit.get() != null && !buyerSecurityDeposit.get().isEmpty()) {
dataModel.setBuyerSecurityDeposit(btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get()));
} else {
dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent());
dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent(tradeCurrencyCode.get()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
public class SecurityDepositValidator extends NumberValidator {

private final BSFormatter formatter;
private String currencyCode;

@Inject
public SecurityDepositValidator(BSFormatter formatter) {
this.formatter = formatter;
}

public void setCurrencyCode(String currencyCode) {
this.currencyCode = currencyCode;
}

@Override
public ValidationResult validate(String input) {
Expand All @@ -54,7 +58,7 @@ public ValidationResult validate(String input) {
private ValidationResult validateIfNotTooLowPercentageValue(String input) {
try {
double percentage = formatter.parsePercentStringToDouble(input);
double minPercentage = Restrictions.getMinBuyerSecurityDepositAsPercent();
double minPercentage = Restrictions.getMinBuyerSecurityDepositAsPercent(currencyCode);
if (percentage < minPercentage)
return new ValidationResult(false,
Res.get("validation.inputTooSmall", formatter.formatToPercentWithSymbol(minPercentage)));
Expand All @@ -68,7 +72,7 @@ private ValidationResult validateIfNotTooLowPercentageValue(String input) {
private ValidationResult validateIfNotTooHighPercentageValue(String input) {
try {
double percentage = formatter.parsePercentStringToDouble(input);
double maxPercentage = Restrictions.getMaxBuyerSecurityDepositAsPercent();
double maxPercentage = Restrictions.getMaxBuyerSecurityDepositAsPercent(currencyCode);
if (percentage > maxPercentage)
return new ValidationResult(false,
Res.get("validation.inputTooLarge", formatter.formatToPercentWithSymbol(maxPercentage)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void setUp() {

when(btcWalletService.getOrCreateAddressEntry(anyString(), any())).thenReturn(addressEntry);
when(preferences.isUsePercentageBasedPrice()).thenReturn(true);
when(preferences.getBuyerSecurityDepositAsPercent()).thenReturn(0.01);
when(preferences.getBuyerSecurityDepositAsPercent(null)).thenReturn(0.01);

model = new CreateOfferDataModel(null, btcWalletService,
null, preferences, user, null,
Expand Down

0 comments on commit ba5804b

Please sign in to comment.