Add adjustment fro multiple ofg 10 EUR for HalCash

With ATMs one can withdraw only multiples of 10 EUR.
We adjust the input values the way that the EUR amount leads to
multiple of 10. MinAmount and amount will be adjusted.

Please note that a similar approach like implemented here for HalCash
can be used for removing the decimal places from fiat amounts to
improve privacy. We keep that for a follow up PR to not mix 2 different
use cases.
This commit is contained in:
Manfred Karrer 2018-08-11 20:48:42 +02:00
parent e7b3629a71
commit 3bce2b828b
No known key found for this signature in database
GPG Key ID: 401250966A6B2C46
6 changed files with 70 additions and 21 deletions

View File

@ -40,6 +40,7 @@ import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.BankAccount;
import bisq.core.payment.CountryBasedPaymentAccount;
import bisq.core.payment.F2FAccount;
import bisq.core.payment.HalCashAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.SameBankAccount;
import bisq.core.payment.SepaAccount;
@ -307,7 +308,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
@SuppressWarnings("ConstantConditions")
Offer createAndGetOffer() {
final boolean useMarketBasedPriceValue = isUseMarketBasedPriceValue();
boolean useMarketBasedPriceValue = isUseMarketBasedPriceValue();
long priceAsLong = price.get() != null && !useMarketBasedPriceValue ? price.get().getValue() : 0L;
String currencyCode = tradeCurrencyCode.get();
boolean isCryptoCurrency = CurrencyUtil.isCryptoCurrency(currencyCode);
@ -662,7 +663,13 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
!amount.get().isZero() &&
!price.get().isZero()) {
try {
volume.set(price.get().getVolumeByAmount(amount.get()));
Volume volumeByAmount = price.get().getVolumeByAmount(amount.get());
// For HalCash we want multiple of 10 EUR
if (isHalCashAccount())
volumeByAmount = OfferUtil.getAdjustedVolumeForHalCash(volumeByAmount);
volume.set(volumeByAmount);
} catch (Throwable t) {
log.error(t.toString());
}
@ -743,7 +750,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
}
protected boolean isUseMarketBasedPriceValue() {
return marketPriceAvailable && useMarketBasedPrice.get();
return marketPriceAvailable && useMarketBasedPrice.get() && !isHalCashAccount();
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -813,4 +820,8 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
public boolean isBsqForFeeAvailable() {
return OfferUtil.isBsqForFeeAvailable(bsqWalletService, amount.get(), marketPriceAvailable, marketPriceMargin);
}
public boolean isHalCashAccount() {
return paymentAccount instanceof HalCashAccount;
}
}

View File

