diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateService.java b/core/src/main/java/bisq/core/dao/state/DaoStateService.java index f53d3cfa70f..c4e226c746c 100644 --- a/core/src/main/java/bisq/core/dao/state/DaoStateService.java +++ b/core/src/main/java/bisq/core/dao/state/DaoStateService.java @@ -35,8 +35,8 @@ import bisq.core.dao.state.model.governance.Issuance; import bisq.core.dao.state.model.governance.IssuanceType; import bisq.core.dao.state.model.governance.ParamChange; -import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Coin; @@ -924,7 +924,7 @@ public Coin getParamValueAsCoin(Param param, String paramValue) { } public double getParamValueAsPercentDouble(String paramValue) { - return BSFormatter.parsePercentStringToDouble(paramValue); + return ParsingUtils.parsePercentStringToDouble(paramValue); } public int getParamValueAsBlock(String paramValue) { diff --git a/core/src/main/java/bisq/core/monetary/Altcoin.java b/core/src/main/java/bisq/core/monetary/Altcoin.java index 55ca1f48cc0..87c4e754263 100644 --- a/core/src/main/java/bisq/core/monetary/Altcoin.java +++ b/core/src/main/java/bisq/core/monetary/Altcoin.java @@ -17,7 +17,7 @@ package bisq.core.monetary; -import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Monetary; import org.bitcoinj.utils.MonetaryFormat; @@ -89,7 +89,7 @@ public String getCurrencyCode() { * @throws IllegalArgumentException if you try to specify fractional satoshis, or a value out of range. */ public static Altcoin parseAltcoin(final String currencyCode, String input) { - String cleaned = BSFormatter.convertCharsForNumber(input); + String cleaned = ParsingUtils.convertCharsForNumber(input); try { long val = new BigDecimal(cleaned).movePointRight(SMALLEST_UNIT_EXPONENT) .toBigIntegerExact().longValue(); diff --git a/core/src/main/java/bisq/core/monetary/Price.java b/core/src/main/java/bisq/core/monetary/Price.java index cc9a7750575..6e588353681 100644 --- a/core/src/main/java/bisq/core/monetary/Price.java +++ b/core/src/main/java/bisq/core/monetary/Price.java @@ -18,7 +18,7 @@ package bisq.core.monetary; import bisq.core.locale.CurrencyUtil; -import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Monetary; @@ -58,7 +58,7 @@ public Price(Monetary monetary) { * @return The parsed Price. */ public static Price parse(String currencyCode, String input) { - String cleaned = BSFormatter.convertCharsForNumber(input); + String cleaned = ParsingUtils.convertCharsForNumber(input); if (CurrencyUtil.isFiatCurrency(currencyCode)) return new Price(Fiat.parseFiat(currencyCode, cleaned)); else diff --git a/core/src/main/java/bisq/core/monetary/Volume.java b/core/src/main/java/bisq/core/monetary/Volume.java index cd79a0b2115..bd2bc752e04 100644 --- a/core/src/main/java/bisq/core/monetary/Volume.java +++ b/core/src/main/java/bisq/core/monetary/Volume.java @@ -18,7 +18,7 @@ package bisq.core.monetary; import bisq.core.locale.CurrencyUtil; -import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Monetary; import org.bitcoinj.utils.Fiat; @@ -36,7 +36,7 @@ public Volume(Monetary monetary) { } public static Volume parse(String input, String currencyCode) { - String cleaned = BSFormatter.convertCharsForNumber(input); + String cleaned = ParsingUtils.convertCharsForNumber(input); if (CurrencyUtil.isFiatCurrency(currencyCode)) return new Volume(Fiat.parseFiat(currencyCode, cleaned)); else diff --git a/core/src/main/java/bisq/core/util/BSFormatter.java b/core/src/main/java/bisq/core/util/BSFormatter.java index 866b09eb630..98ed6f0d5ab 100644 --- a/core/src/main/java/bisq/core/util/BSFormatter.java +++ b/core/src/main/java/bisq/core/util/BSFormatter.java @@ -52,6 +52,7 @@ import java.util.TimeZone; import java.util.stream.Collectors; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -66,7 +67,8 @@ public class BSFormatter { // Input of a group separator (1,123,45) lead to an validation error. // Note: BtcFormat was intended to be used, but it lead to many problems (automatic format to mBit, // no way to remove grouping separator). It seems to be not optimal for user input formatting. - protected MonetaryFormat coinFormat; + @Getter + protected MonetaryFormat monetaryFormat; // protected String currencyCode = CurrencyUtil.getDefaultFiatCurrencyAsCode(); @@ -77,7 +79,7 @@ public class BSFormatter { @Inject public BSFormatter() { - coinFormat = BisqEnvironment.getParameters().getMonetaryFormat(); + monetaryFormat = BisqEnvironment.getParameters().getMonetaryFormat(); } @@ -99,7 +101,7 @@ public String formatCoin(long value, MonetaryFormat coinFormat) { } public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) { - return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, coinFormat); + return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, monetaryFormat); } public static String formatCoin(Coin coin, @@ -129,11 +131,11 @@ public static String formatCoin(Coin coin, } public String formatCoinWithCode(Coin coin) { - return formatCoinWithCode(coin, coinFormat); + return formatCoinWithCode(coin, monetaryFormat); } public String formatCoinWithCode(long value) { - return formatCoinWithCode(Coin.valueOf(value), coinFormat); + return formatCoinWithCode(Coin.valueOf(value), monetaryFormat); } public static String formatCoinWithCode(long value, MonetaryFormat coinFormat) { @@ -155,24 +157,6 @@ public static String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) { } } - public Coin parseToCoin(String input) { - return parseToCoin(input, coinFormat); - } - - public Coin parseToCoin(String input, MonetaryFormat coinFormat) { - if (input != null && input.length() > 0) { - try { - return coinFormat.parse(cleanDoubleInput(input)); - } catch (Throwable t) { - log.warn("Exception at parseToBtc: " + t.toString()); - return Coin.ZERO; - } - } else { - return Coin.ZERO; - } - } - - /////////////////////////////////////////////////////////////////////////////////////////// // FIAT /////////////////////////////////////////////////////////////////////////////////////////// @@ -194,10 +178,10 @@ public static String formatFiat(Fiat fiat, MonetaryFormat format, boolean append } } - protected static Fiat parseToFiat(String input, String currencyCode) { + private static Fiat parseToFiat(String input, String currencyCode) { if (input != null && input.length() > 0) { try { - return Fiat.parseFiat(currencyCode, cleanDoubleInput(input)); + return Fiat.parseFiat(currencyCode, ParsingUtils.cleanDoubleInput(input)); } catch (Exception e) { log.warn("Exception at parseToFiat: " + e.toString()); return Fiat.valueOf(currencyCode, 0); @@ -220,7 +204,7 @@ protected static Fiat parseToFiat(String input, String currencyCode) { public static Fiat parseToFiatWithPrecision(String input, String currencyCode) { if (input != null && input.length() > 0) { try { - return parseToFiat(new BigDecimal(cleanDoubleInput(input)).setScale(2, BigDecimal.ROUND_HALF_UP).toString(), + return parseToFiat(new BigDecimal(ParsingUtils.cleanDoubleInput(input)).setScale(2, BigDecimal.ROUND_HALF_UP).toString(), currencyCode); } catch (Throwable t) { log.warn("Exception at parseToFiatWithPrecision: " + t.toString()); @@ -387,60 +371,6 @@ public static String formatToPercent(double value) { return decimalFormat.format(MathUtils.roundDouble(value * 100.0, 2)).replace(",", "."); } - public static double parseNumberStringToDouble(String input) throws NumberFormatException { - return Double.parseDouble(cleanDoubleInput(input)); - } - - public static double parsePercentStringToDouble(String percentString) throws NumberFormatException { - String input = percentString.replace("%", ""); - input = cleanDoubleInput(input); - double value = Double.parseDouble(input); - return MathUtils.roundDouble(value / 100d, 4); - } - - public static long parsePriceStringToLong(BSFormatter bsFormatter, - String currencyCode, - String amount, - int precision) { - if (amount == null || amount.isEmpty()) - return 0; - - long value = 0; - try { - double amountValue = Double.parseDouble(amount); - amount = BSFormatter.formatRoundedDoubleWithPrecision(amountValue, precision); - value = Price.parse(currencyCode, amount).getValue(); - } catch (NumberFormatException ignore) { - // expected NumberFormatException if input is not a number - } catch (Throwable t) { - log.error("parsePriceStringToLong: " + t.toString()); - } - - return value; - } - - public static String convertCharsForNumber(String input) { - // Some languages like finnish use the long dash for the minus - input = input.replace("−", "-"); - input = StringUtils.deleteWhitespace(input); - return input.replace(",", "."); - } - - public static String cleanDoubleInput(String input) { - input = convertCharsForNumber(input); - if (input.equals(".")) - input = input.replace(".", "0."); - if (input.equals("-.")) - input = input.replace("-.", "-0."); - // don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific - // notation (1.0E-6) which screw up coinFormat.parse - //noinspection ResultOfMethodCallIgnored - // Just called to check if we have a valid double, throws exception otherwise - //noinspection ResultOfMethodCallIgnored - Double.parseDouble(input); - return input; - } - public static String formatDurationAsWords(long durationMillis) { return formatDurationAsWords(durationMillis, false, true); } diff --git a/core/src/main/java/bisq/core/util/BsqFormatter.java b/core/src/main/java/bisq/core/util/BsqFormatter.java index 7f2524598e0..8dd90644434 100644 --- a/core/src/main/java/bisq/core/util/BsqFormatter.java +++ b/core/src/main/java/bisq/core/util/BsqFormatter.java @@ -61,12 +61,12 @@ public BsqFormatter() { GlobalSettings.localeProperty().addListener((observable, oldValue, newValue) -> setFormatter(newValue)); setFormatter(GlobalSettings.getLocale()); - btcCoinFormat = super.coinFormat; + btcCoinFormat = super.monetaryFormat; final String baseCurrencyCode = BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode(); switch (baseCurrencyCode) { case "BTC": - coinFormat = new MonetaryFormat().shift(6).code(6, "BSQ").minDecimals(2); + monetaryFormat = new MonetaryFormat().shift(6).code(6, "BSQ").minDecimals(2); break; default: throw new RuntimeException("baseCurrencyCode not defined. baseCurrencyCode=" + baseCurrencyCode); @@ -123,11 +123,11 @@ public String formatMarketCap(MarketPrice bsqPriceMarketPrice, MarketPrice fiatM } public String formatBSQSatoshis(long satoshi) { - return super.formatCoin(satoshi, coinFormat); + return super.formatCoin(satoshi, monetaryFormat); } public String formatBSQSatoshisWithCode(long satoshi) { - return super.formatCoinWithCode(satoshi, coinFormat); + return super.formatCoinWithCode(satoshi, monetaryFormat); } public String formatBTCSatoshis(long satoshi) { @@ -147,7 +147,7 @@ public String formatBTC(Coin coin) { } public Coin parseToBTC(String input) { - return super.parseToCoin(input, btcCoinFormat); + return ParsingUtils.parseToCoin(input, btcCoinFormat); } public void validateBtcInput(String input) throws ProposalValidationException { @@ -155,12 +155,12 @@ public void validateBtcInput(String input) throws ProposalValidationException { } public void validateBsqInput(String input) throws ProposalValidationException { - validateCoinInput(input, this.coinFormat); + validateCoinInput(input, this.monetaryFormat); } private void validateCoinInput(String input, MonetaryFormat coinFormat) throws ProposalValidationException { try { - coinFormat.parse(cleanDoubleInput(input)); + coinFormat.parse(ParsingUtils.cleanDoubleInput(input)); } catch (Throwable t) { throw new ProposalValidationException("Invalid format for a " + coinFormat.code() + " value"); } @@ -172,11 +172,11 @@ public String formatParamValue(Param param, String value) { // In case we add a new param old clients will not know that enum and fall back to UNDEFINED. return Res.get("shared.na"); case BSQ: - return formatCoinWithCode(parseToCoin(value)); + return formatCoinWithCode(ParsingUtils.parseToCoin(value, this)); case BTC: return formatBTCWithCode(parseToBTC(value)); case PERCENT: - return formatToPercentWithSymbol(parsePercentStringToDouble(value)); + return formatToPercentWithSymbol(ParsingUtils.parsePercentStringToDouble(value)); case BLOCK: return Res.get("dao.param.blocks", Integer.parseInt(value)); case ADDRESS: @@ -190,7 +190,7 @@ public String formatParamValue(Param param, String value) { public Coin parseParamValueToCoin(Param param, String inputValue) { switch (param.getParamType()) { case BSQ: - return parseToCoin(inputValue); + return ParsingUtils.parseToCoin(inputValue, this); case BTC: return parseToBTC(inputValue); default: @@ -216,7 +216,7 @@ public String parseParamValueToString(Param param, String inputValue) throws Pro case BTC: return formatBTC(parseParamValueToCoin(param, inputValue)); case PERCENT: - return formatToPercent(parsePercentStringToDouble(inputValue)); + return formatToPercent(ParsingUtils.parsePercentStringToDouble(inputValue)); case BLOCK: return Integer.toString(parseParamValueToBlocks(param, inputValue)); case ADDRESS: diff --git a/core/src/main/java/bisq/core/util/ParsingUtils.java b/core/src/main/java/bisq/core/util/ParsingUtils.java new file mode 100644 index 00000000000..c63e5bf138f --- /dev/null +++ b/core/src/main/java/bisq/core/util/ParsingUtils.java @@ -0,0 +1,83 @@ +package bisq.core.util; + +import bisq.core.monetary.Price; + +import bisq.common.util.MathUtils; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; + +import org.apache.commons.lang3.StringUtils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ParsingUtils { + public static Coin parseToCoin(String input, BSFormatter bsFormatter) { + return parseToCoin(input, bsFormatter.getMonetaryFormat()); + } + + public static Coin parseToCoin(String input, MonetaryFormat coinFormat) { + if (input != null && input.length() > 0) { + try { + return coinFormat.parse(cleanDoubleInput(input)); + } catch (Throwable t) { + log.warn("Exception at parseToBtc: " + t.toString()); + return Coin.ZERO; + } + } else { + return Coin.ZERO; + } + } + + public static double parseNumberStringToDouble(String input) throws NumberFormatException { + return Double.parseDouble(cleanDoubleInput(input)); + } + + public static double parsePercentStringToDouble(String percentString) throws NumberFormatException { + String input = percentString.replace("%", ""); + input = cleanDoubleInput(input); + double value = Double.parseDouble(input); + return MathUtils.roundDouble(value / 100d, 4); + } + + public static long parsePriceStringToLong(String currencyCode, String amount, int precision) { + if (amount == null || amount.isEmpty()) + return 0; + + long value = 0; + try { + double amountValue = Double.parseDouble(amount); + amount = BSFormatter.formatRoundedDoubleWithPrecision(amountValue, precision); + value = Price.parse(currencyCode, amount).getValue(); + } catch (NumberFormatException ignore) { + // expected NumberFormatException if input is not a number + } catch (Throwable t) { + log.error("parsePriceStringToLong: " + t.toString()); + } + + return value; + } + + public static String convertCharsForNumber(String input) { + // Some languages like finnish use the long dash for the minus + input = input.replace("−", "-"); + input = StringUtils.deleteWhitespace(input); + return input.replace(",", "."); + } + + public static String cleanDoubleInput(String input) { + input = convertCharsForNumber(input); + if (input.equals(".")) + input = input.replace(".", "0."); + if (input.equals("-.")) + input = input.replace("-.", "-0."); + // don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific + // notation (1.0E-6) which screw up coinFormat.parse + //noinspection ResultOfMethodCallIgnored + // Just called to check if we have a valid double, throws exception otherwise + //noinspection ResultOfMethodCallIgnored + Double.parseDouble(input); + return input; + } +} diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/notifications/MobileNotificationsView.java b/desktop/src/main/java/bisq/desktop/main/account/content/notifications/MobileNotificationsView.java index e2da49d0e0f..a311d6f5d3c 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/notifications/MobileNotificationsView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/notifications/MobileNotificationsView.java @@ -48,6 +48,7 @@ import bisq.core.user.Preferences; import bisq.core.user.User; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.InputValidator; import bisq.common.UserThread; @@ -347,7 +348,7 @@ private void onPaymentAccountSelected() { private void onAddMarketAlert() { PaymentAccount paymentAccount = paymentAccountsComboBox.getSelectionModel().getSelectedItem(); - double percentAsDouble = BSFormatter.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()); + double percentAsDouble = ParsingUtils.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()); int triggerValue = (int) Math.round(percentAsDouble * 10000); boolean isBuyOffer = offerTypeRadioButtonsToggleGroup.getSelectedToggle() == buyOffersRadioButton; MarketAlertFilter marketAlertFilter = new MarketAlertFilter(paymentAccount, triggerValue, isBuyOffer); @@ -510,7 +511,7 @@ public PaymentAccount fromString(String string) { marketAlertTriggerFocusListener = (observable, oldValue, newValue) -> { if (oldValue && !newValue) { try { - double percentAsDouble = BSFormatter.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100; + double percentAsDouble = ParsingUtils.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100; marketAlertTriggerInputTextField.setText(BSFormatter.formatRoundedDoubleWithPrecision(percentAsDouble, 2) + "%"); } catch (Throwable ignore) { } @@ -747,7 +748,7 @@ private long getPriceAsLong(InputTextField inputTextField) { try { String inputValue = inputTextField.getText(); if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) { - double priceAsDouble = BSFormatter.parseNumberStringToDouble(inputValue); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue); String currencyCode = selectedPriceAlertTradeCurrency; int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : 2; @@ -755,7 +756,7 @@ private long getPriceAsLong(InputTextField inputTextField) { // E.g. if input is 5555.5555 it will be rounded to 5555.55 and we use that as the value for comparing // low and high price... String stringValue = BSFormatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision); - return BSFormatter.parsePriceStringToLong(formatter, currencyCode, stringValue, precision); + return ParsingUtils.parsePriceStringToLong(currencyCode, stringValue, precision); } else { return 0; } @@ -768,7 +769,7 @@ private void applyPriceFormatting(InputTextField inputTextField) { try { String inputValue = inputTextField.getText(); if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) { - double priceAsDouble = BSFormatter.parseNumberStringToDouble(inputValue); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue); String currencyCode = selectedPriceAlertTradeCurrency; int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : 2; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationView.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationView.java index db30a5569fe..a4d84749dea 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationView.java @@ -38,6 +38,7 @@ import bisq.core.locale.Res; import bisq.core.user.Preferences; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.HexStringValidator; import bisq.core.util.validation.IntegerValidator; @@ -170,7 +171,7 @@ protected void activate() { bsqWalletService.addBsqBalanceListener(this); lockupButton.setOnAction((event) -> { - Coin lockupAmount = bsqFormatter.parseToCoin(amountInputTextField.getText()); + Coin lockupAmount = ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter); int lockupTime = Integer.parseInt(timeInputTextField.getText()); byte[] salt = Utilities.decodeFromHex(saltInputTextField.getText()); bondingViewUtils.lockupBondForReputation(lockupAmount, diff --git a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetFeeView.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetFeeView.java index 6a843bb842f..5988bf6f28e 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetFeeView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetFeeView.java @@ -36,6 +36,7 @@ import bisq.core.locale.Res; import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.common.app.DevEnv; @@ -273,7 +274,7 @@ private void updateButtonState() { } private Coin getListingFee() { - return bsqFormatter.parseToCoin(feeAmountInputTextField.getText()); + return ParsingUtils.parseToCoin(feeAmountInputTextField.getText(), bsqFormatter); } private void doPublishFeeTx(Transaction transaction) { diff --git a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java index 1c82da633f7..7ac3097ce24 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnView.java @@ -38,6 +38,7 @@ import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.InputValidator; import bisq.common.app.DevEnv; @@ -273,7 +274,7 @@ private void updateButtonState() { } private Coin getAmountFee() { - return bsqFormatter.parseToCoin(amountInputTextField.getText()); + return ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter); } private void doPublishFeeTx(Transaction transaction, String preImageAsString) { diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java index 4219d86c406..7b9c513d2dc 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/make/MakeProposalView.java @@ -52,6 +52,7 @@ import bisq.core.locale.Res; import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.asset.Asset; @@ -395,13 +396,13 @@ private ProposalWithTransaction getProposalWithTransaction(ProposalType proposal "proposalDisplay.requestedBsqTextField must not be null"); return daoFacade.getCompensationProposalWithTransaction(name, link, - bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText())); + ParsingUtils.parseToCoin(proposalDisplay.requestedBsqTextField.getText(), bsqFormatter)); case REIMBURSEMENT_REQUEST: checkNotNull(proposalDisplay.requestedBsqTextField, "proposalDisplay.requestedBsqTextField must not be null"); return daoFacade.getReimbursementProposalWithTransaction(name, link, - bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText())); + ParsingUtils.parseToCoin(proposalDisplay.requestedBsqTextField.getText(), bsqFormatter)); case CHANGE_PARAM: checkNotNull(proposalDisplay.paramComboBox, "proposalDisplay.paramComboBox must no tbe null"); diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsView.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsView.java index d5d28609e59..1023e79e778 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsView.java @@ -55,6 +55,7 @@ import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -463,7 +464,7 @@ private void showHowToSetStakeForVotingPopup() { } private void onVote() { - Coin stake = bsqFormatter.parseToCoin(stakeInputTextField.getText()); + Coin stake = ParsingUtils.parseToCoin(stakeInputTextField.getText(), bsqFormatter); try { // We create a dummy tx to get the miningFee for displaying it at the confirmation popup Tuple2 miningFeeAndTxSize = daoFacade.getBlindVoteMiningFeeAndTxSize(stake); diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java index 24de472f155..7ba3c38e197 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/send/BsqSendView.java @@ -47,6 +47,7 @@ import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; import bisq.core.util.CoinUtil; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -234,7 +235,7 @@ private void addSendBsqGroup() { // TODO break up in methods if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) { String receiversAddressString = bsqFormatter.getAddressFromBsqAddress(receiversAddressInputTextField.getText()).toString(); - Coin receiverAmount = bsqFormatter.parseToCoin(amountInputTextField.getText()); + Coin receiverAmount = ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter); try { Transaction preparedSendTx = bsqWalletService.getPreparedSendBsqTx(receiversAddressString, receiverAmount); Transaction txWithBtcFee = btcWalletService.completePreparedSendBsqTx(preparedSendTx, true); diff --git a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java index 0cf2230120b..6d80df920ec 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java @@ -36,6 +36,7 @@ import bisq.core.provider.fee.FeeService; import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -232,7 +233,7 @@ protected void activate() { walletService.addBalanceListener(balanceListener); amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> { - addressTextField.setAmountAsCoin(formatter.parseToCoin(t)); + addressTextField.setAmountAsCoin(ParsingUtils.parseToCoin(t, formatter)); updateQRCode(); }); @@ -301,7 +302,7 @@ private void updateList() { } private Coin getAmountAsCoin() { - return formatter.parseToCoin(amountTextField.getText()); + return ParsingUtils.parseToCoin(amountTextField.getText(), formatter); } @NotNull diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java index f3565535d0a..02e0e595966 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java @@ -41,6 +41,7 @@ import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; import bisq.core.util.CoinUtil; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -246,7 +247,7 @@ public void onBalanceChanged(Coin balance, Transaction tx) { amountListener = (observable, oldValue, newValue) -> { if (amountTextField.focusedProperty().get()) { try { - amountAsCoin = formatter.parseToCoin(amountTextField.getText()); + amountAsCoin = ParsingUtils.parseToCoin(amountTextField.getText(), formatter); } catch (Throwable t) { log.error("Error at amountTextField input. " + t.toString()); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java index 660220ea35d..70f972af3a4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java @@ -53,6 +53,7 @@ import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.InputValidator; import bisq.network.p2p.P2PService; @@ -316,7 +317,7 @@ private void createListeners() { if (marketPrice != null && marketPrice.isRecentExternalPriceAvailable()) { double marketPriceAsDouble = marketPrice.getPrice(); try { - double priceAsDouble = BSFormatter.parseNumberStringToDouble(price.get()); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(price.get()); double relation = priceAsDouble / marketPriceAsDouble; final OfferPayload.Direction compareDirection = CurrencyUtil.isCryptoCurrency(currencyCode) ? OfferPayload.Direction.SELL : @@ -342,7 +343,7 @@ private void createListeners() { if (inputIsMarketBasedPrice) { try { if (!newValue.isEmpty() && !newValue.equals("-")) { - double percentage = BSFormatter.parsePercentStringToDouble(newValue); + double percentage = ParsingUtils.parsePercentStringToDouble(newValue); if (percentage >= 1 || percentage <= -1) { new Popup<>().warning(Res.get("popup.warning.tooLargePercentageValue") + "\n" + Res.get("popup.warning.examplePercentageValue")) @@ -866,7 +867,7 @@ void onFocusOutBuyerSecurityDepositTextField(boolean oldValue, boolean newValue) if (result.isValid) { double defaultSecurityDeposit = Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount()); String key = "buyerSecurityDepositIsLowerAsDefault"; - double depositAsDouble = BSFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get()); + double depositAsDouble = ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get()); if (preferences.showAgain(key) && depositAsDouble < defaultSecurityDeposit) { String postfix = dataModel.isBuyOffer() ? Res.get("createOffer.tooLowSecDeposit.makerIsBuyer") : @@ -906,7 +907,7 @@ private void applyBuyerSecurityDepositOnFocusOut() { public boolean isPriceInRange() { if (marketPriceMargin.get() != null && !marketPriceMargin.get().isEmpty()) { - if (Math.abs(BSFormatter.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) { + if (Math.abs(ParsingUtils.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) { displayPriceOutOfRangePopup(); return false; } else { @@ -1130,7 +1131,7 @@ private void setVolumeToModel() { private void setBuyerSecurityDepositToModel() { if (buyerSecurityDeposit.get() != null && !buyerSecurityDeposit.get().isEmpty()) { - dataModel.setBuyerSecurityDeposit(BSFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get())); + dataModel.setBuyerSecurityDeposit(ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get())); } else { dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount())); } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java index 09cab0c8301..af8d6cf43df 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -37,6 +37,7 @@ import bisq.core.offer.Offer; import bisq.core.trade.Contract; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import bisq.common.UserThread; import bisq.common.util.Tuple2; @@ -357,8 +358,8 @@ private void removePayoutAmountListeners() { } private boolean isPayoutAmountValid() { - Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText()); - Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText()); + Coin buyerAmount = ParsingUtils.parseToCoin(buyerPayoutAmountInputTextField.getText(), formatter); + Coin sellerAmount = ParsingUtils.parseToCoin(sellerPayoutAmountInputTextField.getText(), formatter); Contract contract = dispute.getContract(); Coin tradeAmount = contract.getTradeAmount(); Offer offer = new Offer(contract.getOfferPayload()); @@ -371,8 +372,8 @@ private boolean isPayoutAmountValid() { private void applyCustomAmounts(InputTextField inputTextField) { Contract contract = dispute.getContract(); - Coin buyerAmount = formatter.parseToCoin(buyerPayoutAmountInputTextField.getText()); - Coin sellerAmount = formatter.parseToCoin(sellerPayoutAmountInputTextField.getText()); + Coin buyerAmount = ParsingUtils.parseToCoin(buyerPayoutAmountInputTextField.getText(), formatter); + Coin sellerAmount = ParsingUtils.parseToCoin(sellerPayoutAmountInputTextField.getText(), formatter); Offer offer = new Offer(contract.getOfferPayload()); Coin available = contract.getTradeAmount(). add(offer.getBuyerSecurityDeposit()) diff --git a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index b04e8562235..8da003572d5 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -47,6 +47,7 @@ import bisq.core.user.BlockChainExplorer; import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.IntegerValidator; import bisq.common.UserThread; @@ -314,7 +315,7 @@ public BaseCurrencyNetwork fromString(String string) { deviationListener = (observable, oldValue, newValue) -> { try { - double value = BSFormatter.parsePercentStringToDouble(newValue); + double value = ParsingUtils.parsePercentStringToDouble(newValue); final double maxDeviation = 0.5; if (value <= maxDeviation) { preferences.setMaxPriceDistanceInPercent(value); diff --git a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java index 184e8b41431..7a1f1f8721a 100644 --- a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java +++ b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java @@ -9,6 +9,7 @@ import bisq.core.offer.Offer; import bisq.core.offer.OfferPayload; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Monetary; @@ -265,7 +266,7 @@ public static String getFeeWithFiatAmount(Coin makerFeeAsCoin, */ public static Coin parseToCoinWith4Decimals(String input, BSFormatter bsFormatter) { try { - return Coin.valueOf(new BigDecimal(bsFormatter.parseToCoin(BSFormatter.cleanDoubleInput(input)).value).setScale(-scale - 1, + return Coin.valueOf(new BigDecimal(ParsingUtils.parseToCoin(ParsingUtils.cleanDoubleInput(input), bsFormatter).value).setScale(-scale - 1, BigDecimal.ROUND_HALF_UP).setScale(scale + 1, BigDecimal.ROUND_HALF_UP).toBigInteger().longValue()); } catch (Throwable t) { if (input != null && input.length() > 0) @@ -275,7 +276,7 @@ public static Coin parseToCoinWith4Decimals(String input, BSFormatter bsFormatte } public static boolean hasBtcValidDecimals(String input, BSFormatter bsFormatter) { - return bsFormatter.parseToCoin(input).equals(parseToCoinWith4Decimals(input, bsFormatter)); + return ParsingUtils.parseToCoin(input, bsFormatter).equals(parseToCoinWith4Decimals(input, bsFormatter)); } /** @@ -286,6 +287,6 @@ public static boolean hasBtcValidDecimals(String input, BSFormatter bsFormatter) * @return The transformed coin */ public static Coin reduceTo4Decimals(Coin coin, BSFormatter bsFormatter) { - return bsFormatter.parseToCoin(bsFormatter.formatCoin(coin)); + return ParsingUtils.parseToCoin(bsFormatter.formatCoin(coin), bsFormatter); } } diff --git a/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java b/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java index 4749354771d..0ab87710ae4 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java @@ -21,6 +21,7 @@ import bisq.core.locale.Res; import bisq.core.util.BsqFormatter; import bisq.core.util.CoinUtil; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Coin; @@ -53,7 +54,7 @@ protected double getMinValue() { public BsqValidator(BsqFormatter bsqFormatter) { this.bsqFormatter = bsqFormatter; // Limit to avoid overflows - setMaxValue(bsqFormatter.parseToCoin("10000000")); + setMaxValue(ParsingUtils.parseToCoin("10000000", bsqFormatter)); } public void setMinValue(@NotNull Coin minValue) { @@ -94,7 +95,7 @@ public ValidationResult validate(String input) { } private ValidationResult validateIfAboveDust(String input) { - final Coin coin = bsqFormatter.parseToCoin(input); + final Coin coin = ParsingUtils.parseToCoin(input, bsqFormatter); if (Restrictions.isAboveDust(coin)) return new ValidationResult(true); else @@ -113,7 +114,7 @@ private ValidationResult validateIfNotFractionalBtcValue(String input) { private ValidationResult validateIfNotExceedsMaxBtcValue(String input) { try { - final Coin coin = bsqFormatter.parseToCoin(input); + final Coin coin = ParsingUtils.parseToCoin(input, bsqFormatter); if (maxValue != null && coin.compareTo(maxValue) > 0) return new ValidationResult(false, Res.get("validation.btc.toLarge", bsqFormatter.formatCoinWithCode(maxValue))); else @@ -125,7 +126,7 @@ private ValidationResult validateIfNotExceedsMaxBtcValue(String input) { private ValidationResult validateIfSufficientAvailableBalance(String input) { try { - final Coin coin = bsqFormatter.parseToCoin(input); + final Coin coin = ParsingUtils.parseToCoin(input, bsqFormatter); if (availableBalance != null && availableBalance.compareTo(coin) < 0) return new ValidationResult(false, Res.get("validation.bsq.insufficientBalance", bsqFormatter.formatCoinWithCode(availableBalance))); @@ -138,7 +139,7 @@ private ValidationResult validateIfSufficientAvailableBalance(String input) { private ValidationResult validateIfNotBelowMinValue(String input) { try { - final Coin coin = bsqFormatter.parseToCoin(input); + final Coin coin = ParsingUtils.parseToCoin(input, bsqFormatter); if (minValue != null && coin.compareTo(minValue) < 0) return new ValidationResult(false, Res.get("validation.bsq.amountBelowMinAmount", bsqFormatter.formatCoinWithCode(minValue))); diff --git a/desktop/src/main/java/bisq/desktop/util/validation/NumberValidator.java b/desktop/src/main/java/bisq/desktop/util/validation/NumberValidator.java index 9a4d5496fa4..1aaa4162fbf 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/NumberValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/NumberValidator.java @@ -18,7 +18,7 @@ package bisq.desktop.util.validation; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.InputValidator; /** @@ -30,7 +30,7 @@ public abstract class NumberValidator extends InputValidator { protected String cleanInput(String input) { - return BSFormatter.convertCharsForNumber(input); + return ParsingUtils.convertCharsForNumber(input); } protected ValidationResult validateIfNumber(String input) { diff --git a/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java b/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java index 2b64219bbf4..0abfec1a4ef 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java @@ -21,6 +21,7 @@ import bisq.core.locale.Res; import bisq.core.payment.PaymentAccount; import bisq.core.util.BSFormatter; +import bisq.core.util.ParsingUtils; import javax.inject.Inject; @@ -58,7 +59,7 @@ public ValidationResult validate(String input) { private ValidationResult validateIfNotTooLowPercentageValue(String input) { try { - double percentage = BSFormatter.parsePercentStringToDouble(input); + double percentage = ParsingUtils.parsePercentStringToDouble(input); double minPercentage = Restrictions.getMinBuyerSecurityDepositAsPercent(paymentAccount); if (percentage < minPercentage) return new ValidationResult(false, @@ -72,7 +73,7 @@ private ValidationResult validateIfNotTooLowPercentageValue(String input) { private ValidationResult validateIfNotTooHighPercentageValue(String input) { try { - double percentage = BSFormatter.parsePercentStringToDouble(input); + double percentage = ParsingUtils.parsePercentStringToDouble(input); double maxPercentage = Restrictions.getMaxBuyerSecurityDepositAsPercent(paymentAccount); if (percentage > maxPercentage) return new ValidationResult(false,