From 9c2308f7a33412709c243b4835968bfa16134dcf Mon Sep 17 00:00:00 2001 From: woodser Date: Sun, 3 Sep 2023 10:45:55 -0400 Subject: [PATCH] support goldback (XGB) --- .../payment/AbstractPaymentAccountTest.java | 2 +- .../java/haveno/core/locale/CurrencyUtil.java | 33 +++++++++++++++---- .../core/locale/TraditionalCurrency.java | 20 +++++++---- .../java/haveno/core/user/Preferences.java | 2 +- .../haveno/core/util/FormattingUtils.java | 11 ++----- .../main/java/haveno/core/util/PriceUtil.java | 19 ++++++----- .../java/haveno/core/util/VolumeUtil.java | 24 +++++++------- .../java/haveno/core/util/coin/CoinUtil.java | 20 +++++------ ...tor.java => AmountValidator4Decimals.java} | 4 +-- ...tor.java => AmountValidator8Decimals.java} | 4 +-- .../MobileNotificationsView.java | 7 ++-- .../offerbook/OfferBookChartViewModel.java | 12 +++---- .../main/offer/MutableOfferDataModel.java | 5 --- .../main/offer/MutableOfferViewModel.java | 26 ++++++++------- .../createoffer/CreateOfferViewModel.java | 12 +++---- .../offer/offerbook/OfferBookViewModel.java | 2 +- .../offer/takeoffer/TakeOfferViewModel.java | 8 ++--- .../DuplicateOfferViewModel.java | 12 +++---- .../editoffer/EditOfferViewModel.java | 12 +++---- .../java/haveno/desktop/util/GUIUtil.java | 6 ++-- .../java/haveno/desktop/MarketsPrintTool.java | 2 +- .../createoffer/CreateOfferViewModelTest.java | 12 +++---- proto/src/main/proto/pb.proto | 1 - 23 files changed, 135 insertions(+), 121 deletions(-) rename core/src/main/java/haveno/core/util/validation/{FiatPriceValidator.java => AmountValidator4Decimals.java} (91%) rename core/src/main/java/haveno/core/util/validation/{NonFiatPriceValidator.java => AmountValidator8Decimals.java} (90%) diff --git a/apitest/src/test/java/haveno/apitest/method/payment/AbstractPaymentAccountTest.java b/apitest/src/test/java/haveno/apitest/method/payment/AbstractPaymentAccountTest.java index d7dcb57e..3667ed5d 100644 --- a/apitest/src/test/java/haveno/apitest/method/payment/AbstractPaymentAccountTest.java +++ b/apitest/src/test/java/haveno/apitest/method/payment/AbstractPaymentAccountTest.java @@ -209,7 +209,7 @@ public class AbstractPaymentAccountTest extends MethodTest { protected final String getCommaDelimitedTraditionalCurrencyCodes(Collection traditionalCurrencies) { return traditionalCurrencies.stream() .sorted(Comparator.comparing(TradeCurrency::getCode)) - .map(c -> c.getCurrency().getCurrencyCode()) + .map(c -> c.getCode()) .collect(Collectors.joining(",")); } diff --git a/core/src/main/java/haveno/core/locale/CurrencyUtil.java b/core/src/main/java/haveno/core/locale/CurrencyUtil.java index bd9db3b2..7a0925eb 100644 --- a/core/src/main/java/haveno/core/locale/CurrencyUtil.java +++ b/core/src/main/java/haveno/core/locale/CurrencyUtil.java @@ -56,6 +56,14 @@ public class CurrencyUtil { private static String baseCurrencyCode = "XMR"; + private static List getTraditionalNonFiatCurrencies() { + return Arrays.asList( + new TraditionalCurrency("XAG", "Gold"), + new TraditionalCurrency("XAU", "Silver"), + new TraditionalCurrency("XGB", "Goldback") + ); + } + // Calls to isTraditionalCurrency and isCryptoCurrency are very frequent so we use a cache of the results. // The main improvement was already achieved with using memoize for the source maps, but // the caching still reduces performance costs by about 20% for isCryptoCurrency (1752 ms vs 2121 ms) and about 50% @@ -101,7 +109,7 @@ public class CurrencyUtil { public static Collection getAllSortedTraditionalCurrencies(Comparator comparator) { return (List) getAllSortedTraditionalCurrencies().stream() - .sorted(comparator) // sorted by comparator param + .sorted(comparator) .collect(Collectors.toList()); } @@ -109,7 +117,7 @@ public class CurrencyUtil { List currencies = CountryUtil.getAllCountries().stream() .map(country -> getCurrencyByCountryCode(country.code)) .collect(Collectors.toList()); - for (String isoCode : nonFiatIsoCodes) currencies.add(new TraditionalCurrency(Currency.getInstance(isoCode))); + currencies.addAll(getTraditionalNonFiatCurrencies()); return currencies.stream().sorted(TradeCurrency::compareTo) .distinct() .collect(Collectors.toMap(TradeCurrency::getCode, Function.identity(), (x, y) -> x, LinkedHashMap::new)); @@ -131,12 +139,14 @@ public class CurrencyUtil { public static List getMainTraditionalCurrencies() { List list = getMainFiatCurrencies(); - for (String isoCode : nonFiatIsoCodes) list.add(new TraditionalCurrency(isoCode)); + list.addAll(getTraditionalNonFiatCurrencies()); postProcessTraditionalCurrenciesList(list); return list; } - private static List nonFiatIsoCodes = Arrays.asList("XAG", "XAU"); + private static boolean isTraditionalNonFiatCurrency(String currencyCode) { + return getTraditionalNonFiatCurrencies().stream().anyMatch(c -> c.getCode().equals(currencyCode)); + } private static void postProcessTraditionalCurrenciesList(List list) { list.sort(TradeCurrency::compareTo); @@ -209,7 +219,7 @@ public class CurrencyUtil { public static boolean isFiatCurrency(String currencyCode) { if (!isTraditionalCurrency(currencyCode)) return false; - if ("XAG".equalsIgnoreCase(currencyCode) || "XAU".equalsIgnoreCase(currencyCode)) return false; + if (isTraditionalNonFiatCurrency(currencyCode)) return false; return true; } @@ -224,7 +234,7 @@ public class CurrencyUtil { boolean isTraditionalCurrency = currencyCode != null && !currencyCode.isEmpty() && !isCryptoCurrency(currencyCode) - && Currency.getInstance(currencyCode) != null; + && (isTraditionalNonFiatCurrency(currencyCode) || Currency.getInstance(currencyCode) != null); if (currencyCode != null) { isTraditionalCurrencyMap.put(currencyCode, isTraditionalCurrency); @@ -237,6 +247,17 @@ public class CurrencyUtil { } } + public static boolean isVolumeRoundedToNearestUnit(String currencyCode) { + return isFiatCurrency(currencyCode) || + "XGB".equals(currencyCode.toUpperCase()); + } + + public static boolean isPricePrecise(String currencyCode) { + return isCryptoCurrency(currencyCode) || + "XAU".equals(currencyCode.toUpperCase()) || + "XAG".equals(currencyCode.toUpperCase()); + } + public static Optional getTraditionalCurrency(String currencyCode) { return Optional.ofNullable(traditionalCurrencyMapSupplier.get().get(currencyCode)); } diff --git a/core/src/main/java/haveno/core/locale/TraditionalCurrency.java b/core/src/main/java/haveno/core/locale/TraditionalCurrency.java index b8fafc6c..32dca917 100644 --- a/core/src/main/java/haveno/core/locale/TraditionalCurrency.java +++ b/core/src/main/java/haveno/core/locale/TraditionalCurrency.java @@ -30,15 +30,22 @@ import java.util.Locale; @ToString @Getter public final class TraditionalCurrency extends TradeCurrency { + // http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618 private final static String PREFIX = "★ "; - private final Currency currency; - public TraditionalCurrency(String currencyCode) { this(Currency.getInstance(currencyCode), getLocale()); } + public TraditionalCurrency(String currencyCode, String name) { + super(currencyCode, name); + } + + public TraditionalCurrency(TraditionalCurrency currency) { + this(currency.getCode(), currency.getName()); + } + @SuppressWarnings("WeakerAccess") public TraditionalCurrency(Currency currency) { this(currency, getLocale()); @@ -47,7 +54,6 @@ public final class TraditionalCurrency extends TradeCurrency { @SuppressWarnings("WeakerAccess") public TraditionalCurrency(Currency currency, Locale locale) { super(currency.getCurrencyCode(), currency.getDisplayName(locale)); - this.currency = currency; } @@ -57,15 +63,15 @@ public final class TraditionalCurrency extends TradeCurrency { @Override public Message toProtoMessage() { - protobuf.Currency.Builder currencyBuilder = protobuf.Currency.newBuilder().setCurrencyCode(currency.getCurrencyCode()); - protobuf.TraditionalCurrency.Builder traditionalCurrencyBuilder = protobuf.TraditionalCurrency.newBuilder().setCurrency(currencyBuilder); return getTradeCurrencyBuilder() - .setTraditionalCurrency(traditionalCurrencyBuilder) + .setCode(code) + .setName(name) + .setTraditionalCurrency(protobuf.TraditionalCurrency.newBuilder()) .build(); } public static TraditionalCurrency fromProto(protobuf.TradeCurrency proto) { - return new TraditionalCurrency(proto.getCode()); + return new TraditionalCurrency(proto.getCode(), proto.getName()); } diff --git a/core/src/main/java/haveno/core/user/Preferences.java b/core/src/main/java/haveno/core/user/Preferences.java index a3924615..213f2994 100644 --- a/core/src/main/java/haveno/core/user/Preferences.java +++ b/core/src/main/java/haveno/core/user/Preferences.java @@ -632,7 +632,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid public void setTraditionalCurrencies(List currencies) { traditionalCurrenciesAsObservable.setAll(currencies.stream() - .map(traditionalCurrency -> new TraditionalCurrency(traditionalCurrency.getCurrency())) + .map(traditionalCurrency -> new TraditionalCurrency(traditionalCurrency)) .distinct().collect(Collectors.toList())); requestPersistence(); } diff --git a/core/src/main/java/haveno/core/util/FormattingUtils.java b/core/src/main/java/haveno/core/util/FormattingUtils.java index d8df8253..ac652d91 100644 --- a/core/src/main/java/haveno/core/util/FormattingUtils.java +++ b/core/src/main/java/haveno/core/util/FormattingUtils.java @@ -29,9 +29,8 @@ public class FormattingUtils { public final static String RANGE_SEPARATOR = " - "; - private static final MonetaryFormat fiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); - private static final MonetaryFormat nonFiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0); - private static final MonetaryFormat traditionalFormat = new MonetaryFormat().shift(0).minDecimals(TraditionalMoney.SMALLEST_UNIT_EXPONENT).repeatOptionalDecimals(0, 0); + private static final MonetaryFormat priceFormat4Decimals = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); + private static final MonetaryFormat priceFormat8Decimals = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0); private static final MonetaryFormat cryptoFormat = new MonetaryFormat().shift(0).minDecimals(CryptoMoney.SMALLEST_UNIT_EXPONENT).repeatOptionalDecimals(0, 0); private static final DecimalFormat decimalFormat = new DecimalFormat("#.#"); @@ -293,11 +292,7 @@ public class FormattingUtils { return formattedNumber; } - public static MonetaryFormat getMonetaryFormat(String currencyCode) { - return CurrencyUtil.isTraditionalCurrency(currencyCode) ? traditionalFormat : cryptoFormat; - } - public static MonetaryFormat getPriceMonetaryFormat(String currencyCode) { - return CurrencyUtil.isFiatCurrency(currencyCode) ? fiatPriceFormat : nonFiatPriceFormat; + return CurrencyUtil.isPricePrecise(currencyCode) ? priceFormat8Decimals : priceFormat4Decimals; } } diff --git a/core/src/main/java/haveno/core/util/PriceUtil.java b/core/src/main/java/haveno/core/util/PriceUtil.java index c1892fc0..e00806b3 100644 --- a/core/src/main/java/haveno/core/util/PriceUtil.java +++ b/core/src/main/java/haveno/core/util/PriceUtil.java @@ -29,8 +29,8 @@ import haveno.core.provider.price.MarketPrice; import haveno.core.provider.price.PriceFeedService; import haveno.core.trade.statistics.TradeStatisticsManager; import haveno.core.user.Preferences; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; +import haveno.core.util.validation.AmountValidator8Decimals; +import haveno.core.util.validation.AmountValidator4Decimals; import haveno.core.util.validation.InputValidator; import haveno.core.util.validation.MonetaryValidator; import lombok.extern.slf4j.Slf4j; @@ -53,21 +53,21 @@ public class PriceUtil { this.priceFeedService = priceFeedService; } - public static MonetaryValidator getPriceValidator(boolean isFiatCurrency) { - return isFiatCurrency ? - new FiatPriceValidator() : - new NonFiatPriceValidator(); + public static MonetaryValidator getPriceValidator(String currencyCode) { + return CurrencyUtil.isPricePrecise(currencyCode) ? + new AmountValidator4Decimals() : + new AmountValidator8Decimals(); } public static InputValidator.ValidationResult isTriggerPriceValid(String triggerPriceAsString, MarketPrice marketPrice, boolean isSellOffer, - boolean isFiatCurrency) { + String currencyCode) { if (triggerPriceAsString == null || triggerPriceAsString.isEmpty()) { return new InputValidator.ValidationResult(true); } - InputValidator.ValidationResult result = getPriceValidator(isFiatCurrency).validate(triggerPriceAsString); + InputValidator.ValidationResult result = getPriceValidator(currencyCode).validate(triggerPriceAsString); if (!result.isValid) { return result; } @@ -76,7 +76,8 @@ public class PriceUtil { long marketPriceAsLong = PriceUtil.getMarketPriceAsLong("" + marketPrice.getPrice(), marketPrice.getCurrencyCode()); String marketPriceAsString = FormattingUtils.formatMarketPrice(marketPrice.getPrice(), marketPrice.getCurrencyCode()); - if ((isSellOffer && isFiatCurrency) || (!isSellOffer && !isFiatCurrency)) { + boolean isCryptoCurrency = CurrencyUtil.isCryptoCurrency(currencyCode); + if ((isSellOffer && !isCryptoCurrency) || (!isSellOffer && isCryptoCurrency)) { if (triggerPriceAsLong >= marketPriceAsLong) { return new InputValidator.ValidationResult(false, Res.get("createOffer.triggerPrice.invalid.tooHigh", marketPriceAsString)); diff --git a/core/src/main/java/haveno/core/util/VolumeUtil.java b/core/src/main/java/haveno/core/util/VolumeUtil.java index 38b75999..816390a6 100644 --- a/core/src/main/java/haveno/core/util/VolumeUtil.java +++ b/core/src/main/java/haveno/core/util/VolumeUtil.java @@ -38,33 +38,33 @@ import java.util.Locale; public class VolumeUtil { - private static final MonetaryFormat FIAT_VOLUME_FORMAT = new MonetaryFormat().shift(0).minDecimals(0).repeatOptionalDecimals(0, 0); - private static final MonetaryFormat TRADITIONAL_VOLUME_FORMAT = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); + private static final MonetaryFormat VOLUME_FORMAT_UNIT = new MonetaryFormat().shift(0).minDecimals(0).repeatOptionalDecimals(0, 0); + private static final MonetaryFormat VOLUME_FORMAT_PRECISE = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); private static double EXPONENT = Math.pow(10, TraditionalMoney.SMALLEST_UNIT_EXPONENT); // 1000000000000 with precision 8 public static Volume getAdjustedVolume(Volume volumeByAmount, String paymentMethodId) { if (PaymentMethod.isRoundedForAtmCash(paymentMethodId)) return VolumeUtil.getRoundedAtmCashVolume(volumeByAmount); - else if (CurrencyUtil.isFiatCurrency(volumeByAmount.getCurrencyCode())) - return VolumeUtil.getRoundedFiatVolume(volumeByAmount); + else if (CurrencyUtil.isVolumeRoundedToNearestUnit(volumeByAmount.getCurrencyCode())) + return VolumeUtil.getRoundedVolumeUnit(volumeByAmount); else if (CurrencyUtil.isTraditionalCurrency(volumeByAmount.getCurrencyCode())) - return VolumeUtil.getRoundedTraditionalVolume(volumeByAmount); + return VolumeUtil.getRoundedVolumePrecise(volumeByAmount); return volumeByAmount; } - public static Volume getRoundedFiatVolume(Volume volumeByAmount) { - // We want to get rounded to 1 unit of the fiat currency, e.g. 1 EUR. - return getAdjustedFiatVolume(volumeByAmount, 1); + public static Volume getRoundedVolumeUnit(Volume volumeByAmount) { + // We want to get rounded to 1 unit of the currency, e.g. 1 EUR. + return getAdjustedVolumeUnit(volumeByAmount, 1); } private static Volume getRoundedAtmCashVolume(Volume volumeByAmount) { // EUR has precision TraditionalMoney.SMALLEST_UNIT_EXPONENT and we want multiple of 10 so we divide by EXPONENT then // round and multiply with 10 - return getAdjustedFiatVolume(volumeByAmount, 10); + return getAdjustedVolumeUnit(volumeByAmount, 10); } - public static Volume getRoundedTraditionalVolume(Volume volumeByAmount) { + public static Volume getRoundedVolumePrecise(Volume volumeByAmount) { DecimalFormat decimalFormat = new DecimalFormat("#.####"); double roundedVolume = Double.parseDouble(decimalFormat.format(Double.parseDouble(volumeByAmount.toString()))); return Volume.parse(String.valueOf(roundedVolume), volumeByAmount.getCurrencyCode()); @@ -77,7 +77,7 @@ public class VolumeUtil { * units of 1 EUR, 10 means rounded to 10 EUR. * @return The adjusted Fiat volume */ - public static Volume getAdjustedFiatVolume(Volume volumeByAmount, int factor) { + public static Volume getAdjustedVolumeUnit(Volume volumeByAmount, int factor) { // Fiat currencies use precision TraditionalMoney.SMALLEST_UNIT_EXPONENT and we want multiple of factor so we divide // by EXPONENT * factor then round and multiply with factor long roundedVolume = Math.round((double) volumeByAmount.getValue() / (EXPONENT * factor)) * factor; @@ -168,6 +168,6 @@ public class VolumeUtil { } private static MonetaryFormat getMonetaryFormat(String currencyCode) { - return CurrencyUtil.isFiatCurrency(currencyCode) ? FIAT_VOLUME_FORMAT : TRADITIONAL_VOLUME_FORMAT; + return CurrencyUtil.isVolumeRoundedToNearestUnit(currencyCode) ? VOLUME_FORMAT_UNIT : VOLUME_FORMAT_PRECISE; } } diff --git a/core/src/main/java/haveno/core/util/coin/CoinUtil.java b/core/src/main/java/haveno/core/util/coin/CoinUtil.java index 4de06030..4ad56251 100644 --- a/core/src/main/java/haveno/core/util/coin/CoinUtil.java +++ b/core/src/main/java/haveno/core/util/coin/CoinUtil.java @@ -32,7 +32,7 @@ import java.math.BigInteger; import java.text.DecimalFormat; import static com.google.common.base.Preconditions.checkArgument; -import static haveno.core.util.VolumeUtil.getAdjustedFiatVolume; +import static haveno.core.util.VolumeUtil.getAdjustedVolumeUnit; public class CoinUtil { @@ -82,10 +82,10 @@ public class CoinUtil { public static BigInteger getRoundedAmount(BigInteger amount, Price price, long maxTradeLimit, String currencyCode, String paymentMethodId) { if (PaymentMethod.isRoundedForAtmCash(paymentMethodId)) { return getRoundedAtmCashAmount(amount, price, maxTradeLimit); - } else if (CurrencyUtil.isFiatCurrency(currencyCode)) { - return getRoundedFiatAmount(amount, price, maxTradeLimit); + } else if (CurrencyUtil.isVolumeRoundedToNearestUnit(currencyCode)) { + return getRoundedAmountUnit(amount, price, maxTradeLimit); } else if (CurrencyUtil.isTraditionalCurrency(currencyCode)) { - return getRoundedTraditionalAmount(amount, price, maxTradeLimit); + return getRoundedAmountPrecise(amount, price, maxTradeLimit); } return amount; } @@ -98,16 +98,16 @@ public class CoinUtil { * Calculate the possibly adjusted amount for {@code amount}, taking into account the * {@code price} and {@code maxTradeLimit} and {@code factor}. * - * @param amount Bitcoin amount which is a candidate for getting rounded. + * @param amount Monero amount which is a candidate for getting rounded. * @param price Price used in relation to that amount. - * @param maxTradeLimit The max. trade limit of the users account, in satoshis. + * @param maxTradeLimit The max. trade limit of the users account, in atomic units. * @return The adjusted amount */ - public static BigInteger getRoundedFiatAmount(BigInteger amount, Price price, long maxTradeLimit) { + public static BigInteger getRoundedAmountUnit(BigInteger amount, Price price, long maxTradeLimit) { return getAdjustedAmount(amount, price, maxTradeLimit, 1); } - public static BigInteger getRoundedTraditionalAmount(BigInteger amount, Price price, long maxTradeLimit) { + public static BigInteger getRoundedAmountPrecise(BigInteger amount, Price price, long maxTradeLimit) { DecimalFormat decimalFormat = new DecimalFormat("#.####"); double roundedXmrAmount = Double.parseDouble(decimalFormat.format(HavenoUtils.atomicUnitsToXmr(amount))); return HavenoUtils.xmrToAtomicUnits(roundedXmrAmount); @@ -154,8 +154,8 @@ public class CoinUtil { // We get the adjusted volume from our amount Volume volume = useSmallestUnitForAmount - ? getAdjustedFiatVolume(price.getVolumeByAmount(smallestUnitForAmount), factor) - : getAdjustedFiatVolume(price.getVolumeByAmount(amount), factor); + ? getAdjustedVolumeUnit(price.getVolumeByAmount(smallestUnitForAmount), factor) + : getAdjustedVolumeUnit(price.getVolumeByAmount(amount), factor); if (volume.getValue() <= 0) return BigInteger.valueOf(0); diff --git a/core/src/main/java/haveno/core/util/validation/FiatPriceValidator.java b/core/src/main/java/haveno/core/util/validation/AmountValidator4Decimals.java similarity index 91% rename from core/src/main/java/haveno/core/util/validation/FiatPriceValidator.java rename to core/src/main/java/haveno/core/util/validation/AmountValidator4Decimals.java index d14db6fa..1c9a26a6 100644 --- a/core/src/main/java/haveno/core/util/validation/FiatPriceValidator.java +++ b/core/src/main/java/haveno/core/util/validation/AmountValidator4Decimals.java @@ -19,7 +19,7 @@ package haveno.core.util.validation; import javax.inject.Inject; -public class FiatPriceValidator extends MonetaryValidator { +public class AmountValidator4Decimals extends MonetaryValidator { @Override public double getMinValue() { return 0.0001; @@ -33,6 +33,6 @@ public class FiatPriceValidator extends MonetaryValidator { } @Inject - public FiatPriceValidator() { + public AmountValidator4Decimals() { } } diff --git a/core/src/main/java/haveno/core/util/validation/NonFiatPriceValidator.java b/core/src/main/java/haveno/core/util/validation/AmountValidator8Decimals.java similarity index 90% rename from core/src/main/java/haveno/core/util/validation/NonFiatPriceValidator.java rename to core/src/main/java/haveno/core/util/validation/AmountValidator8Decimals.java index 6e154c8b..5a329918 100644 --- a/core/src/main/java/haveno/core/util/validation/NonFiatPriceValidator.java +++ b/core/src/main/java/haveno/core/util/validation/AmountValidator8Decimals.java @@ -19,7 +19,7 @@ package haveno.core.util.validation; import javax.inject.Inject; -public class NonFiatPriceValidator extends MonetaryValidator { +public class AmountValidator8Decimals extends MonetaryValidator { @Override public double getMinValue() { return 0.00000001; @@ -32,6 +32,6 @@ public class NonFiatPriceValidator extends MonetaryValidator { } @Inject - public NonFiatPriceValidator() { + public AmountValidator8Decimals() { } } diff --git a/desktop/src/main/java/haveno/desktop/main/account/content/notifications/MobileNotificationsView.java b/desktop/src/main/java/haveno/desktop/main/account/content/notifications/MobileNotificationsView.java index 3cd91242..ba20aa9c 100644 --- a/desktop/src/main/java/haveno/desktop/main/account/content/notifications/MobileNotificationsView.java +++ b/desktop/src/main/java/haveno/desktop/main/account/content/notifications/MobileNotificationsView.java @@ -40,8 +40,6 @@ import haveno.core.user.User; import haveno.core.util.FormattingUtils; import haveno.core.util.ParsingUtils; import haveno.core.util.PriceUtil; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; import haveno.core.util.validation.InputValidator; import haveno.desktop.common.view.ActivatableView; import haveno.desktop.common.view.FxmlView; @@ -313,9 +311,8 @@ public class MobileNotificationsView extends ActivatableView { TradeCurrency selectedItem = currencyComboBox.getSelectionModel().getSelectedItem(); if (selectedItem != null) { selectedPriceAlertTradeCurrency = selectedItem.getCode(); - boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(selectedPriceAlertTradeCurrency); - priceAlertHighInputTextField.setValidator(isFiatCurrency ? new FiatPriceValidator() : new NonFiatPriceValidator()); - priceAlertLowInputTextField.setValidator(isFiatCurrency ? new FiatPriceValidator() : new NonFiatPriceValidator()); + priceAlertHighInputTextField.setValidator(PriceUtil.getPriceValidator(selectedPriceAlertTradeCurrency)); + priceAlertLowInputTextField.setValidator(PriceUtil.getPriceValidator(selectedPriceAlertTradeCurrency)); } else { selectedPriceAlertTradeCurrency = null; } diff --git a/desktop/src/main/java/haveno/desktop/main/market/offerbook/OfferBookChartViewModel.java b/desktop/src/main/java/haveno/desktop/main/market/offerbook/OfferBookChartViewModel.java index aae4a050..0df8b455 100644 --- a/desktop/src/main/java/haveno/desktop/main/market/offerbook/OfferBookChartViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/market/offerbook/OfferBookChartViewModel.java @@ -257,15 +257,15 @@ class OfferBookChartViewModel extends ActivatableViewModel { } public int getMaxNumberOfPriceZeroDecimalsToColorize(Offer offer) { - return offer.isFiatOffer() - ? GUIUtil.FIAT_DECIMALS_WITH_ZEROS - : GUIUtil.CRYPTOS_DECIMALS_WITH_ZEROS; + return CurrencyUtil.isVolumeRoundedToNearestUnit(offer.getCurrencyCode()) + ? GUIUtil.NUM_DECIMALS_UNIT + : GUIUtil.NUM_DECIMALS_PRECISE; } public int getZeroDecimalsForPrice(Offer offer) { - return offer.isFiatOffer() - ? GUIUtil.FIAT_PRICE_DECIMALS_WITH_ZEROS - : GUIUtil.CRYPTOS_DECIMALS_WITH_ZEROS; + return CurrencyUtil.isPricePrecise(offer.getCurrencyCode()) + ? GUIUtil.NUM_DECIMALS_PRECISE + : GUIUtil.NUM_DECIMALS_PRICE_LESS_PRECISE; } public String getPrice(Offer offer) { diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java index 6ac76fc2..871b6af8 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java @@ -32,7 +32,6 @@ import haveno.core.offer.OfferDirection; import haveno.core.offer.OfferUtil; import haveno.core.offer.OpenOfferManager; import haveno.core.payment.PaymentAccount; -import haveno.core.payment.payload.PaymentMethod; import haveno.core.provider.price.PriceFeedService; import haveno.core.trade.HavenoUtils; import haveno.core.trade.handlers.TransactionResultHandler; @@ -685,8 +684,4 @@ public abstract class MutableOfferDataModel extends OfferDataModel { public void setReserveExactAmount(boolean reserveExactAmount) { this.reserveExactAmount = reserveExactAmount; } - - public boolean isUsingRoundedAtmCashAccount() { - return PaymentMethod.isRoundedForAtmCash(paymentAccount.getPaymentMethod().getId()); - } } diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java index 6f05f658..39928ec9 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferViewModel.java @@ -47,8 +47,8 @@ import haveno.core.util.PriceUtil; import haveno.core.util.VolumeUtil; import haveno.core.util.coin.CoinFormatter; import haveno.core.util.coin.CoinUtil; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; +import haveno.core.util.validation.AmountValidator8Decimals; +import haveno.core.util.validation.AmountValidator4Decimals; import haveno.core.util.validation.InputValidator; import haveno.core.util.validation.MonetaryValidator; import haveno.core.xmr.wallet.Restrictions; @@ -95,8 +95,8 @@ public abstract class MutableOfferViewModel ext private final Preferences preferences; protected final CoinFormatter btcFormatter; private final FiatVolumeValidator fiatVolumeValidator; - private final FiatPriceValidator fiatPriceValidator; - private final NonFiatPriceValidator nonFiatPriceValidator; + private final AmountValidator4Decimals amountValidator4Decimals; + private final AmountValidator8Decimals amountValidator8Decimals; protected final OfferUtil offerUtil; private String amountDescription; @@ -184,8 +184,8 @@ public abstract class MutableOfferViewModel ext @Inject public MutableOfferViewModel(M dataModel, FiatVolumeValidator fiatVolumeValidator, - FiatPriceValidator fiatPriceValidator, - NonFiatPriceValidator nonFiatPriceValidator, + AmountValidator4Decimals amountValidator4Decimals, + AmountValidator8Decimals amountValidator8Decimals, XmrValidator btcValidator, SecurityDepositValidator securityDepositValidator, PriceFeedService priceFeedService, @@ -197,8 +197,8 @@ public abstract class MutableOfferViewModel ext super(dataModel); this.fiatVolumeValidator = fiatVolumeValidator; - this.fiatPriceValidator = fiatPriceValidator; - this.nonFiatPriceValidator = nonFiatPriceValidator; + this.amountValidator4Decimals = amountValidator4Decimals; + this.amountValidator8Decimals = amountValidator8Decimals; this.xmrValidator = btcValidator; this.securityDepositValidator = securityDepositValidator; this.priceFeedService = priceFeedService; @@ -763,7 +763,7 @@ public abstract class MutableOfferViewModel ext InputValidator.ValidationResult result = PriceUtil.isTriggerPriceValid(triggerPriceAsString, marketPrice, dataModel.isSellOffer(), - dataModel.isTraditionalCurrency() + dataModel.getCurrencyCode() ); triggerPriceValidationResult.set(result); updateButtonDisableState(); @@ -1175,16 +1175,20 @@ public abstract class MutableOfferViewModel ext return getVolumeValidator().validate(input); } + // TODO: replace with PriceUtils and VolumeUtils? + private MonetaryValidator getPriceValidator() { - return CurrencyUtil.isFiatCurrency(getTradeCurrency().getCode()) ? fiatPriceValidator : nonFiatPriceValidator; + return CurrencyUtil.isPricePrecise(getTradeCurrency().getCode()) ? amountValidator8Decimals : amountValidator4Decimals; } private MonetaryValidator getVolumeValidator() { final String code = getTradeCurrency().getCode(); if (CurrencyUtil.isFiatCurrency(code)) { return fiatVolumeValidator; + } else if (CurrencyUtil.isVolumeRoundedToNearestUnit(code)) { + return amountValidator4Decimals; } else { - return nonFiatPriceValidator; + return amountValidator8Decimals; } } diff --git a/desktop/src/main/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModel.java index 00b9d678..a38f3d77 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModel.java @@ -27,8 +27,8 @@ import haveno.core.provider.price.PriceFeedService; import haveno.core.user.Preferences; import haveno.core.util.FormattingUtils; import haveno.core.util.coin.CoinFormatter; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; +import haveno.core.util.validation.AmountValidator8Decimals; +import haveno.core.util.validation.AmountValidator4Decimals; import haveno.desktop.Navigation; import haveno.desktop.common.model.ViewModel; import haveno.desktop.main.offer.MutableOfferViewModel; @@ -40,8 +40,8 @@ class CreateOfferViewModel extends MutableOfferViewModel i @Inject public CreateOfferViewModel(CreateOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, - FiatPriceValidator fiatPriceValidator, - NonFiatPriceValidator nonFiatPriceValidator, + AmountValidator4Decimals priceValidator4Decimals, + AmountValidator8Decimals priceValidator8Decimals, XmrValidator btcValidator, SecurityDepositValidator securityDepositValidator, PriceFeedService priceFeedService, @@ -52,8 +52,8 @@ class CreateOfferViewModel extends MutableOfferViewModel i OfferUtil offerUtil) { super(dataModel, fiatVolumeValidator, - fiatPriceValidator, - nonFiatPriceValidator, + priceValidator4Decimals, + priceValidator8Decimals, btcValidator, securityDepositValidator, priceFeedService, diff --git a/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java index 8477289d..a65909ec 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -427,7 +427,7 @@ abstract class OfferBookViewModel extends ActivatableViewModel { } int getNumberOfDecimalsForVolume(OfferBookListItem item) { - return item.getOffer().isFiatOffer() ? GUIUtil.FIAT_DECIMALS_WITH_ZEROS : GUIUtil.CRYPTOS_DECIMALS_WITH_ZEROS; + return CurrencyUtil.isVolumeRoundedToNearestUnit(item.getOffer().getCurrencyCode()) ? GUIUtil.NUM_DECIMALS_UNIT : GUIUtil.NUM_DECIMALS_PRECISE; } String getPaymentMethod(OfferBookListItem item) { diff --git a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferViewModel.java index ee24c3ef..2f59f80c 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -311,9 +311,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel im if (!isAmountEqualMinAmount(dataModel.getAmount().get()) && (!isAmountEqualMaxAmount(dataModel.getAmount().get()))) { // We only apply the rounding if the amount is variable (minAmount is lower as amount). // Otherwise we could get an amount lower then the minAmount set by rounding - BigInteger roundedAmount = dataModel.getOffer().isFiatOffer() ? - CoinUtil.getRoundedFiatAmount(dataModel.getAmount().get(), tradePrice, maxTradeLimit) : - CoinUtil.getRoundedTraditionalAmount(dataModel.getAmount().get(), tradePrice, maxTradeLimit); + BigInteger roundedAmount = CoinUtil.getRoundedAmount(dataModel.getAmount().get(), tradePrice, maxTradeLimit, dataModel.getOffer().getCurrencyCode(), dataModel.getOffer().getPaymentMethodId()); dataModel.applyAmount(roundedAmount); } amount.set(HavenoUtils.formatXmr(dataModel.getAmount().get())); @@ -582,9 +580,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel im && !isAmountEqualMinAmount(amount) && !isAmountEqualMaxAmount(amount)) { // We only apply the rounding if the amount is variable (minAmount is lower as amount). // Otherwise we could get an amount lower then the minAmount set by rounding - amount = dataModel.getOffer().isFiatOffer() ? - CoinUtil.getRoundedFiatAmount(amount, price, maxTradeLimit) : - CoinUtil.getRoundedTraditionalAmount(amount, price, maxTradeLimit); + amount = CoinUtil.getRoundedAmount(dataModel.getAmount().get(), price, maxTradeLimit, dataModel.getOffer().getCurrencyCode(), dataModel.getOffer().getPaymentMethodId()); } } dataModel.applyAmount(amount); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java b/desktop/src/main/java/haveno/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java index a3a0f6fe..6eafc192 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java @@ -29,8 +29,8 @@ import haveno.core.provider.price.PriceFeedService; import haveno.core.user.Preferences; import haveno.core.util.FormattingUtils; import haveno.core.util.coin.CoinFormatter; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; +import haveno.core.util.validation.AmountValidator8Decimals; +import haveno.core.util.validation.AmountValidator4Decimals; import haveno.desktop.Navigation; import haveno.desktop.main.offer.MutableOfferViewModel; import lombok.extern.slf4j.Slf4j; @@ -43,8 +43,8 @@ class DuplicateOfferViewModel extends MutableOfferViewModel { @Inject public EditOfferViewModel(EditOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, - FiatPriceValidator fiatPriceValidator, - NonFiatPriceValidator nonFiatPriceValidator, + AmountValidator4Decimals priceValidator4Decimals, + AmountValidator8Decimals priceValidator8Decimals, XmrValidator btcValidator, SecurityDepositValidator securityDepositValidator, PriceFeedService priceFeedService, @@ -55,8 +55,8 @@ class EditOfferViewModel extends MutableOfferViewModel { OfferUtil offerUtil) { super(dataModel, fiatVolumeValidator, - fiatPriceValidator, - nonFiatPriceValidator, + priceValidator4Decimals, + priceValidator8Decimals, btcValidator, securityDepositValidator, priceFeedService, diff --git a/desktop/src/main/java/haveno/desktop/util/GUIUtil.java b/desktop/src/main/java/haveno/desktop/util/GUIUtil.java index d2c40e61..4ba30e62 100644 --- a/desktop/src/main/java/haveno/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/haveno/desktop/util/GUIUtil.java @@ -126,9 +126,9 @@ public class GUIUtil { public final static String OPEN_WEB_PAGE_KEY = "warnOpenURLWhenTorEnabled"; - public final static int FIAT_DECIMALS_WITH_ZEROS = 0; - public final static int FIAT_PRICE_DECIMALS_WITH_ZEROS = 3; - public final static int CRYPTOS_DECIMALS_WITH_ZEROS = 7; + public final static int NUM_DECIMALS_UNIT = 0; + public final static int NUM_DECIMALS_PRICE_LESS_PRECISE = 3; + public final static int NUM_DECIMALS_PRECISE = 7; public final static int AMOUNT_DECIMALS_WITH_ZEROS = 3; public final static int AMOUNT_DECIMALS = 4; diff --git a/desktop/src/test/java/haveno/desktop/MarketsPrintTool.java b/desktop/src/test/java/haveno/desktop/MarketsPrintTool.java index 03baf445..02a080b5 100644 --- a/desktop/src/test/java/haveno/desktop/MarketsPrintTool.java +++ b/desktop/src/test/java/haveno/desktop/MarketsPrintTool.java @@ -39,7 +39,7 @@ public class MarketsPrintTool { final Collection allSortedTraditionalCurrencies = CurrencyUtil.getAllSortedTraditionalCurrencies(); final Stream traditionalStream = allSortedTraditionalCurrencies.stream() - .filter(e -> !e.getCurrency().getCurrencyCode().equals("XMR")) // TODO (woodser): update to XMR + .filter(e -> !e.getCode().equals("XMR")) .map(e -> new MarketCurrency("xmr_" + e.getCode().toLowerCase(), e.getName(), e.getCode())) .distinct(); diff --git a/desktop/src/test/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModelTest.java b/desktop/src/test/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModelTest.java index afca5829..9cda92f1 100644 --- a/desktop/src/test/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModelTest.java +++ b/desktop/src/test/java/haveno/desktop/main/offer/createoffer/CreateOfferViewModelTest.java @@ -37,8 +37,8 @@ import haveno.core.user.Preferences; import haveno.core.user.User; import haveno.core.util.coin.CoinFormatter; import haveno.core.util.coin.ImmutableCoinFormatter; -import haveno.core.util.validation.NonFiatPriceValidator; -import haveno.core.util.validation.FiatPriceValidator; +import haveno.core.util.validation.AmountValidator8Decimals; +import haveno.core.util.validation.AmountValidator4Decimals; import haveno.core.util.validation.InputValidator; import haveno.core.xmr.model.XmrAddressEntry; import haveno.core.xmr.wallet.XmrWalletService; @@ -72,8 +72,8 @@ public class CreateOfferViewModelTest { Res.setup(); final XmrValidator btcValidator = new XmrValidator(); - final NonFiatPriceValidator nonFiatPriceValidator = new NonFiatPriceValidator(); - final FiatPriceValidator fiatPriceValidator = new FiatPriceValidator(); + final AmountValidator8Decimals priceValidator8Decimals = new AmountValidator8Decimals(); + final AmountValidator4Decimals priceValidator4Decimals = new AmountValidator4Decimals(); XmrAddressEntry addressEntry = mock(XmrAddressEntry.class); XmrWalletService xmrWalletService = mock(XmrWalletService.class); @@ -121,8 +121,8 @@ public class CreateOfferViewModelTest { model = new CreateOfferViewModel(dataModel, null, - fiatPriceValidator, - nonFiatPriceValidator, + priceValidator4Decimals, + priceValidator8Decimals, btcValidator, securityDepositValidator, priceFeedService, diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 7ec85347..b50aba8e 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -1786,7 +1786,6 @@ message CryptoCurrency { } message TraditionalCurrency { - Currency currency = 1; } message Country {