@ -238,7 +238,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
onPaymentAccountsComboBoxSelected();
balanceTextField.setTargetAmount(model.getDataModel().totalToPayAsCoinProperty().get());
updateMarketPriceAvailable();
updatePriceToggle();
}
}
@ -297,7 +297,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
percentagePriceDescription.setText(Res.get("shared.aboveInPercent"));
}
updateMarketPriceAvailable();
updatePriceToggle();
if (!model.getDataModel().isMakerFeeValid() && model.getDataModel().getMakerFee() != null)
showInsufficientBsqFundsForBtcFeePaymentPopup();
@ -502,6 +502,8 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
}
currencyComboBox.setOnAction(currencyComboBoxSelectionHandler);
updatePriceToggle();
}
private void onCurrencyComboBoxSelected() {
@ -703,7 +705,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
}
};
marketPriceAvailableListener = (observable, oldValue, newValue) -> updateMarketPriceAvailable();
marketPriceAvailableListener = (observable, oldValue, newValue) -> updatePriceToggle();
getShowWalletFundedNotificationListener = (observable, oldValue, newValue) -> {
if (newValue) {
@ -756,15 +758,16 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel> extends
return label;
}
protected void updateMarketPriceAvailable() {
protected void updatePriceToggle() {
int marketPriceAvailableValue = model.marketPriceAvailableProperty.get();
if (marketPriceAvailableValue > -1) {
boolean isMarketPriceAvailable = marketPriceAvailableValue == 1;
percentagePriceBox.setVisible(isMarketPriceAvailable);
percentagePriceBox.setManaged(isMarketPriceAvailable);
priceTypeToggleButton.setVisible(isMarketPriceAvailable);
priceTypeToggleButton.setManaged(isMarketPriceAvailable);
boolean fixedPriceSelected = !model.getDataModel().getUseMarketBasedPrice().get() || !isMarketPriceAvailable;
boolean showPriceToggle = marketPriceAvailableValue == 1 &&
!model.getDataModel().isHalCashAccount();
percentagePriceBox.setVisible(showPriceToggle);
percentagePriceBox.setManaged(showPriceToggle);
priceTypeToggleButton.setVisible(showPriceToggle);
priceTypeToggleButton.setManaged(showPriceToggle);
boolean fixedPriceSelected = !model.getDataModel().getUseMarketBasedPrice().get() || !showPriceToggle;
updatePriceToggleButtons(fixedPriceSelected);
}
}

View File

@ -45,6 +45,7 @@ import bisq.core.monetary.Price;
import bisq.core.monetary.Volume;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.PaymentAccount;
import bisq.core.provider.price.MarketPrice;
import bisq.core.provider.price.PriceFeedService;
@ -683,6 +684,9 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (minAmount.get() != null)
minAmountValidationResult.set(isBtcInputValid(minAmount.get()));
}
// We want to trigger a recalculation of the volume
UserThread.execute(() -> onFocusOutVolumeTextField(true, false));
}
}
@ -723,6 +727,13 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
dataModel.calculateAmount();
applyMakerFee();
}
// We want to trigger a recalculation of the volume and minAmount
UserThread.execute(() -> {
onFocusOutVolumeTextField(true, false);
// We also need to update minAmount
onFocusOutMinAmountTextField(true, false);
});
}
}
@ -743,8 +754,16 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (result.isValid) {
setVolumeToModel();
ignoreVolumeStringListener = true;
if (dataModel.getVolume().get() != null)
volume.set(btcFormatter.formatVolume(dataModel.getVolume().get()));
Volume volume = dataModel.getVolume().get();
if (volume != null) {
// For HalCash we want multiple of 10 EUR
if (dataModel.isHalCashAccount())
volume = OfferUtil.getAdjustedVolumeForHalCash(volume);
this.volume.set(btcFormatter.formatVolume(volume));
}
ignoreVolumeStringListener = false;
dataModel.calculateAmount();
@ -958,10 +977,16 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
}
private void setMinAmountToModel() {
if (minAmount.get() != null && !minAmount.get().isEmpty())
dataModel.setMinAmount(btcFormatter.parseToCoinWith4Decimals(minAmount.get()));
else
if (minAmount.get() != null && !minAmount.get().isEmpty()) {
Coin minAmount = btcFormatter.parseToCoinWith4Decimals(this.minAmount.get());
if (dataModel.isHalCashAccount() && dataModel.getPrice().get() != null)
minAmount = OfferUtil.getAdjustedMinAmountForHalCash(minAmount, dataModel.getPrice().get());
dataModel.setMinAmount(minAmount);
} else {
dataModel.setMinAmount(null);
}
}
private void setPriceToModel() {

View File

@ -35,6 +35,7 @@ import bisq.core.monetary.Price;
import bisq.core.monetary.Volume;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.PaymentAccountUtil;
@ -490,8 +491,11 @@ class TakeOfferDataModel extends OfferDataModel {
if (tradePrice != null && offer != null &&
amount.get() != null &&
!amount.get().isZero()) {
volume.set(tradePrice.getVolumeByAmount(amount.get()));
//volume.set(new ExchangeRate(tradePrice).coinToFiat(amountAsCoin.get()));
Volume volumeByAmount = tradePrice.getVolumeByAmount(amount.get());
if (offer.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID))
volumeByAmount = OfferUtil.getAdjustedVolumeForHalCash(volumeByAmount);
volume.set(volumeByAmount);
updateBalance();
}

View File

@ -31,6 +31,7 @@ import bisq.core.btc.wallet.WalletsSetup;
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.Trade;
@ -280,6 +281,11 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
calculateVolume();
if (dataModel.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID)) {
dataModel.applyAmount(OfferUtil.getAdjustedMinAmountForHalCash(dataModel.getAmount().get(), dataModel.tradePrice));
amount.set(btcFormatter.formatCoin(dataModel.getAmount().get()));
}
if (!dataModel.isMinAmountLessOrEqualAmount())
amountValidationResult.set(new InputValidator.ValidationResult(false,
Res.get("takeOffer.validation.amountSmallerThanMinAmount")));

View File

@ -97,7 +97,7 @@ public class EditOfferView extends MutableOfferView<EditOfferViewModel> {
// Workaround to fix margin on top of amount group
gridPane.setPadding(new Insets(-20, 25, -1, 25));
updateMarketPriceAvailable();
updatePriceToggle();
updateElementsWithDirection();
model.isNextButtonDisabled.setValue(false);