From 1f0d1935b89c89c69e8305c11ac1c2d1481ea4d8 Mon Sep 17 00:00:00 2001 From: Justin Carter Date: Sun, 8 Sep 2019 08:30:08 +0200 Subject: [PATCH] Dissolve BSFormatter BSFormatter was a statefull catch all type class with a huge interface. It had dependencies to globals and very many classes depended on it. It was hard to reason about code flow due to how tangled up things were, making refactoring attempts of higher level classes difficult. To Dissolve BSFormatter the following changes were made: - Move functions that only have 1 call-site to private functions on the caller. - Make functions that do not depend on local state static. - Move functions that are only depended on by the desktop project to DisplayUtils. - Move functions that are Parsing related to ParsingUtils. - Move remaining static functions to FormattingUtils. - Create interface CoinFormatter and class ImmutableCoinFormatter to handle statefull functions. - Remove dependency to globals by instantiating an instance in CoreModule and inject it via Guice. --- core/src/main/java/bisq/core/CoreModule.java | 6 + .../main/java/bisq/core/app/BisqSetup.java | 8 +- .../java/bisq/core/app/WalletAppSetup.java | 11 +- .../dao/governance/asset/AssetService.java | 2 +- .../proposal/param/ChangeParamValidator.java | 2 +- .../bisq/core/dao/presentation/DaoUtil.java | 16 +- .../bisq/core/dao/state/DaoStateService.java | 5 +- .../java/bisq/core/locale/CurrencyUtil.java | 25 + .../main/java/bisq/core/monetary/Altcoin.java | 4 +- .../main/java/bisq/core/monetary/Price.java | 4 +- .../main/java/bisq/core/monetary/Volume.java | 4 +- .../alerts/market/MarketAlerts.java | 12 +- .../alerts/price/PriceAlert.java | 11 +- .../main/java/bisq/core/offer/OfferUtil.java | 17 +- .../presentation/BalancePresentation.java | 7 +- .../main/java/bisq/core/util/BSFormatter.java | 809 ------------------ .../java/bisq/core/util/FormattingUtils.java | 298 +++++++ .../java/bisq/core/util/ParsingUtils.java | 86 ++ .../core/util/{ => coin}/BsqFormatter.java | 141 ++- .../bisq/core/util/coin/CoinFormatter.java | 19 + .../bisq/core/util/{ => coin}/CoinUtil.java | 2 +- .../util/coin/ImmutableCoinFormatter.java | 50 ++ .../param/ChangeParamValidatorTest.java | 2 +- .../core/dao/state/DaoStateServiceTest.java | 2 +- .../bisq/core/util/CoinCryptoUtilsTest.java | 2 + .../bisq/core/util/FormattingUtilsTest.java | 69 ++ .../util/coin/ImmutableCoinFormatterTest.java | 33 + .../main/java/bisq/desktop/DesktopModule.java | 6 + .../desktop/components/BalanceTextField.java | 7 +- .../BalanceWithConfirmationTextField.java | 7 +- .../ColoredDecimalPlacesWithZerosText.java | 9 +- .../bisq/desktop/components/PeerInfoIcon.java | 16 +- .../desktop/components/PeerInfoIconSmall.java | 6 +- .../paymentmethods/AdvancedCashForm.java | 5 +- .../components/paymentmethods/AliPayForm.java | 5 +- .../components/paymentmethods/AssetsForm.java | 8 +- .../components/paymentmethods/BankForm.java | 5 +- .../paymentmethods/CashDepositForm.java | 5 +- .../paymentmethods/ChaseQuickPayForm.java | 5 +- .../paymentmethods/ClearXchangeForm.java | 5 +- .../components/paymentmethods/F2FForm.java | 5 +- .../paymentmethods/FasterPaymentsForm.java | 5 +- .../GeneralAccountNumberForm.java | 5 +- .../paymentmethods/GeneralBankForm.java | 5 +- .../paymentmethods/GeneralSepaForm.java | 5 +- .../paymentmethods/HalCashForm.java | 5 +- .../paymentmethods/InteracETransferForm.java | 5 +- .../paymentmethods/MoneyBeamForm.java | 5 +- .../paymentmethods/MoneyGramForm.java | 5 +- .../paymentmethods/NationalBankForm.java | 4 +- .../paymentmethods/PaymentMethodForm.java | 13 +- .../paymentmethods/PerfectMoneyForm.java | 5 +- .../paymentmethods/PopmoneyForm.java | 5 +- .../paymentmethods/PromptPayForm.java | 5 +- .../paymentmethods/RevolutForm.java | 5 +- .../paymentmethods/SameBankForm.java | 5 +- .../components/paymentmethods/SepaForm.java | 5 +- .../paymentmethods/SepaInstantForm.java | 5 +- .../paymentmethods/SpecificBankForm.java | 5 +- .../components/paymentmethods/SwishForm.java | 5 +- .../USPostalMoneyOrderForm.java | 5 +- .../components/paymentmethods/UpholdForm.java | 5 +- .../paymentmethods/WeChatPayForm.java | 5 +- .../paymentmethods/WesternUnionForm.java | 5 +- .../java/bisq/desktop/main/Chat/Chat.java | 10 +- .../main/java/bisq/desktop/main/MainView.java | 10 +- .../java/bisq/desktop/main/MainViewModel.java | 12 +- .../altcoinaccounts/AltCoinAccountsView.java | 8 +- .../fiataccounts/FiatAccountsView.java | 8 +- .../ManageMarketAlertsWindow.java | 12 +- .../MobileNotificationsView.java | 32 +- .../main/dao/bonding/BondingViewUtils.java | 22 +- .../main/dao/bonding/bonds/BondListItem.java | 6 +- .../main/dao/bonding/bonds/BondsView.java | 2 +- .../reputation/MyReputationListItem.java | 6 +- .../bonding/reputation/MyReputationView.java | 5 +- .../dao/bonding/roles/RoleDetailsWindow.java | 5 +- .../main/dao/bonding/roles/RolesView.java | 2 +- .../dao/burnbsq/assetfee/AssetFeeView.java | 13 +- .../dao/burnbsq/assetfee/AssetListItem.java | 2 +- .../proofofburn/MyProofOfBurnListItem.java | 6 +- .../proofofburn/ProofOfBurnListItem.java | 6 +- .../burnbsq/proofofburn/ProofOfBurnView.java | 14 +- .../economy/dashboard/BsqDashboardView.java | 12 +- .../main/dao/economy/supply/SupplyView.java | 2 +- .../main/dao/governance/ProposalDisplay.java | 2 +- .../dashboard/GovernanceDashboardView.java | 13 +- .../dao/governance/make/MakeProposalView.java | 18 +- .../proposals/ProposalsListItem.java | 2 +- .../governance/proposals/ProposalsView.java | 17 +- .../dao/governance/result/CycleListItem.java | 5 +- .../governance/result/ProposalListItem.java | 2 +- .../dao/governance/result/VoteListItem.java | 2 +- .../dao/governance/result/VoteResultView.java | 5 +- .../bisq/desktop/main/dao/news/NewsView.java | 10 +- .../main/dao/wallet/BsqBalanceUtil.java | 2 +- .../dao/wallet/receive/BsqReceiveView.java | 11 +- .../main/dao/wallet/send/BsqSendView.java | 26 +- .../main/dao/wallet/tx/BsqTxListItem.java | 12 +- .../desktop/main/dao/wallet/tx/BsqTxView.java | 16 +- .../arbitrator/ArbitratorDisputeView.java | 13 +- .../disputes/trader/TraderDisputeView.java | 24 +- .../main/funds/deposit/DepositListItem.java | 5 +- .../main/funds/deposit/DepositView.java | 15 +- .../main/funds/locked/LockedListItem.java | 7 +- .../desktop/main/funds/locked/LockedView.java | 11 +- .../main/funds/reserved/ReservedListItem.java | 7 +- .../main/funds/reserved/ReservedView.java | 11 +- .../TransactionListItemFactory.java | 8 +- .../transactions/TransactionsListItem.java | 10 +- .../funds/transactions/TransactionsView.java | 8 +- .../funds/withdrawal/WithdrawalListItem.java | 7 +- .../main/funds/withdrawal/WithdrawalView.java | 13 +- .../bisq/desktop/main/market/MarketView.java | 24 +- .../market/offerbook/OfferBookChartView.java | 17 +- .../offerbook/OfferBookChartViewModel.java | 11 +- .../main/market/spread/SpreadView.java | 9 +- .../main/market/spread/SpreadViewModel.java | 12 +- .../main/market/trades/TradesChartsView.java | 36 +- .../market/trades/TradesChartsViewModel.java | 13 +- .../main/offer/MutableOfferDataModel.java | 15 +- .../desktop/main/offer/MutableOfferView.java | 16 +- .../main/offer/MutableOfferViewModel.java | 78 +- .../createoffer/CreateOfferDataModel.java | 8 +- .../offer/createoffer/CreateOfferView.java | 10 +- .../createoffer/CreateOfferViewModel.java | 10 +- .../main/offer/offerbook/OfferBookView.java | 22 +- .../offer/offerbook/OfferBookViewModel.java | 38 +- .../offer/takeoffer/TakeOfferDataModel.java | 2 +- .../main/offer/takeoffer/TakeOfferView.java | 15 +- .../offer/takeoffer/TakeOfferViewModel.java | 44 +- .../main/overlays/windows/ContractWindow.java | 22 +- .../windows/DisputeSummaryWindow.java | 33 +- .../overlays/windows/EmptyWalletWindow.java | 13 +- .../overlays/windows/OfferDetailsWindow.java | 73 +- .../windows/ProposalResultsWindow.java | 5 +- .../windows/SelectProposalWindow.java | 2 +- .../overlays/windows/TradeDetailsWindow.java | 52 +- .../closedtrades/ClosedTradesView.java | 13 +- .../closedtrades/ClosedTradesViewModel.java | 24 +- .../editoffer/EditOfferDataModel.java | 10 +- .../portfolio/editoffer/EditOfferView.java | 9 +- .../editoffer/EditOfferViewModel.java | 20 +- .../failedtrades/FailedTradesViewModel.java | 22 +- .../openoffer/OpenOffersViewModel.java | 26 +- .../pendingtrades/PendingTradesView.java | 16 +- .../pendingtrades/PendingTradesViewModel.java | 54 +- .../steps/buyer/BuyerStep2View.java | 3 +- .../steps/buyer/BuyerStep4View.java | 7 +- .../steps/seller/SellerStep3View.java | 3 +- .../presentation/MarketPricePresentation.java | 16 +- .../settings/network/NetworkSettingsView.java | 16 +- .../settings/network/P2pNetworkListItem.java | 15 +- .../settings/preferences/PreferencesView.java | 20 +- .../bisq/desktop/util/BsqAddressHelper.java | 41 + .../java/bisq/desktop/util/DisplayUtils.java | 221 +++++ .../main/java/bisq/desktop/util/GUIUtil.java | 21 +- .../util/validation/BsqAddressValidator.java | 12 +- .../desktop/util/validation/BsqValidator.java | 15 +- .../desktop/util/validation/BtcValidator.java | 8 +- .../util/validation/NumberValidator.java | 4 +- .../validation/SecurityDepositValidator.java | 18 +- .../java/bisq/desktop/GuiceSetupTest.java | 4 +- .../OfferBookChartViewModelTest.java | 25 +- .../market/spread/SpreadViewModelTest.java | 19 +- .../trades/TradesChartsViewModelTest.java | 4 +- .../createoffer/CreateOfferViewModelTest.java | 16 +- .../offerbook/OfferBookViewModelTest.java | 29 +- .../editoffer/EditOfferDataModelTest.java | 5 +- .../bisq/desktop/util/BSFormatterTest.java | 199 ----- .../bisq/desktop/util/DisplayUtilsTest.java | 134 +++ .../util/validation/BtcValidatorTest.java | 5 +- 172 files changed, 2134 insertions(+), 1840 deletions(-) delete mode 100644 core/src/main/java/bisq/core/util/BSFormatter.java create mode 100644 core/src/main/java/bisq/core/util/FormattingUtils.java create mode 100644 core/src/main/java/bisq/core/util/ParsingUtils.java rename core/src/main/java/bisq/core/util/{ => coin}/BsqFormatter.java (66%) create mode 100644 core/src/main/java/bisq/core/util/coin/CoinFormatter.java rename core/src/main/java/bisq/core/util/{ => coin}/CoinUtil.java (99%) create mode 100644 core/src/main/java/bisq/core/util/coin/ImmutableCoinFormatter.java create mode 100644 core/src/test/java/bisq/core/util/FormattingUtilsTest.java create mode 100644 core/src/test/java/bisq/core/util/coin/ImmutableCoinFormatterTest.java create mode 100644 desktop/src/main/java/bisq/desktop/util/BsqAddressHelper.java create mode 100644 desktop/src/main/java/bisq/desktop/util/DisplayUtils.java delete mode 100644 desktop/src/test/java/bisq/desktop/util/BSFormatterTest.java create mode 100644 desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java diff --git a/core/src/main/java/bisq/core/CoreModule.java b/core/src/main/java/bisq/core/CoreModule.java index b73c25dd2cf..56df032da14 100644 --- a/core/src/main/java/bisq/core/CoreModule.java +++ b/core/src/main/java/bisq/core/CoreModule.java @@ -31,6 +31,9 @@ import bisq.core.proto.persistable.CorePersistenceProtoResolver; import bisq.core.trade.TradeModule; import bisq.core.user.Preferences; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.crypto.EncryptionServiceModule; import bisq.network.p2p.P2PModule; @@ -68,6 +71,9 @@ protected void configure() { bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class); + CoinFormatter btcFormatter = new ImmutableCoinFormatter(BisqEnvironment.getParameters().getMonetaryFormat()); + bind(CoinFormatter.class).annotatedWith(named(FormattingUtils.BTC_FORMATTER_KEY)).toInstance(btcFormatter); + File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR)); bind(File.class).annotatedWith(named(Storage.STORAGE_DIR)).toInstance(storageDir); diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index cd4d2f4e1ac..c1c8cd87aa8 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -52,7 +52,8 @@ import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import bisq.network.crypto.DecryptedDataTuple; import bisq.network.crypto.EncryptionService; @@ -73,6 +74,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import com.google.common.net.InetAddresses; @@ -156,7 +158,7 @@ public interface BisqSetupCompleteListener { private final AssetService assetService; private final TorSetup torSetup; private final TradeLimits tradeLimits; - private final BSFormatter formatter; + private final CoinFormatter formatter; @Setter @Nullable private Consumer displayTacHandler; @@ -235,7 +237,7 @@ public BisqSetup(P2PNetworkSetup p2PNetworkSetup, AssetService assetService, TorSetup torSetup, TradeLimits tradeLimits, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.p2PNetworkSetup = p2PNetworkSetup; diff --git a/core/src/main/java/bisq/core/app/WalletAppSetup.java b/core/src/main/java/bisq/core/app/WalletAppSetup.java index f9ad67f2fd8..baf6a930f20 100644 --- a/core/src/main/java/bisq/core/app/WalletAppSetup.java +++ b/core/src/main/java/bisq/core/app/WalletAppSetup.java @@ -21,7 +21,9 @@ import bisq.core.btc.wallet.WalletsManager; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import org.bitcoinj.core.VersionMessage; import org.bitcoinj.store.BlockStoreException; @@ -57,7 +59,6 @@ public class WalletAppSetup { private final WalletsSetup walletsSetup; private final BisqEnvironment bisqEnvironment; private final Preferences preferences; - private final BSFormatter formatter; @SuppressWarnings("FieldCanBeLocal") private MonadicBinding btcInfoBinding; @@ -79,13 +80,11 @@ public class WalletAppSetup { public WalletAppSetup(WalletsManager walletsManager, WalletsSetup walletsSetup, BisqEnvironment bisqEnvironment, - Preferences preferences, - BSFormatter formatter) { + Preferences preferences) { this.walletsManager = walletsManager; this.walletsSetup = walletsSetup; this.bisqEnvironment = bisqEnvironment; this.preferences = preferences; - this.formatter = formatter; this.useTorForBTC.set(preferences.getUseTorForBitcoinJ()); } @@ -120,7 +119,7 @@ void init(@Nullable Consumer chainFileLockedExceptionHandler, result = Res.get("mainView.footer.btcInfo", peers, Res.get("mainView.footer.btcInfo.synchronizingWith"), - getBtcNetworkAsString() + ": " + formatter.formatToPercentWithSymbol(percentage)); + getBtcNetworkAsString() + ": " + FormattingUtils.formatToPercentWithSymbol(percentage)); } else { result = Res.get("mainView.footer.btcInfo", peers, diff --git a/core/src/main/java/bisq/core/dao/governance/asset/AssetService.java b/core/src/main/java/bisq/core/dao/governance/asset/AssetService.java index 7b9390da6cd..f8bd0e00b49 100644 --- a/core/src/main/java/bisq/core/dao/governance/asset/AssetService.java +++ b/core/src/main/java/bisq/core/dao/governance/asset/AssetService.java @@ -38,7 +38,7 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.trade.statistics.TradeStatistics2; import bisq.core.trade.statistics.TradeStatisticsManager; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.Timer; import bisq.common.UserThread; diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java b/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java index 626d30a5186..230ee8903dd 100644 --- a/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java +++ b/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java @@ -28,7 +28,7 @@ import bisq.core.dao.state.model.governance.ChangeParamProposal; import bisq.core.dao.state.model.governance.Proposal; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.BtcAddressValidator; import bisq.core.util.validation.InputValidator; diff --git a/core/src/main/java/bisq/core/dao/presentation/DaoUtil.java b/core/src/main/java/bisq/core/dao/presentation/DaoUtil.java index 819b2548e48..44a02536e47 100644 --- a/core/src/main/java/bisq/core/dao/presentation/DaoUtil.java +++ b/core/src/main/java/bisq/core/dao/presentation/DaoUtil.java @@ -20,7 +20,7 @@ import bisq.core.dao.DaoFacade; import bisq.core.dao.state.model.governance.DaoPhase; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; import java.text.SimpleDateFormat; @@ -32,7 +32,7 @@ */ public class DaoUtil { - public static String getNextPhaseDuration(int height, DaoPhase.Phase phase, DaoFacade daoFacade, BSFormatter formatter) { + public static String getNextPhaseDuration(int height, DaoPhase.Phase phase, DaoFacade daoFacade) { final int currentCycleDuration = daoFacade.getCurrentCycleDuration(); long start = daoFacade.getFirstBlockOfPhaseForDisplay(height, phase) + currentCycleDuration; long end = daoFacade.getLastBlockOfPhaseForDisplay(height, phase) + currentCycleDuration; @@ -40,22 +40,22 @@ public static String getNextPhaseDuration(int height, DaoPhase.Phase phase, DaoF long now = new Date().getTime(); SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault()); SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault()); - String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); - String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); + String startDateTime = FormattingUtils.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); + String endDateTime = FormattingUtils.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); return Res.get("dao.cycle.phaseDurationWithoutBlocks", start, end, startDateTime, endDateTime); } - public static String getPhaseDuration(int height, DaoPhase.Phase phase, DaoFacade daoFacade, BSFormatter formatter) { + public static String getPhaseDuration(int height, DaoPhase.Phase phase, DaoFacade daoFacade) { long start = daoFacade.getFirstBlockOfPhaseForDisplay(height, phase); long end = daoFacade.getLastBlockOfPhaseForDisplay(height, phase); long duration = daoFacade.getDurationForPhaseForDisplay(phase); long now = new Date().getTime(); SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault()); SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm", Locale.getDefault()); - String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); - String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); - String durationTime = formatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false); + String startDateTime = FormattingUtils.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); + String endDateTime = FormattingUtils.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter); + String durationTime = FormattingUtils.formatDurationAsWords(duration * 10 * 60 * 1000, false, false); return Res.get("dao.cycle.phaseDuration", duration, durationTime, start, end, startDateTime, endDateTime); } } 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 96559828f19..ecb33ae229e 100644 --- a/core/src/main/java/bisq/core/dao/state/DaoStateService.java +++ b/core/src/main/java/bisq/core/dao/state/DaoStateService.java @@ -35,7 +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.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.ParsingUtils; import org.bitcoinj.core.Coin; @@ -923,7 +924,7 @@ public Coin getParamValueAsCoin(Param param, String paramValue) { } public double getParamValueAsPercentDouble(String paramValue) { - return bsqFormatter.parsePercentStringToDouble(paramValue); + return ParsingUtils.parsePercentStringToDouble(paramValue); } public int getParamValueAsBlock(String paramValue) { diff --git a/core/src/main/java/bisq/core/locale/CurrencyUtil.java b/core/src/main/java/bisq/core/locale/CurrencyUtil.java index ac8a8350174..b98b5b3d893 100644 --- a/core/src/main/java/bisq/core/locale/CurrencyUtil.java +++ b/core/src/main/java/bisq/core/locale/CurrencyUtil.java @@ -507,4 +507,29 @@ public static List getActiveSortedCryptoCurrencies(AssetService .filter(e -> !filterManager.isCurrencyBanned(e.getCode())) .collect(Collectors.toList()); } + + public static String getCurrencyPair(String currencyCode) { + if (isFiatCurrency(currencyCode)) + return Res.getBaseCurrencyCode() + "/" + currencyCode; + else + return currencyCode + "/" + Res.getBaseCurrencyCode(); + } + + public static String getCounterCurrency(String currencyCode) { + if (isFiatCurrency(currencyCode)) + return currencyCode; + else + return Res.getBaseCurrencyCode(); + } + + public static String getPriceWithCurrencyCode(String currencyCode) { + return getPriceWithCurrencyCode(currencyCode, "shared.priceInCurForCur"); + } + + public static String getPriceWithCurrencyCode(String currencyCode, String translationKey) { + if (isCryptoCurrency(currencyCode)) + return Res.get(translationKey, Res.getBaseCurrencyCode(), currencyCode); + else + return Res.get(translationKey, currencyCode, Res.getBaseCurrencyCode()); + } } 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/notifications/alerts/market/MarketAlerts.java b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java index fad6fc2a2f1..521bfc86992 100644 --- a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java +++ b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java @@ -30,7 +30,7 @@ import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.crypto.KeyRing; import bisq.common.util.MathUtils; @@ -53,17 +53,15 @@ public class MarketAlerts { private final User user; private final PriceFeedService priceFeedService; private final KeyRing keyRing; - private final BSFormatter formatter; @Inject public MarketAlerts(OfferBookService offerBookService, MobileNotificationService mobileNotificationService, - User user, PriceFeedService priceFeedService, KeyRing keyRing, BSFormatter formatter) { + User user, PriceFeedService priceFeedService, KeyRing keyRing) { this.offerBookService = offerBookService; this.mobileNotificationService = mobileNotificationService; this.user = user; this.priceFeedService = priceFeedService; this.keyRing = keyRing; - this.formatter = formatter; } @@ -180,9 +178,9 @@ else if (!isFiatCurrency && !isSellOffer) ratio = Math.abs(ratio); String msg = Res.get("account.notifications.marketAlert.message.msg", direction, - formatter.getCurrencyPair(currencyCode), - formatter.formatPrice(offerPrice), - formatter.formatToPercentWithSymbol(ratio / 10000d), + CurrencyUtil.getCurrencyPair(currencyCode), + FormattingUtils.formatPrice(offerPrice), + FormattingUtils.formatToPercentWithSymbol(ratio / 10000d), marketDir, Res.get(offer.getPaymentMethod().getId()), shortOfferId); diff --git a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java index f52a048f60e..0fb8407b3b9 100644 --- a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java +++ b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java @@ -26,7 +26,8 @@ import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.util.MathUtils; @@ -43,14 +44,12 @@ public class PriceAlert { private final PriceFeedService priceFeedService; private final MobileNotificationService mobileNotificationService; private final User user; - private final BSFormatter formatter; @Inject - public PriceAlert(PriceFeedService priceFeedService, MobileNotificationService mobileNotificationService, User user, BSFormatter formatter) { + public PriceAlert(PriceFeedService priceFeedService, MobileNotificationService mobileNotificationService, User user) { this.priceFeedService = priceFeedService; this.user = user; this.mobileNotificationService = mobileNotificationService; - this.formatter = formatter; } public void onAllServicesInitialized() { @@ -70,8 +69,8 @@ private void update() { if (priceAsLong > filter.getHigh() || priceAsLong < filter.getLow()) { String msg = Res.get("account.notifications.priceAlert.message.msg", currencyName, - formatter.formatMarketPrice(priceAsDouble, currencyCode), - formatter.getCurrencyPair(currencyCode)); + FormattingUtils.formatMarketPrice(priceAsDouble, currencyCode), + CurrencyUtil.getCurrencyPair(currencyCode)); MobileMessage message = new MobileMessage(Res.get("account.notifications.priceAlert.message.title", currencyName), msg, MobileMessageType.PRICE); diff --git a/core/src/main/java/bisq/core/offer/OfferUtil.java b/core/src/main/java/bisq/core/offer/OfferUtil.java index 7d26b6cad39..4925ad3316b 100644 --- a/core/src/main/java/bisq/core/offer/OfferUtil.java +++ b/core/src/main/java/bisq/core/offer/OfferUtil.java @@ -32,9 +32,8 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.statistics.ReferralIdService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinUtil; import bisq.network.p2p.P2PService; @@ -306,18 +305,6 @@ public static Optional getFeeInUserFiatCurrency(Coin makerFee, boolean i } } - public static String getFeeWithFiatAmount(Coin makerFeeAsCoin, Optional optionalFeeInFiat, BSFormatter formatter) { - String fee = makerFeeAsCoin != null ? formatter.formatCoinWithCode(makerFeeAsCoin) : Res.get("shared.na"); - String feeInFiatAsString; - if (optionalFeeInFiat != null && optionalFeeInFiat.isPresent()) { - feeInFiatAsString = formatter.formatVolumeWithCode(optionalFeeInFiat.get()); - } else { - feeInFiatAsString = Res.get("shared.na"); - } - return Res.get("feeOptionWindow.fee", fee, feeInFiatAsString); - } - - public static Map getExtraDataMap(AccountAgeWitnessService accountAgeWitnessService, ReferralIdService referralIdService, PaymentAccount paymentAccount, diff --git a/core/src/main/java/bisq/core/presentation/BalancePresentation.java b/core/src/main/java/bisq/core/presentation/BalancePresentation.java index 3b42d19ac6a..07a7badd07a 100644 --- a/core/src/main/java/bisq/core/presentation/BalancePresentation.java +++ b/core/src/main/java/bisq/core/presentation/BalancePresentation.java @@ -18,9 +18,12 @@ package bisq.core.presentation; import bisq.core.btc.Balances; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import javax.inject.Inject; +import javax.inject.Named; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; @@ -38,7 +41,7 @@ public class BalancePresentation { private final StringProperty lockedBalance = new SimpleStringProperty(); @Inject - public BalancePresentation(Balances balances, BSFormatter formatter) { + public BalancePresentation(Balances balances, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { balances.getAvailableBalance().addListener((observable, oldValue, newValue) -> { String value = formatter.formatCoinWithCode(newValue); // If we get full precision the BTC postfix breaks layout so we omit it diff --git a/core/src/main/java/bisq/core/util/BSFormatter.java b/core/src/main/java/bisq/core/util/BSFormatter.java deleted file mode 100644 index ffe731b639d..00000000000 --- a/core/src/main/java/bisq/core/util/BSFormatter.java +++ /dev/null @@ -1,809 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.core.util; - -import bisq.core.app.BisqEnvironment; -import bisq.core.locale.CurrencyUtil; -import bisq.core.locale.GlobalSettings; -import bisq.core.locale.LanguageUtil; -import bisq.core.locale.Res; -import bisq.core.monetary.Altcoin; -import bisq.core.monetary.Price; -import bisq.core.monetary.Volume; -import bisq.core.offer.Offer; -import bisq.core.offer.OfferPayload; - -import bisq.network.p2p.NodeAddress; - -import bisq.common.util.MathUtils; - -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.Monetary; -import org.bitcoinj.utils.Fiat; -import org.bitcoinj.utils.MonetaryFormat; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.DateUtils; -import org.apache.commons.lang3.time.DurationFormatUtils; - -import java.text.DateFormat; -import java.text.DecimalFormat; - -import java.math.BigDecimal; - -import java.util.Date; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; -import java.util.stream.Collectors; - -import lombok.extern.slf4j.Slf4j; - -import org.jetbrains.annotations.NotNull; - -@Slf4j -@Singleton -public class BSFormatter { - public final static String RANGE_SEPARATOR = " - "; - - protected boolean useMilliBit; - protected int scale = 3; - - // We don't support localized formatting. Format is always using "." as decimal mark and no grouping separator. - // Input of "," as decimal mark (like in german locale) will be replaced with ".". - // 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; - - // protected String currencyCode = CurrencyUtil.getDefaultFiatCurrencyAsCode(); - - protected final MonetaryFormat fiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); - protected final MonetaryFormat fiatVolumeFormat = new MonetaryFormat().shift(0).minDecimals(2).repeatOptionalDecimals(0, 0); - protected final MonetaryFormat altcoinFormat = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0); - protected final DecimalFormat decimalFormat = new DecimalFormat("#.#"); - - - @Inject - public BSFormatter() { - coinFormat = BisqEnvironment.getParameters().getMonetaryFormat(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // BTC - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatCoin(Coin coin) { - return formatCoin(coin, -1); - } - - @NotNull - public String formatCoin(Coin coin, int decimalPlaces) { - return formatCoin(coin, decimalPlaces, false, 0); - } - - public String formatCoin(long value, MonetaryFormat coinFormat) { - return formatCoin(Coin.valueOf(value), -1, false, 0, coinFormat); - } - - public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) { - return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, coinFormat); - } - - public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits, MonetaryFormat coinFormat) { - String formattedCoin = ""; - - if (coin != null) { - try { - if (decimalPlaces < 0 || decimalPlaces > 4) { - formattedCoin = coinFormat.noCode().format(coin).toString(); - } else { - formattedCoin = coinFormat.noCode().minDecimals(decimalPlaces).repeatOptionalDecimals(1, decimalPlaces).format(coin).toString(); - } - } catch (Throwable t) { - log.warn("Exception at formatBtc: " + t.toString()); - } - } - - if (decimalAligned) { - formattedCoin = fillUpPlacesWithEmptyStrings(formattedCoin, maxNumberOfDigits); - } - - return formattedCoin; - } - - public String formatCoinWithCode(Coin coin) { - return formatCoinWithCode(coin, coinFormat); - } - - public String formatCoinWithCode(long value) { - return formatCoinWithCode(Coin.valueOf(value), coinFormat); - } - - public String formatCoinWithCode(long value, MonetaryFormat coinFormat) { - return formatCoinWithCode(Coin.valueOf(value), coinFormat); - } - - public String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) { - if (coin != null) { - try { - // we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and - // pre and post fixing - return coinFormat.postfixCode().format(coin).toString(); - } catch (Throwable t) { - log.warn("Exception at formatBtcWithCode: " + t.toString()); - return ""; - } - } else { - return ""; - } - } - - 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; - } - } - - /** - * Converts to a coin with max. 4 decimal places. Last place gets rounded. - * 0.01234 -> 0.0123 - * 0.01235 -> 0.0124 - * - * @param input - * @return - */ - public Coin parseToCoinWith4Decimals(String input) { - try { - return Coin.valueOf(new BigDecimal(parseToCoin(cleanDoubleInput(input)).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) - log.warn("Exception at parseToCoinWith4Decimals: " + t.toString()); - return Coin.ZERO; - } - } - - public boolean hasBtcValidDecimals(String input) { - return parseToCoin(input).equals(parseToCoinWith4Decimals(input)); - } - - /** - * Transform a coin with the properties defined in the format (used to reduce decimal places) - * - * @param coin The coin which should be transformed - * @return The transformed coin - */ - public Coin reduceTo4Decimals(Coin coin) { - return parseToCoin(formatCoin(coin)); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // FIAT - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatFiat(Fiat fiat, MonetaryFormat format, boolean appendCurrencyCode) { - if (fiat != null) { - try { - final String res = format.noCode().format(fiat).toString(); - if (appendCurrencyCode) - return res + " " + fiat.getCurrencyCode(); - else - return res; - } catch (Throwable t) { - log.warn("Exception at formatFiatWithCode: " + t.toString()); - return Res.get("shared.na") + " " + fiat.getCurrencyCode(); - } - } else { - return Res.get("shared.na"); - } - } - - protected Fiat parseToFiat(String input, String currencyCode) { - if (input != null && input.length() > 0) { - try { - return Fiat.parseFiat(currencyCode, cleanDoubleInput(input)); - } catch (Exception e) { - log.warn("Exception at parseToFiat: " + e.toString()); - return Fiat.valueOf(currencyCode, 0); - } - - } else { - return Fiat.valueOf(currencyCode, 0); - } - } - - /** - * Converts to a fiat with max. 2 decimal places. Last place gets rounded. - * 0.234 -> 0.23 - * 0.235 -> 0.24 - * - * @param input - * @return - */ - - public 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(), - currencyCode); - } catch (Throwable t) { - log.warn("Exception at parseToFiatWithPrecision: " + t.toString()); - return Fiat.valueOf(currencyCode, 0); - } - - } - return Fiat.valueOf(currencyCode, 0); - } - - public boolean isFiatAlteredWhenPrecisionApplied(String input, String currencyCode) { - return parseToFiat(input, currencyCode).equals(parseToFiatWithPrecision(input, currencyCode)); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Altcoin - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatAltcoin(Altcoin altcoin) { - return formatAltcoin(altcoin, false); - } - - public String formatAltcoinWithCode(Altcoin altcoin) { - return formatAltcoin(altcoin, true); - } - - public String formatAltcoin(Altcoin altcoin, boolean appendCurrencyCode) { - if (altcoin != null) { - try { - String res = altcoinFormat.noCode().format(altcoin).toString(); - if (appendCurrencyCode) - return res + " " + altcoin.getCurrencyCode(); - else - return res; - } catch (Throwable t) { - log.warn("Exception at formatAltcoin: " + t.toString()); - return Res.get("shared.na") + " " + altcoin.getCurrencyCode(); - } - } else { - return Res.get("shared.na"); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Volume - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits) { - return formatVolume(offer, decimalAligned, maxNumberOfDigits, true); - } - - public String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits, boolean showRange) { - String formattedVolume = offer.isRange() && showRange ? formatVolume(offer.getMinVolume()) + RANGE_SEPARATOR + formatVolume(offer.getVolume()) : formatVolume(offer.getVolume()); - - if (decimalAligned) { - formattedVolume = fillUpPlacesWithEmptyStrings(formattedVolume, maxNumberOfDigits); - } - return formattedVolume; - } - - @NotNull - public String fillUpPlacesWithEmptyStrings(String formattedNumber, int maxNumberOfDigits) { - //FIXME: temporary deactivate adding spaces in front of numbers as we don't use a monospace font right now. - /*int numberOfPlacesToFill = maxNumberOfDigits - formattedNumber.length(); - for (int i = 0; i < numberOfPlacesToFill; i++) { - formattedNumber = " " + formattedNumber; - }*/ - return formattedNumber; - } - - public String formatVolume(Volume volume) { - return formatVolume(volume, fiatVolumeFormat, false); - } - - public String formatVolumeWithCode(Volume volume) { - return formatVolume(volume, fiatVolumeFormat, true); - } - - public String formatVolume(Volume volume, MonetaryFormat fiatVolumeFormat, boolean appendCurrencyCode) { - if (volume != null) { - Monetary monetary = volume.getMonetary(); - if (monetary instanceof Fiat) - return formatFiat((Fiat) monetary, fiatVolumeFormat, appendCurrencyCode); - else - return formatAltcoinVolume((Altcoin) monetary, appendCurrencyCode); - } else { - return ""; - } - } - - public String formatAltcoinVolume(Altcoin altcoin, boolean appendCurrencyCode) { - if (altcoin != null) { - try { - // TODO quick hack... - String res; - if (altcoin.getCurrencyCode().equals("BSQ")) - res = altcoinFormat.noCode().minDecimals(2).repeatOptionalDecimals(0, 0).format(altcoin).toString(); - else - res = altcoinFormat.noCode().format(altcoin).toString(); - if (appendCurrencyCode) - return res + " " + altcoin.getCurrencyCode(); - else - return res; - } catch (Throwable t) { - log.warn("Exception at formatAltcoinVolume: " + t.toString()); - return Res.get("shared.na") + " " + altcoin.getCurrencyCode(); - } - } else { - return Res.get("shared.na"); - } - } - - public String formatVolumeLabel(String currencyCode) { - return formatVolumeLabel(currencyCode, ""); - } - - public String formatVolumeLabel(String currencyCode, String postFix) { - return Res.get("formatter.formatVolumeLabel", - currencyCode, postFix); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Amount - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatAmount(Offer offer) { - return formatAmount(offer, false); - } - - public String formatAmount(Offer offer, boolean decimalAligned) { - String formattedAmount = offer.isRange() ? formatCoin(offer.getMinAmount()) + RANGE_SEPARATOR + formatCoin(offer.getAmount()) : formatCoin(offer.getAmount()); - if (decimalAligned) { - formattedAmount = fillUpPlacesWithEmptyStrings(formattedAmount, 15); - } - return formattedAmount; - } - - public String formatAmount(Offer offer, int decimalPlaces, boolean decimalAligned, int maxPlaces) { - String formattedAmount = offer.isRange() ? formatCoin(offer.getMinAmount(), decimalPlaces) + RANGE_SEPARATOR + formatCoin(offer.getAmount(), decimalPlaces) : formatCoin(offer.getAmount(), decimalPlaces); - - if (decimalAligned) { - formattedAmount = fillUpPlacesWithEmptyStrings(formattedAmount, maxPlaces); - } - return formattedAmount; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Price - /////////////////////////////////////////////////////////////////////////////////////////// - - - public String formatPrice(Price price, MonetaryFormat fiatPriceFormat, boolean appendCurrencyCode) { - if (price != null) { - Monetary monetary = price.getMonetary(); - if (monetary instanceof Fiat) - return formatFiat((Fiat) monetary, fiatPriceFormat, appendCurrencyCode); - else - return formatAltcoin((Altcoin) monetary, appendCurrencyCode); - } else { - return Res.get("shared.na"); - } - } - - public String formatPrice(Price price, boolean appendCurrencyCode) { - return formatPrice(price, fiatPriceFormat, true); - } - - public String formatPrice(Price price) { - return formatPrice(price, fiatPriceFormat, false); - } - - public String formatPrice(Price price, Boolean decimalAligned, int maxPlaces) { - String formattedPrice = formatPrice(price); - - if (decimalAligned) { - formattedPrice = fillUpPlacesWithEmptyStrings(formattedPrice, maxPlaces); - } - return formattedPrice; - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Market price - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatMarketPrice(double price, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) - return formatMarketPrice(price, 2); - else - return formatMarketPrice(price, 8); - } - - public String formatMarketPrice(double price, int precision) { - return formatRoundedDoubleWithPrecision(price, precision); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Other - /////////////////////////////////////////////////////////////////////////////////////////// - - public String formatRoundedDoubleWithPrecision(double value, int precision) { - decimalFormat.setMinimumFractionDigits(precision); - decimalFormat.setMaximumFractionDigits(precision); - return decimalFormat.format(MathUtils.roundDouble(value, precision)).replace(",", "."); - } - - public String getDirectionWithCode(OfferPayload.Direction direction, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) - return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyCurrency", Res.getBaseCurrencyCode()) : Res.get("shared.sellCurrency", Res.getBaseCurrencyCode()); - else - return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyCurrency", currencyCode) : Res.get("shared.sellCurrency", currencyCode); - } - - public String getDirectionWithCodeDetailed(OfferPayload.Direction direction, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) - return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyingBTCWith", currencyCode) : Res.get("shared.sellingBTCFor", currencyCode); - else - return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyingCurrency", currencyCode) : Res.get("shared.sellingCurrency", currencyCode); - } - - public String arbitratorAddressesToString(List nodeAddresses) { - return nodeAddresses.stream().map(NodeAddress::getFullAddress).collect(Collectors.joining(", ")); - } - - public String languageCodesToString(List languageLocales) { - return languageLocales.stream().map(LanguageUtil::getDisplayName).collect(Collectors.joining(", ")); - } - - public String formatDateTime(Date date) { - return formatDateTime(date, true); - } - - public String formatDateTime(Date date, boolean useLocaleAndLocalTimezone) { - Locale locale = useLocaleAndLocalTimezone ? getLocale() : Locale.US; - DateFormat dateInstance = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); - DateFormat timeInstance = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale); - if (!useLocaleAndLocalTimezone) { - dateInstance.setTimeZone(TimeZone.getTimeZone("UTC")); - timeInstance.setTimeZone(TimeZone.getTimeZone("UTC")); - } - return formatDateTime(date, dateInstance, timeInstance); - } - - public String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) { - if (date != null) { - return dateFormatter.format(date) + " " + timeFormatter.format(date); - } else { - return ""; - } - } - - public String formatDateTimeSpan(Date dateFrom, Date dateTo) { - if (dateFrom != null && dateTo != null) { - DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()); - DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()); - return dateFormatter.format(dateFrom) + " " + timeFormatter.format(dateFrom) + RANGE_SEPARATOR + timeFormatter.format(dateTo); - } else { - return ""; - } - } - - public String formatTime(Date date) { - if (date != null) { - DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()); - return timeFormatter.format(date); - } else { - return ""; - } - } - - public String formatDate(Date date) { - if (date != null) { - DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()); - return dateFormatter.format(date); - } else { - return ""; - } - } - - public String formatToPercentWithSymbol(double value) { - return formatToPercent(value) + "%"; - } - - public String formatPercentagePrice(double value) { - return formatToPercentWithSymbol(value); - } - - public String formatToPercent(double value) { - DecimalFormat decimalFormat = new DecimalFormat("#.##"); - decimalFormat.setMinimumFractionDigits(2); - decimalFormat.setMaximumFractionDigits(2); - return decimalFormat.format(MathUtils.roundDouble(value * 100.0, 2)).replace(",", "."); - } - - public double parseNumberStringToDouble(String input) throws NumberFormatException { - return Double.parseDouble(cleanDoubleInput(input)); - } - - public 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 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 = 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(",", "."); - } - - protected 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 String formatAccountAge(long durationMillis) { - durationMillis = Math.max(0, durationMillis); - String day = Res.get("time.day").toLowerCase(); - String days = Res.get("time.days"); - String format = "d\' " + days + "\'"; - return StringUtils.replaceOnce(DurationFormatUtils.formatDuration(durationMillis, format), "1 " + days, "1 " + day); - } - - public String formatDurationAsWords(long durationMillis) { - return formatDurationAsWords(durationMillis, false, true); - } - - public String formatDurationAsWords(long durationMillis, boolean showSeconds, boolean showZeroValues) { - String format = ""; - String second = Res.get("time.second"); - String minute = Res.get("time.minute"); - String hour = Res.get("time.hour").toLowerCase(); - String day = Res.get("time.day").toLowerCase(); - String days = Res.get("time.days"); - String hours = Res.get("time.hours"); - String minutes = Res.get("time.minutes"); - String seconds = Res.get("time.seconds"); - - if (durationMillis >= DateUtils.MILLIS_PER_DAY) { - format = "d\' " + days + ", \'"; - } - - if (showSeconds) { - format += "H\' " + hours + ", \'m\' " + minutes + ", \'s\' " + seconds + "\'"; - } else { - format += "H\' " + hours + ", \'m\' " + minutes + "\'"; - } - - String duration = durationMillis > 0 ? DurationFormatUtils.formatDuration(durationMillis, format) : ""; - - duration = StringUtils.replacePattern(duration, "^1 " + seconds + "|\\b1 " + seconds, "1 " + second); - duration = StringUtils.replacePattern(duration, "^1 " + minutes + "|\\b1 " + minutes, "1 " + minute); - duration = StringUtils.replacePattern(duration, "^1 " + hours + "|\\b1 " + hours, "1 " + hour); - duration = StringUtils.replacePattern(duration, "^1 " + days + "|\\b1 " + days, "1 " + day); - - if (!showZeroValues) { - duration = duration.replace(", 0 seconds", ""); - duration = duration.replace(", 0 minutes", ""); - duration = duration.replace(", 0 hours", ""); - duration = StringUtils.replacePattern(duration, "^0 days, ", ""); - duration = StringUtils.replacePattern(duration, "^0 hours, ", ""); - duration = StringUtils.replacePattern(duration, "^0 minutes, ", ""); - duration = StringUtils.replacePattern(duration, "^0 seconds, ", ""); - } - return duration.trim(); - } - - public String booleanToYesNo(boolean value) { - return value ? Res.get("shared.yes") : Res.get("shared.no"); - } - - public String getDirectionBothSides(OfferPayload.Direction direction, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - currencyCode = Res.getBaseCurrencyCode(); - return direction == OfferPayload.Direction.BUY ? - Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) : - Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer")); - } else { - return direction == OfferPayload.Direction.SELL ? - Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) : - Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer")); - } - } - - public String getDirectionForBuyer(boolean isMyOffer, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - String code = Res.getBaseCurrencyCode(); - return isMyOffer ? - Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code) : - Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code); - } else { - return isMyOffer ? - Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode) : - Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode); - } - } - - public String getDirectionForSeller(boolean isMyOffer, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - String code = Res.getBaseCurrencyCode(); - return isMyOffer ? - Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code) : - Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code); - } else { - return isMyOffer ? - Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode) : - Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode); - } - } - - public String getDirectionForTakeOffer(OfferPayload.Direction direction, String currencyCode) { - String baseCurrencyCode = Res.getBaseCurrencyCode(); - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - return direction == OfferPayload.Direction.BUY ? - Res.get("formatter.youAre", Res.get("shared.selling"), baseCurrencyCode, Res.get("shared.buying"), currencyCode) : - Res.get("formatter.youAre", Res.get("shared.buying"), baseCurrencyCode, Res.get("shared.selling"), currencyCode); - } else { - - return direction == OfferPayload.Direction.SELL ? - Res.get("formatter.youAre", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), baseCurrencyCode) : - Res.get("formatter.youAre", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), baseCurrencyCode); - } - } - - public String getOfferDirectionForCreateOffer(OfferPayload.Direction direction, String currencyCode) { - String baseCurrencyCode = Res.getBaseCurrencyCode(); - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - return direction == OfferPayload.Direction.BUY ? - Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.buy"), baseCurrencyCode) : - Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.sell"), baseCurrencyCode); - } else { - return direction == OfferPayload.Direction.SELL ? - Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.buy"), currencyCode, Res.get("shared.selling"), baseCurrencyCode) : - Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.sell"), currencyCode, Res.get("shared.buying"), baseCurrencyCode); - } - } - - public String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) { - String baseCurrencyCode = Res.getBaseCurrencyCode(); - if (isBuyerMakerAndSellerTaker) - return isMaker ? - Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.buyer")) : - Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.seller")); - else - return isMaker ? - Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.seller")) : - Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.buyer")); - } else { - if (isBuyerMakerAndSellerTaker) - return isMaker ? - Res.get("formatter.asMaker", currencyCode, Res.get("shared.seller")) : - Res.get("formatter.asTaker", currencyCode, Res.get("shared.buyer")); - else - return isMaker ? - Res.get("formatter.asMaker", currencyCode, Res.get("shared.buyer")) : - Res.get("formatter.asTaker", currencyCode, Res.get("shared.seller")); - } - - } - - public String formatBytes(long bytes) { - double kb = 1024; - double mb = kb * kb; - DecimalFormat decimalFormat = new DecimalFormat("#.##"); - if (bytes < kb) - return bytes + " bytes"; - else if (bytes < mb) - return decimalFormat.format(bytes / kb) + " KB"; - else - return decimalFormat.format(bytes / mb) + " MB"; - } - - public String getCurrencyPair(String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) - return Res.getBaseCurrencyCode() + "/" + currencyCode; - else - return currencyCode + "/" + Res.getBaseCurrencyCode(); - } - - public String getCounterCurrency(String currencyCode) { - if (CurrencyUtil.isFiatCurrency(currencyCode)) - return currencyCode; - else - return Res.getBaseCurrencyCode(); - } - - public String getBaseCurrency(String currencyCode) { - if (CurrencyUtil.isCryptoCurrency(currencyCode)) - return currencyCode; - else - return Res.getBaseCurrencyCode(); - } - - public String getCounterCurrencyAndCurrencyPair(String currencyCode) { - return getCounterCurrency(currencyCode) + " (" + getCurrencyPair(currencyCode) + ")"; - } - - public String getCurrencyNameAndCurrencyPair(String currencyCode) { - return CurrencyUtil.getNameByCode(currencyCode) + " (" + getCurrencyPair(currencyCode) + ")"; - } - - public String getPriceWithCurrencyCode(String currencyCode) { - return getPriceWithCurrencyCode(currencyCode, "shared.priceInCurForCur"); - } - - public String getPriceWithCurrencyCode(String currencyCode, String translationKey) { - if (CurrencyUtil.isCryptoCurrency(currencyCode)) - return Res.get(translationKey, Res.getBaseCurrencyCode(), currencyCode); - else - return Res.get(translationKey, currencyCode, Res.getBaseCurrencyCode()); - } - - public Locale getLocale() { - return GlobalSettings.getLocale(); - } -} diff --git a/core/src/main/java/bisq/core/util/FormattingUtils.java b/core/src/main/java/bisq/core/util/FormattingUtils.java new file mode 100644 index 00000000000..ae0dec79e3c --- /dev/null +++ b/core/src/main/java/bisq/core/util/FormattingUtils.java @@ -0,0 +1,298 @@ +package bisq.core.util; + +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.GlobalSettings; +import bisq.core.locale.Res; +import bisq.core.monetary.Altcoin; +import bisq.core.monetary.Price; +import bisq.core.offer.Offer; + +import bisq.common.util.MathUtils; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Monetary; +import org.bitcoinj.utils.Fiat; +import org.bitcoinj.utils.MonetaryFormat; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; + +import java.text.DateFormat; +import java.text.DecimalFormat; + +import java.math.BigDecimal; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import lombok.extern.slf4j.Slf4j; + +import org.jetbrains.annotations.NotNull; + +@Slf4j +public class FormattingUtils { + public static final String BTC_FORMATTER_KEY = "BTC"; + + public final static String RANGE_SEPARATOR = " - "; + + private static final MonetaryFormat altcoinFormat = new MonetaryFormat().shift(0).minDecimals(8).repeatOptionalDecimals(0, 0); + private static final MonetaryFormat fiatPriceFormat = new MonetaryFormat().shift(0).minDecimals(4).repeatOptionalDecimals(0, 0); + private static final DecimalFormat decimalFormat = new DecimalFormat("#.#"); + + public static String formatCoinWithCode(long value, MonetaryFormat coinFormat) { + return formatCoinWithCode(Coin.valueOf(value), coinFormat); + } + + public static String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) { + if (coin != null) { + try { + // we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and + // pre and post fixing + return coinFormat.postfixCode().format(coin).toString(); + } catch (Throwable t) { + log.warn("Exception at formatBtcWithCode: " + t.toString()); + return ""; + } + } else { + return ""; + } + } + + public static String formatCoin(long value, MonetaryFormat coinFormat) { + return formatCoin(Coin.valueOf(value), -1, false, 0, coinFormat); + } + + public static String formatCoin(Coin coin, + int decimalPlaces, + boolean decimalAligned, + int maxNumberOfDigits, + MonetaryFormat coinFormat) { + String formattedCoin = ""; + + if (coin != null) { + try { + if (decimalPlaces < 0 || decimalPlaces > 4) { + formattedCoin = coinFormat.noCode().format(coin).toString(); + } else { + formattedCoin = coinFormat.noCode().minDecimals(decimalPlaces).repeatOptionalDecimals(1, decimalPlaces).format(coin).toString(); + } + } catch (Throwable t) { + log.warn("Exception at formatBtc: " + t.toString()); + } + } + + if (decimalAligned) { + formattedCoin = fillUpPlacesWithEmptyStrings(formattedCoin, maxNumberOfDigits); + } + + return formattedCoin; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Volume + /////////////////////////////////////////////////////////////////////////////////////////// + + public static String formatFiat(Fiat fiat, MonetaryFormat format, boolean appendCurrencyCode) { + if (fiat != null) { + try { + final String res = format.noCode().format(fiat).toString(); + if (appendCurrencyCode) + return res + " " + fiat.getCurrencyCode(); + else + return res; + } catch (Throwable t) { + log.warn("Exception at formatFiat: " + t.toString()); + return Res.get("shared.na") + " " + fiat.getCurrencyCode(); + } + } else { + return Res.get("shared.na"); + } + } + + public static String formatPrice(Price price, + MonetaryFormat fiatPriceFormat, + boolean appendCurrencyCode) { + if (price != null) { + Monetary monetary = price.getMonetary(); + if (monetary instanceof Fiat) + return formatFiat((Fiat) monetary, fiatPriceFormat, appendCurrencyCode); + else + return formatAltcoin((Altcoin) monetary, appendCurrencyCode); + } else { + return Res.get("shared.na"); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Price + /////////////////////////////////////////////////////////////////////////////////////////// + + public static String formatPrice(Price price) { + return formatPrice(price, fiatPriceFormat, false); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Market price + /////////////////////////////////////////////////////////////////////////////////////////// + + public static String formatMarketPrice(double price, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) + return formatMarketPrice(price, 2); + else + return formatMarketPrice(price, 8); + } + + private static String formatMarketPrice(double price, int precision) { + return formatRoundedDoubleWithPrecision(price, precision); + } + + public static String formatRoundedDoubleWithPrecision(double value, int precision) { + decimalFormat.setMinimumFractionDigits(precision); + decimalFormat.setMaximumFractionDigits(precision); + return decimalFormat.format(MathUtils.roundDouble(value, precision)).replace(",", "."); + } + + public static String formatDateTime(Date date, boolean useLocaleAndLocalTimezone) { + Locale locale = useLocaleAndLocalTimezone ? GlobalSettings.getLocale() : Locale.US; + DateFormat dateInstance = DateFormat.getDateInstance(DateFormat.DEFAULT, locale); + DateFormat timeInstance = DateFormat.getTimeInstance(DateFormat.DEFAULT, locale); + if (!useLocaleAndLocalTimezone) { + dateInstance.setTimeZone(TimeZone.getTimeZone("UTC")); + timeInstance.setTimeZone(TimeZone.getTimeZone("UTC")); + } + return formatDateTime(date, dateInstance, timeInstance); + } + + public static String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) { + if (date != null) { + return dateFormatter.format(date) + " " + timeFormatter.format(date); + } else { + return ""; + } + } + + public static String formatToPercentWithSymbol(double value) { + return formatToPercent(value) + "%"; + } + + public static String formatPercentagePrice(double value) { + return formatToPercentWithSymbol(value); + } + public static String formatToPercent(double value) { + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + decimalFormat.setMinimumFractionDigits(2); + decimalFormat.setMaximumFractionDigits(2); + return decimalFormat.format(MathUtils.roundDouble(value * 100.0, 2)).replace(",", "."); + } + + public static String formatDurationAsWords(long durationMillis) { + return formatDurationAsWords(durationMillis, false, true); + } + + public static String formatDurationAsWords(long durationMillis, boolean showSeconds, boolean showZeroValues) { + String format = ""; + String second = Res.get("time.second"); + String minute = Res.get("time.minute"); + String hour = Res.get("time.hour").toLowerCase(); + String day = Res.get("time.day").toLowerCase(); + String days = Res.get("time.days"); + String hours = Res.get("time.hours"); + String minutes = Res.get("time.minutes"); + String seconds = Res.get("time.seconds"); + + if (durationMillis >= DateUtils.MILLIS_PER_DAY) { + format = "d\' " + days + ", \'"; + } + + if (showSeconds) { + format += "H\' " + hours + ", \'m\' " + minutes + ", \'s\' " + seconds + "\'"; + } else { + format += "H\' " + hours + ", \'m\' " + minutes + "\'"; + } + + String duration = durationMillis > 0 ? DurationFormatUtils.formatDuration(durationMillis, format) : ""; + + duration = StringUtils.replacePattern(duration, "^1 " + seconds + "|\\b1 " + seconds, "1 " + second); + duration = StringUtils.replacePattern(duration, "^1 " + minutes + "|\\b1 " + minutes, "1 " + minute); + duration = StringUtils.replacePattern(duration, "^1 " + hours + "|\\b1 " + hours, "1 " + hour); + duration = StringUtils.replacePattern(duration, "^1 " + days + "|\\b1 " + days, "1 " + day); + + if (!showZeroValues) { + duration = duration.replace(", 0 seconds", ""); + duration = duration.replace(", 0 minutes", ""); + duration = duration.replace(", 0 hours", ""); + duration = StringUtils.replacePattern(duration, "^0 days, ", ""); + duration = StringUtils.replacePattern(duration, "^0 hours, ", ""); + duration = StringUtils.replacePattern(duration, "^0 minutes, ", ""); + duration = StringUtils.replacePattern(duration, "^0 seconds, ", ""); + } + return duration.trim(); + } + + public static String formatBytes(long bytes) { + double kb = 1024; + double mb = kb * kb; + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + if (bytes < kb) + return bytes + " bytes"; + else if (bytes < mb) + return decimalFormat.format(bytes / kb) + " KB"; + else + return decimalFormat.format(bytes / mb) + " MB"; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Altcoin + /////////////////////////////////////////////////////////////////////////////////////////// + + public static String formatAltcoinVolume(Altcoin altcoin, boolean appendCurrencyCode) { + if (altcoin != null) { + try { + // TODO quick hack... + String res; + if (altcoin.getCurrencyCode().equals("BSQ")) + res = altcoinFormat.noCode().minDecimals(2).repeatOptionalDecimals(0, 0).format(altcoin).toString(); + else + res = altcoinFormat.noCode().format(altcoin).toString(); + if (appendCurrencyCode) + return res + " " + altcoin.getCurrencyCode(); + else + return res; + } catch (Throwable t) { + log.warn("Exception at formatAltcoinVolume: " + t.toString()); + return Res.get("shared.na") + " " + altcoin.getCurrencyCode(); + } + } else { + return Res.get("shared.na"); + } + } + + private static String formatAltcoin(Altcoin altcoin, boolean appendCurrencyCode) { + if (altcoin != null) { + try { + String res = altcoinFormat.noCode().format(altcoin).toString(); + if (appendCurrencyCode) + return res + " " + altcoin.getCurrencyCode(); + else + return res; + } catch (Throwable t) { + log.warn("Exception at formatAltcoin: " + t.toString()); + return Res.get("shared.na") + " " + altcoin.getCurrencyCode(); + } + } else { + return Res.get("shared.na"); + } + } + + @NotNull + public static String fillUpPlacesWithEmptyStrings(String formattedNumber, int maxNumberOfDigits) { + //FIXME: temporary deactivate adding spaces in front of numbers as we don't use a monospace font right now. + /*int numberOfPlacesToFill = maxNumberOfDigits - formattedNumber.length(); + for (int i = 0; i < numberOfPlacesToFill; i++) { + formattedNumber = " " + formattedNumber; + }*/ + return formattedNumber; + } +} 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..c667f6fbf0e --- /dev/null +++ b/core/src/main/java/bisq/core/util/ParsingUtils.java @@ -0,0 +1,86 @@ +package bisq.core.util; + +import bisq.core.monetary.Price; +import bisq.core.util.coin.CoinFormatter; + +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, CoinFormatter coinFormat) { + return parseToCoin(input, coinFormat.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 parseToCoin: " + 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 = FormattingUtils.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/core/src/main/java/bisq/core/util/BsqFormatter.java b/core/src/main/java/bisq/core/util/coin/BsqFormatter.java similarity index 66% rename from core/src/main/java/bisq/core/util/BsqFormatter.java rename to core/src/main/java/bisq/core/util/coin/BsqFormatter.java index 7f2524598e0..715faebd964 100644 --- a/core/src/main/java/bisq/core/util/BsqFormatter.java +++ b/core/src/main/java/bisq/core/util/coin/BsqFormatter.java @@ -15,7 +15,7 @@ * along with Bisq. If not, see . */ -package bisq.core.util; +package bisq.core.util.coin; import bisq.core.app.BisqEnvironment; import bisq.core.dao.governance.param.Param; @@ -23,14 +23,13 @@ import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; import bisq.core.provider.price.MarketPrice; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.BtcAddressValidator; import bisq.core.util.validation.InputValidator; -import bisq.common.app.DevEnv; import bisq.common.util.MathUtils; -import org.bitcoinj.core.Address; -import org.bitcoinj.core.AddressFormatException; import org.bitcoinj.core.Coin; import org.bitcoinj.utils.MonetaryFormat; @@ -42,31 +41,42 @@ import java.util.Locale; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; + @Slf4j @Singleton -public class BsqFormatter extends BSFormatter { - @SuppressWarnings("PointlessBooleanExpression") - private static final boolean useBsqAddressFormat = true || !DevEnv.isDevMode(); - private final String prefix = "B"; +public class BsqFormatter implements CoinFormatter { + private final ImmutableCoinFormatter coinFormatter; + + protected int scale = 3; + // We don't support localized formatting. Format is always using "." as decimal mark and no grouping separator. + // Input of "," as decimal mark (like in german locale) will be replaced with ".". + // 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. + @Getter + private MonetaryFormat monetaryFormat; private DecimalFormat amountFormat; private DecimalFormat marketCapFormat; private final MonetaryFormat btcCoinFormat; @Inject public BsqFormatter() { - super(); + this.monetaryFormat = BisqEnvironment.getParameters().getMonetaryFormat(); + this.coinFormatter = new ImmutableCoinFormatter(BisqEnvironment.getParameters().getMonetaryFormat()); - GlobalSettings.localeProperty().addListener((observable, oldValue, newValue) -> setFormatter(newValue)); - setFormatter(GlobalSettings.getLocale()); + GlobalSettings.localeProperty().addListener((observable, oldValue, newValue) -> switchToLocale(newValue)); + switchToLocale(GlobalSettings.getLocale()); - btcCoinFormat = super.coinFormat; + btcCoinFormat = 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); @@ -75,7 +85,7 @@ public BsqFormatter() { amountFormat.setMinimumFractionDigits(2); } - private void setFormatter(Locale locale) { + private void switchToLocale(Locale locale) { amountFormat = (DecimalFormat) NumberFormat.getNumberInstance(locale); amountFormat.setMinimumFractionDigits(2); amountFormat.setMaximumFractionDigits(2); @@ -85,30 +95,6 @@ private void setFormatter(Locale locale) { marketCapFormat.setMaximumFractionDigits(0); } - /** - * Returns the base-58 encoded String representation of this - * object, including version and checksum bytes. - */ - public String getBsqAddressStringFromAddress(Address address) { - final String addressString = address.toString(); - if (useBsqAddressFormat) - return prefix + addressString; - else - return addressString; - - } - - public Address getAddressFromBsqAddress(String encoded) { - if (useBsqAddressFormat) - encoded = encoded.substring(prefix.length(), encoded.length()); - - try { - return Address.fromBase58(BisqEnvironment.getParameters(), encoded); - } catch (AddressFormatException e) { - throw new RuntimeException(e); - } - } - public String formatAmountWithGroupSeparatorAndCode(Coin amount) { return amountFormat.format(MathUtils.scaleDownByPowerOf10(amount.value, 2)) + " BSQ"; } @@ -123,47 +109,31 @@ public String formatMarketCap(MarketPrice bsqPriceMarketPrice, MarketPrice fiatM } public String formatBSQSatoshis(long satoshi) { - return super.formatCoin(satoshi, coinFormat); + return FormattingUtils.formatCoin(satoshi, monetaryFormat); } public String formatBSQSatoshisWithCode(long satoshi) { - return super.formatCoinWithCode(satoshi, coinFormat); + return FormattingUtils.formatCoinWithCode(satoshi, monetaryFormat); } public String formatBTCSatoshis(long satoshi) { - return super.formatCoin(satoshi, btcCoinFormat); + return FormattingUtils.formatCoin(satoshi, btcCoinFormat); } public String formatBTCWithCode(long satoshi) { - return super.formatCoinWithCode(satoshi, btcCoinFormat); + return FormattingUtils.formatCoinWithCode(satoshi, btcCoinFormat); } public String formatBTCWithCode(Coin coin) { - return super.formatCoinWithCode(coin, btcCoinFormat); + return FormattingUtils.formatCoinWithCode(coin, btcCoinFormat); } - public String formatBTC(Coin coin) { - return super.formatCoin(coin.value, btcCoinFormat); + private String formatBTC(Coin coin) { + return FormattingUtils.formatCoin(coin.value, btcCoinFormat); } public Coin parseToBTC(String input) { - return super.parseToCoin(input, btcCoinFormat); - } - - public void validateBtcInput(String input) throws ProposalValidationException { - validateCoinInput(input, btcCoinFormat); - } - - public void validateBsqInput(String input) throws ProposalValidationException { - validateCoinInput(input, this.coinFormat); - } - - private void validateCoinInput(String input, MonetaryFormat coinFormat) throws ProposalValidationException { - try { - coinFormat.parse(cleanDoubleInput(input)); - } catch (Throwable t) { - throw new ProposalValidationException("Invalid format for a " + coinFormat.code() + " value"); - } + return ParsingUtils.parseToCoin(input, btcCoinFormat); } public String formatParamValue(Param param, String value) { @@ -172,11 +142,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 FormattingUtils.formatToPercentWithSymbol(ParsingUtils.parsePercentStringToDouble(value)); case BLOCK: return Res.get("dao.param.blocks", Integer.parseInt(value)); case ADDRESS: @@ -190,7 +160,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: @@ -198,15 +168,6 @@ public Coin parseParamValueToCoin(Param param, String inputValue) { } } - public int parseParamValueToBlocks(Param param, String inputValue) { - switch (param.getParamType()) { - case BLOCK: - return Integer.parseInt(inputValue); - default: - throw new IllegalArgumentException("Unsupported paramType. param: " + param); - } - } - public String parseParamValueToString(Param param, String inputValue) throws ProposalValidationException { switch (param.getParamType()) { case UNDEFINED: @@ -216,7 +177,7 @@ public String parseParamValueToString(Param param, String inputValue) throws Pro case BTC: return formatBTC(parseParamValueToCoin(param, inputValue)); case PERCENT: - return formatToPercent(parsePercentStringToDouble(inputValue)); + return FormattingUtils.formatToPercent(ParsingUtils.parsePercentStringToDouble(inputValue)); case BLOCK: return Integer.toString(parseParamValueToBlocks(param, inputValue)); case ADDRESS: @@ -230,4 +191,34 @@ public String parseParamValueToString(Param param, String inputValue) throws Pro return Res.get("shared.na"); } } + + private int parseParamValueToBlocks(Param param, String inputValue) { + switch (param.getParamType()) { + case BLOCK: + return Integer.parseInt(inputValue); + default: + throw new IllegalArgumentException("Unsupported paramType. param: " + param); + } + } + + public String formatCoin(Coin coin) { + return coinFormatter.formatCoin(coin, -1); + } + + @NotNull + public String formatCoin(Coin coin, int decimalPlaces) { + return coinFormatter.formatCoin(coin, decimalPlaces, false, 0); + } + + public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) { + return coinFormatter.formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits); + } + + public String formatCoinWithCode(Coin coin) { + return coinFormatter.formatCoin(coin); + } + + public String formatCoinWithCode(long value) { + return coinFormatter.formatCoinWithCode(value); + } } diff --git a/core/src/main/java/bisq/core/util/coin/CoinFormatter.java b/core/src/main/java/bisq/core/util/coin/CoinFormatter.java new file mode 100644 index 00000000000..6ef86b49a16 --- /dev/null +++ b/core/src/main/java/bisq/core/util/coin/CoinFormatter.java @@ -0,0 +1,19 @@ +package bisq.core.util.coin; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; + +public interface CoinFormatter { + MonetaryFormat getMonetaryFormat(); + + String formatCoin(Coin coin); + + String formatCoin(Coin coin, int decimalPlaces); + + String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits); + + String formatCoinWithCode(Coin coin); + + String formatCoinWithCode(long coin); + +} diff --git a/core/src/main/java/bisq/core/util/CoinUtil.java b/core/src/main/java/bisq/core/util/coin/CoinUtil.java similarity index 99% rename from core/src/main/java/bisq/core/util/CoinUtil.java rename to core/src/main/java/bisq/core/util/coin/CoinUtil.java index fa2c1a1922d..d6c90d9e364 100644 --- a/core/src/main/java/bisq/core/util/CoinUtil.java +++ b/core/src/main/java/bisq/core/util/coin/CoinUtil.java @@ -15,7 +15,7 @@ * along with Bisq. If not, see . */ -package bisq.core.util; +package bisq.core.util.coin; import bisq.common.util.MathUtils; diff --git a/core/src/main/java/bisq/core/util/coin/ImmutableCoinFormatter.java b/core/src/main/java/bisq/core/util/coin/ImmutableCoinFormatter.java new file mode 100644 index 00000000000..bb0bdf73629 --- /dev/null +++ b/core/src/main/java/bisq/core/util/coin/ImmutableCoinFormatter.java @@ -0,0 +1,50 @@ +package bisq.core.util.coin; + +import bisq.core.util.FormattingUtils; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import org.jetbrains.annotations.NotNull; + +import static bisq.core.util.ParsingUtils.parseToCoin; + +@Slf4j +public class ImmutableCoinFormatter implements CoinFormatter { + + // We don't support localized formatting. Format is always using "." as decimal mark and no grouping separator. + // Input of "," as decimal mark (like in german locale) will be replaced with ".". + // 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. + @Getter + private final MonetaryFormat monetaryFormat; + + public ImmutableCoinFormatter(MonetaryFormat coinFormat) { + this.monetaryFormat = coinFormat; + } + + public String formatCoin(Coin coin) { + return formatCoin(coin, -1); + } + + @NotNull + public String formatCoin(Coin coin, int decimalPlaces) { + return formatCoin(coin, decimalPlaces, false, 0); + } + + public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) { + return FormattingUtils.formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, monetaryFormat); + } + + public String formatCoinWithCode(Coin coin) { + return FormattingUtils.formatCoinWithCode(coin, monetaryFormat); + } + + public String formatCoinWithCode(long value) { + return FormattingUtils.formatCoinWithCode(Coin.valueOf(value), monetaryFormat); + } +} diff --git a/core/src/test/java/bisq/core/dao/governance/proposal/param/ChangeParamValidatorTest.java b/core/src/test/java/bisq/core/dao/governance/proposal/param/ChangeParamValidatorTest.java index 790d543e5a0..0ba4bed83d6 100644 --- a/core/src/test/java/bisq/core/dao/governance/proposal/param/ChangeParamValidatorTest.java +++ b/core/src/test/java/bisq/core/dao/governance/proposal/param/ChangeParamValidatorTest.java @@ -19,7 +19,7 @@ import bisq.core.dao.governance.param.Param; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import org.junit.Assert; import org.junit.Before; diff --git a/core/src/test/java/bisq/core/dao/state/DaoStateServiceTest.java b/core/src/test/java/bisq/core/dao/state/DaoStateServiceTest.java index 9b2dee42c8f..96857e59bba 100644 --- a/core/src/test/java/bisq/core/dao/state/DaoStateServiceTest.java +++ b/core/src/test/java/bisq/core/dao/state/DaoStateServiceTest.java @@ -19,7 +19,7 @@ import bisq.core.dao.state.model.DaoState; import bisq.core.dao.state.model.blockchain.Block; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import org.bitcoinj.core.Coin; diff --git a/core/src/test/java/bisq/core/util/CoinCryptoUtilsTest.java b/core/src/test/java/bisq/core/util/CoinCryptoUtilsTest.java index 254cdee23f9..2f04b7a75f4 100644 --- a/core/src/test/java/bisq/core/util/CoinCryptoUtilsTest.java +++ b/core/src/test/java/bisq/core/util/CoinCryptoUtilsTest.java @@ -17,6 +17,8 @@ package bisq.core.util; +import bisq.core.util.coin.CoinUtil; + import org.bitcoinj.core.Coin; import org.slf4j.Logger; diff --git a/core/src/test/java/bisq/core/util/FormattingUtilsTest.java b/core/src/test/java/bisq/core/util/FormattingUtilsTest.java new file mode 100644 index 00000000000..76f5a46e0b7 --- /dev/null +++ b/core/src/test/java/bisq/core/util/FormattingUtilsTest.java @@ -0,0 +1,69 @@ +package bisq.core.util; + +import bisq.core.locale.Res; +import bisq.core.monetary.Altcoin; +import bisq.core.monetary.Price; + +import org.bitcoinj.utils.Fiat; + +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import com.natpryce.makeiteasy.Instantiator; +import com.natpryce.makeiteasy.Maker; +import com.natpryce.makeiteasy.Property; + +import org.junit.Before; +import org.junit.Test; + +import static com.natpryce.makeiteasy.MakeItEasy.a; +import static com.natpryce.makeiteasy.MakeItEasy.make; +import static com.natpryce.makeiteasy.MakeItEasy.with; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class FormattingUtilsTest { + private static final Property currencyCode = new Property<>(); + private static final Property priceString = new Property<>(); + private static final Maker usdPrice = a(lookup -> + new Price(Fiat.parseFiat(lookup.valueOf(currencyCode, "USD"), lookup.valueOf(priceString, "100")))); + + @Before + public void setUp() { + Locale.setDefault(new Locale("en", "US")); + Res.setBaseCurrencyCode("BTC"); + Res.setBaseCurrencyName("Bitcoin"); + } + + @Test + public void testFormatDurationAsWords() { + long oneDay = TimeUnit.DAYS.toMillis(1); + long oneHour = TimeUnit.HOURS.toMillis(1); + long oneMinute = TimeUnit.MINUTES.toMillis(1); + long oneSecond = TimeUnit.SECONDS.toMillis(1); + + assertEquals("1 hour, 0 minutes", FormattingUtils.formatDurationAsWords(oneHour)); + assertEquals("1 day, 0 hours, 0 minutes", FormattingUtils.formatDurationAsWords(oneDay)); + assertEquals("2 days, 0 hours, 1 minute", FormattingUtils.formatDurationAsWords(oneDay * 2 + oneMinute)); + assertEquals("2 days, 0 hours, 2 minutes", FormattingUtils.formatDurationAsWords(oneDay * 2 + oneMinute * 2)); + assertEquals("1 hour, 0 minutes, 0 seconds", FormattingUtils.formatDurationAsWords(oneHour, true, true)); + assertEquals("1 hour, 0 minutes, 1 second", FormattingUtils.formatDurationAsWords(oneHour + oneSecond, true, true)); + assertEquals("1 hour, 0 minutes, 2 seconds", FormattingUtils.formatDurationAsWords(oneHour + oneSecond * 2, true, true)); + assertEquals("2 days, 21 hours, 28 minutes", FormattingUtils.formatDurationAsWords(oneDay * 2 + oneHour * 21 + oneMinute * 28)); + assertEquals("110 days", FormattingUtils.formatDurationAsWords(oneDay * 110, false, false)); + assertEquals("10 days, 10 hours, 10 minutes, 10 seconds", FormattingUtils.formatDurationAsWords(oneDay * 10 + oneHour * 10 + oneMinute * 10 + oneSecond * 10, true, false)); + assertEquals("1 hour, 2 seconds", FormattingUtils.formatDurationAsWords(oneHour + oneSecond * 2, true, false)); + assertEquals("1 hour", FormattingUtils.formatDurationAsWords(oneHour + oneSecond * 2, false, false)); + assertEquals("0 hours, 0 minutes, 1 second", FormattingUtils.formatDurationAsWords(oneSecond, true, true)); + assertEquals("1 second", FormattingUtils.formatDurationAsWords(oneSecond, true, false)); + assertEquals("0 hours", FormattingUtils.formatDurationAsWords(oneSecond, false, false)); + assertEquals("", FormattingUtils.formatDurationAsWords(0)); + assertTrue(FormattingUtils.formatDurationAsWords(0).isEmpty()); + } + + @Test + public void testFormatPrice() { + assertEquals("100.0000", FormattingUtils.formatPrice(make(usdPrice))); + assertEquals("7098.4700", FormattingUtils.formatPrice(make(usdPrice.but(with(priceString, "7098.4700"))))); + } +} diff --git a/core/src/test/java/bisq/core/util/coin/ImmutableCoinFormatterTest.java b/core/src/test/java/bisq/core/util/coin/ImmutableCoinFormatterTest.java new file mode 100644 index 00000000000..c46f70d16ce --- /dev/null +++ b/core/src/test/java/bisq/core/util/coin/ImmutableCoinFormatterTest.java @@ -0,0 +1,33 @@ +package bisq.core.util.coin; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; + +import com.natpryce.makeiteasy.Instantiator; +import com.natpryce.makeiteasy.Property; + +import org.junit.Test; + +import static com.natpryce.makeiteasy.MakeItEasy.a; +import static com.natpryce.makeiteasy.MakeItEasy.make; +import static com.natpryce.makeiteasy.MakeItEasy.with; +import static org.bitcoinj.core.Coin.valueOf; +import static org.junit.Assert.assertEquals; + +public class ImmutableCoinFormatterTest { + private static final Property satoshis = new Property<>(); + private static final Instantiator Coin = lookup -> + valueOf(lookup.valueOf(satoshis, 100000000L)); + private static final Coin oneBitcoin = make(a(Coin)); + + private final CoinFormatter formatter = new ImmutableCoinFormatter(MonetaryFormat.BTC); + + @Test + public void testFormatCoin() { + assertEquals("1.00", formatter.formatCoin(oneBitcoin)); + assertEquals("1.0000", formatter.formatCoin(oneBitcoin, 4)); + assertEquals("1.00", formatter.formatCoin(oneBitcoin, 5)); + assertEquals("0.000001", formatter.formatCoin(make(a(Coin).but(with(satoshis, 100L))))); + assertEquals("0.00000001", formatter.formatCoin(make(a(Coin).but(with(satoshis, 1L))))); + } +} diff --git a/desktop/src/main/java/bisq/desktop/DesktopModule.java b/desktop/src/main/java/bisq/desktop/DesktopModule.java index ce4124f3840..1f683c9bf1a 100644 --- a/desktop/src/main/java/bisq/desktop/DesktopModule.java +++ b/desktop/src/main/java/bisq/desktop/DesktopModule.java @@ -21,11 +21,14 @@ import bisq.desktop.common.view.ViewFactory; import bisq.desktop.common.view.ViewLoader; import bisq.desktop.common.view.guice.InjectorViewFactory; +import bisq.desktop.util.BsqAddressHelper; import bisq.core.app.AppOptionKeys; +import bisq.core.app.BisqEnvironment; import bisq.core.locale.Res; import bisq.common.app.AppModule; +import bisq.common.app.DevEnv; import org.springframework.core.env.Environment; @@ -48,6 +51,9 @@ protected void configure() { bind(ResourceBundle.class).toInstance(Res.getResourceBundle()); bind(ViewLoader.class).to(FxmlViewLoader.class).in(Singleton.class); + BsqAddressHelper bsqAddressHelper = new BsqAddressHelper(true || !DevEnv.isDevMode(), BisqEnvironment.getParameters()); + bind(BsqAddressHelper.class).toInstance(bsqAddressHelper); + bindConstant().annotatedWith(Names.named(AppOptionKeys.APP_NAME_KEY)).to(environment.getRequiredProperty(AppOptionKeys.APP_NAME_KEY)); } } diff --git a/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java b/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java index 4409ee39ef2..c6c0dee68a3 100644 --- a/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java +++ b/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java @@ -17,7 +17,8 @@ package bisq.desktop.components; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Coin; @@ -37,7 +38,7 @@ public class BalanceTextField extends AnchorPane { private final JFXTextField textField; private final Effect fundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.GREEN, 4, 0.0, 0, 0); private final Effect notFundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.ORANGERED, 4, 0.0, 0, 0); - private BSFormatter formatter; + private CoinFormatter formatter; @Nullable private Coin balance; @@ -60,7 +61,7 @@ public BalanceTextField(String label) { getChildren().addAll(textField); } - public void setFormatter(BSFormatter formatter) { + public void setFormatter(CoinFormatter formatter) { this.formatter = formatter; } diff --git a/desktop/src/main/java/bisq/desktop/components/BalanceWithConfirmationTextField.java b/desktop/src/main/java/bisq/desktop/components/BalanceWithConfirmationTextField.java index 17a6155bc64..75f13a7929b 100644 --- a/desktop/src/main/java/bisq/desktop/components/BalanceWithConfirmationTextField.java +++ b/desktop/src/main/java/bisq/desktop/components/BalanceWithConfirmationTextField.java @@ -23,7 +23,8 @@ import bisq.core.btc.listeners.AddressConfidenceListener; import bisq.core.btc.listeners.BalanceListener; import bisq.core.btc.wallet.BtcWalletService; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -56,7 +57,7 @@ public static void setWalletService(BtcWalletService walletService) { private final Effect fundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.GREEN, 4, 0.0, 0, 0); private final Effect notFundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.ORANGERED, 4, 0.0, 0, 0); - private BSFormatter formatter; + private CoinFormatter formatter; /////////////////////////////////////////////////////////////////////////////////////////// @@ -91,7 +92,7 @@ public void cleanup() { walletService.removeAddressConfidenceListener(confidenceListener); } - public void setup(Address address, BSFormatter formatter) { + public void setup(Address address, CoinFormatter formatter) { this.formatter = formatter; confidenceListener = new AddressConfidenceListener(address) { @Override diff --git a/desktop/src/main/java/bisq/desktop/components/ColoredDecimalPlacesWithZerosText.java b/desktop/src/main/java/bisq/desktop/components/ColoredDecimalPlacesWithZerosText.java index 6ce8eb71b13..4622d74b940 100644 --- a/desktop/src/main/java/bisq/desktop/components/ColoredDecimalPlacesWithZerosText.java +++ b/desktop/src/main/java/bisq/desktop/components/ColoredDecimalPlacesWithZerosText.java @@ -17,13 +17,12 @@ package bisq.desktop.components; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.util.Tuple2; import javafx.scene.control.Label; import javafx.scene.layout.HBox; -import javafx.scene.text.Text; import javafx.geometry.Pos; @@ -34,12 +33,12 @@ public ColoredDecimalPlacesWithZerosText(String number, int numberOfZerosToColor if (numberOfZerosToColorize <= 0) { getChildren().addAll(new Label(number)); - } else if (number.contains(BSFormatter.RANGE_SEPARATOR)) { - String[] splitNumber = number.split(BSFormatter.RANGE_SEPARATOR); + } else if (number.contains(FormattingUtils.RANGE_SEPARATOR)) { + String[] splitNumber = number.split(FormattingUtils.RANGE_SEPARATOR); Tuple2 numbers = getSplittedNumberNodes(splitNumber[0], numberOfZerosToColorize); getChildren().addAll(numbers.first, numbers.second); - getChildren().add(new Label(BSFormatter.RANGE_SEPARATOR)); + getChildren().add(new Label(FormattingUtils.RANGE_SEPARATOR)); numbers = getSplittedNumberNodes(splitNumber[1], numberOfZerosToColorize); getChildren().addAll(numbers.first, numbers.second); diff --git a/desktop/src/main/java/bisq/desktop/components/PeerInfoIcon.java b/desktop/src/main/java/bisq/desktop/components/PeerInfoIcon.java index 68e4d2f3641..1cd54300210 100644 --- a/desktop/src/main/java/bisq/desktop/components/PeerInfoIcon.java +++ b/desktop/src/main/java/bisq/desktop/components/PeerInfoIcon.java @@ -18,6 +18,7 @@ package bisq.desktop.components; import bisq.desktop.main.overlays.editor.PeerInfoWithTagEditor; +import bisq.desktop.util.DisplayUtils; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.alert.PrivateNotificationManager; @@ -26,7 +27,8 @@ import bisq.core.offer.Offer; import bisq.core.trade.Trade; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.NodeAddress; @@ -75,7 +77,6 @@ public PeerInfoIcon(NodeAddress nodeAddress, Offer offer, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter, boolean useDevPrivilegeKeys) { this(nodeAddress, role, @@ -85,7 +86,6 @@ public PeerInfoIcon(NodeAddress nodeAddress, null, preferences, accountAgeWitnessService, - formatter, useDevPrivilegeKeys); } @@ -97,7 +97,6 @@ public PeerInfoIcon(NodeAddress nodeAddress, Trade trade, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter, boolean useDevPrivilegeKeys) { this(nodeAddress, role, @@ -107,7 +106,6 @@ public PeerInfoIcon(NodeAddress nodeAddress, trade, preferences, accountAgeWitnessService, - formatter, useDevPrivilegeKeys); } @@ -119,7 +117,6 @@ private PeerInfoIcon(NodeAddress nodeAddress, @Nullable Trade trade, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter, boolean useDevPrivilegeKeys) { this.numTrades = numTrades; this.accountAgeWitnessService = accountAgeWitnessService; @@ -141,7 +138,7 @@ private PeerInfoIcon(NodeAddress nodeAddress, boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()); String accountAge = isFiatCurrency ? - peersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(peersAccountAge)) : + peersAccountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(peersAccountAge)) : Res.get("peerInfoIcon.tooltip.unknownAge") : ""; tooltipText = hasTraded ? @@ -239,7 +236,7 @@ private PeerInfoIcon(NodeAddress nodeAddress, getChildren().addAll(outerBackground, innerBackground, avatarImageView, tagPane, numTradesPane); - addMouseListener(numTrades, privateNotificationManager, offer, preferences, formatter, useDevPrivilegeKeys, isFiatCurrency, peersAccountAge); + addMouseListener(numTrades, privateNotificationManager, offer, preferences, useDevPrivilegeKeys, isFiatCurrency, peersAccountAge); } private long getPeersAccountAge(@Nullable Trade trade, @Nullable Offer offer) { @@ -262,13 +259,12 @@ protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, - BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) { final String accountAgeTagEditor = isFiatCurrency ? makersAccountAge > -1 ? - formatter.formatAccountAge(makersAccountAge) : + DisplayUtils.formatAccountAge(makersAccountAge) : Res.get("peerInfo.unknownAge") : null; setOnMouseClicked(e -> new PeerInfoWithTagEditor(privateNotificationManager, offer, preferences, useDevPrivilegeKeys) diff --git a/desktop/src/main/java/bisq/desktop/components/PeerInfoIconSmall.java b/desktop/src/main/java/bisq/desktop/components/PeerInfoIconSmall.java index c07bc5ff328..f37dd9f037c 100644 --- a/desktop/src/main/java/bisq/desktop/components/PeerInfoIconSmall.java +++ b/desktop/src/main/java/bisq/desktop/components/PeerInfoIconSmall.java @@ -4,7 +4,8 @@ import bisq.core.alert.PrivateNotificationManager; import bisq.core.offer.Offer; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.NodeAddress; @@ -13,7 +14,6 @@ public PeerInfoIconSmall(NodeAddress nodeAddress, String role, Offer offer, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter, boolean useDevPrivilegeKeys) { // We don't want to show number of trades in that case as it would be unreadable. // Also we don't need the privateNotificationManager as no interaction will take place with this icon. @@ -23,7 +23,6 @@ public PeerInfoIconSmall(NodeAddress nodeAddress, offer, preferences, accountAgeWitnessService, - formatter, useDevPrivilegeKeys); } @@ -36,7 +35,6 @@ protected double getScaleFactor() { protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, - BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) { diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AdvancedCashForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AdvancedCashForm.java index e605b48cfa5..518ece225ff 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AdvancedCashForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AdvancedCashForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.AdvancedCashAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -63,7 +64,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, } public AdvancedCashForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, AdvancedCashValidator advancedCashValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.advancedCashAccount = (AdvancedCashAccount) paymentAccount; this.advancedCashValidator = advancedCashValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AliPayForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AliPayForm.java index 1d93e374f06..b0b921f77d0 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AliPayForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AliPayForm.java @@ -25,7 +25,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.AliPayAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -41,7 +42,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount return gridRow; } - public AliPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, AliPayValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public AliPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, AliPayValidator aliPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.aliPayAccount = (AliPayAccount) paymentAccount; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AssetsForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AssetsForm.java index 58078de9e49..3c28ad7304e 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/AssetsForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/AssetsForm.java @@ -37,11 +37,15 @@ import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.validation.AltCoinAddressValidator; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple3; +import javax.inject.Named; + import org.apache.commons.lang3.StringUtils; import javafx.scene.control.CheckBox; @@ -90,7 +94,7 @@ public AssetsForm(PaymentAccount paymentAccount, InputValidator inputValidator, GridPane gridPane, int gridRow, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, AssetService assetService, FilterManager filterManager, Preferences preferences) { diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/BankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/BankForm.java index f9b2d13127f..3295a62d1ee 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/BankForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/BankForm.java @@ -33,7 +33,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.BankAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -167,7 +168,7 @@ static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccountPayload private Country selectedCountry; BankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.bankAccountPayload = (BankAccountPayload) paymentAccount.paymentAccountPayload; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/CashDepositForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/CashDepositForm.java index d61d204392f..a7949c41499 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/CashDepositForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/CashDepositForm.java @@ -34,7 +34,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.CashDepositAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -182,7 +183,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount private Country selectedCountry; public CashDepositForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.cashDepositAccountPayload = (CashDepositAccountPayload) paymentAccount.paymentAccountPayload; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/ChaseQuickPayForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ChaseQuickPayForm.java index 77bc4f7eaec..518d4a28650 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/ChaseQuickPayForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ChaseQuickPayForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.ChaseQuickPayAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -53,7 +54,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount } public ChaseQuickPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, ChaseQuickPayValidator chaseQuickPayValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.chaseQuickPayAccount = (ChaseQuickPayAccount) paymentAccount; this.chaseQuickPayValidator = chaseQuickPayValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/ClearXchangeForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ClearXchangeForm.java index 85111a06c81..7da0f7df614 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/ClearXchangeForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/ClearXchangeForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.ClearXchangeAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -52,7 +53,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount return gridRow; } - public ClearXchangeForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, ClearXchangeValidator clearXchangeValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public ClearXchangeForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, ClearXchangeValidator clearXchangeValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.clearXchangeAccount = (ClearXchangeAccount) paymentAccount; this.clearXchangeValidator = clearXchangeValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/F2FForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/F2FForm.java index 10f10f2e7da..11e171a3e07 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/F2FForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/F2FForm.java @@ -36,7 +36,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.F2FAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -74,7 +75,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, public F2FForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, F2FValidator f2fValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.f2fAccount = (F2FAccount) paymentAccount; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/FasterPaymentsForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/FasterPaymentsForm.java index ad68a8f8dc1..3c350fae6a7 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/FasterPaymentsForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/FasterPaymentsForm.java @@ -30,7 +30,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.FasterPaymentsAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -58,7 +59,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, private InputTextField sortCodeInputTextField; public FasterPaymentsForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, - int gridRow, BSFormatter formatter) { + int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.fasterPaymentsAccount = (FasterPaymentsAccount) paymentAccount; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralAccountNumberForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralAccountNumberForm.java index 7cf16a67cbf..0f3e438de80 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralAccountNumberForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralAccountNumberForm.java @@ -8,7 +8,8 @@ import bisq.core.locale.TradeCurrency; import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentMethod; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -22,7 +23,7 @@ abstract public class GeneralAccountNumberForm extends PaymentMethodForm { private InputTextField accountNrInputTextField; - GeneralAccountNumberForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + GeneralAccountNumberForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralBankForm.java index 9ea45fd7b7c..b9789f041a0 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralBankForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralBankForm.java @@ -11,7 +11,8 @@ import bisq.core.locale.Res; import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.CountryBasedPaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import org.apache.commons.lang3.StringUtils; @@ -38,7 +39,7 @@ public abstract class GeneralBankForm extends PaymentMethodForm { boolean accountNrInputTextFieldEdited; - public GeneralBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public GeneralBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralSepaForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralSepaForm.java index 83a14f39234..41e36b22c99 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralSepaForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/GeneralSepaForm.java @@ -10,7 +10,8 @@ import bisq.core.locale.TradeCurrency; import bisq.core.payment.CountryBasedPaymentAccount; import bisq.core.payment.PaymentAccount; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import org.apache.commons.lang3.StringUtils; @@ -45,7 +46,7 @@ public abstract class GeneralSepaForm extends PaymentMethodForm { private ComboBox currencyComboBox; InputTextField ibanInputTextField; - GeneralSepaForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + GeneralSepaForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/HalCashForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/HalCashForm.java index 2aaff157a57..770db97eaae 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/HalCashForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/HalCashForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.HalCashAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -51,7 +52,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, } public HalCashForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, HalCashValidator halCashValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.halCashAccount = (HalCashAccount) paymentAccount; this.halCashValidator = halCashValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/InteracETransferForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/InteracETransferForm.java index bbde09363fd..ced3db6ac6b 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/InteracETransferForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/InteracETransferForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.InteracETransferAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -57,7 +58,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, } public InteracETransferForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InteracETransferValidator interacETransferValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.interacETransferAccount = (InteracETransferAccount) paymentAccount; this.interacETransferValidator = interacETransferValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyBeamForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyBeamForm.java index 1659b16a018..e8b0b3bf0f5 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyBeamForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyBeamForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.MoneyBeamAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -49,7 +50,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount return gridRow; } - public MoneyBeamForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, MoneyBeamValidator moneyBeamValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public MoneyBeamForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, MoneyBeamValidator moneyBeamValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.account = (MoneyBeamAccount) paymentAccount; this.validator = moneyBeamValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java index 9fe85cd0a9b..3f0de38ef87 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/MoneyGramForm.java @@ -32,7 +32,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.MoneyGramAccountPayload; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -74,7 +75,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, private final EmailValidator emailValidator; public MoneyGramForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.moneyGramAccountPayload = (MoneyGramAccountPayload) paymentAccount.paymentAccountPayload; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/NationalBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/NationalBankForm.java index c0753c61af2..a6a37069c6b 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/NationalBankForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/NationalBankForm.java @@ -20,7 +20,7 @@ import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -31,7 +31,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount } public NationalBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); } } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaymentMethodForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaymentMethodForm.java index 2f962975e7d..65c2725da2d 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaymentMethodForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PaymentMethodForm.java @@ -21,6 +21,7 @@ import bisq.desktop.components.InfoTextField; import bisq.desktop.components.InputTextField; import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.FormBuilder; import bisq.desktop.util.Layout; @@ -33,7 +34,9 @@ import bisq.core.offer.Offer; import bisq.core.payment.AssetAccount; import bisq.core.payment.PaymentAccount; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple3; @@ -41,6 +44,8 @@ import org.bitcoinj.core.Coin; +import javax.inject.Named; + import org.apache.commons.lang3.StringUtils; import javafx.scene.control.CheckBox; @@ -72,7 +77,7 @@ public abstract class PaymentMethodForm { protected final InputValidator inputValidator; protected final GridPane gridPane; protected int gridRow; - private final BSFormatter formatter; + private final CoinFormatter formatter; protected final BooleanProperty allInputsValid = new SimpleBooleanProperty(); protected int gridRowFrom; @@ -81,7 +86,7 @@ public abstract class PaymentMethodForm { protected ComboBox currencyComboBox; public PaymentMethodForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { this.paymentAccount = paymentAccount; this.accountAgeWitnessService = accountAgeWitnessService; this.inputValidator = inputValidator; @@ -182,7 +187,7 @@ else if (!paymentAccount.getTradeCurrencies().isEmpty()) Res.get("payment.maxPeriodAndLimit", getTimeText(hours), formatter.formatCoinWithCode(Coin.valueOf(accountAgeWitnessService.getMyTradeLimit(paymentAccount, tradeCurrency.getCode()))), - formatter.formatAccountAge(accountAge)); + DisplayUtils.formatAccountAge(accountAge)); if (isDisplayForm) addCompactTopLabelTextField(gridPane, ++gridRow, Res.get("payment.limitations"), limitationsText); diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PerfectMoneyForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PerfectMoneyForm.java index 4e71a5a92ef..dde495034de 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PerfectMoneyForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PerfectMoneyForm.java @@ -26,7 +26,8 @@ import bisq.core.payment.PerfectMoneyAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PerfectMoneyAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -45,7 +46,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount } public PerfectMoneyForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, PerfectMoneyValidator perfectMoneyValidator, InputValidator inputValidator, GridPane gridPane, int - gridRow, BSFormatter formatter) { + gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.perfectMoneyAccount = (PerfectMoneyAccount) paymentAccount; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PopmoneyForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PopmoneyForm.java index ee1e3666b73..ad1c857a831 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PopmoneyForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PopmoneyForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.PopmoneyAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PopmoneyAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -51,7 +52,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount return gridRow; } - public PopmoneyForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, PopmoneyValidator popmoneyValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public PopmoneyForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, PopmoneyValidator popmoneyValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.account = (PopmoneyAccount) paymentAccount; this.validator = popmoneyValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PromptPayForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PromptPayForm.java index c5c5f47ff5e..edfded9a654 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/PromptPayForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/PromptPayForm.java @@ -28,7 +28,8 @@ import bisq.core.payment.PromptPayAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PromptPayAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -51,7 +52,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, } public PromptPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, PromptPayValidator promptPayValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.promptPayAccount = (PromptPayAccount) paymentAccount; this.promptPayValidator = promptPayValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/RevolutForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/RevolutForm.java index d9d26dc833b..4fdec4e031d 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/RevolutForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/RevolutForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.RevolutAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.RevolutAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -64,7 +65,7 @@ private static String getTitle(String accountId) { public RevolutForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, RevolutValidator revolutValidator, InputValidator inputValidator, GridPane gridPane, - int gridRow, BSFormatter formatter) { + int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.account = (RevolutAccount) paymentAccount; this.validator = revolutValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SameBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SameBankForm.java index 617e224f4c6..9211f504dfc 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SameBankForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SameBankForm.java @@ -20,7 +20,8 @@ import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -32,7 +33,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount } public SameBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); } } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaForm.java index fe9d2619f7c..25a6b9921f2 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaForm.java @@ -34,7 +34,8 @@ import bisq.core.payment.SepaAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.SepaAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.CheckBox; @@ -77,7 +78,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, public SepaForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, IBANValidator ibanValidator, BICValidator bicValidator, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.sepaAccount = (SepaAccount) paymentAccount; this.ibanValidator = ibanValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaInstantForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaInstantForm.java index 9d2149bfc37..5a4849a4b30 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaInstantForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SepaInstantForm.java @@ -34,7 +34,8 @@ import bisq.core.payment.SepaInstantAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.SepaInstantAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.CheckBox; @@ -77,7 +78,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, public SepaInstantForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, IBANValidator ibanValidator, BICValidator bicValidator, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.sepaInstantAccount = (SepaInstantAccount) paymentAccount; this.ibanValidator = ibanValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SpecificBankForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SpecificBankForm.java index 96bcb07a6ed..f9e83bf2692 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SpecificBankForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SpecificBankForm.java @@ -24,7 +24,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.SpecificBanksAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple3; @@ -53,7 +54,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount } public SpecificBankForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.specificBanksAccountPayload = (SpecificBanksAccountPayload) paymentAccount.paymentAccountPayload; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwishForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwishForm.java index 6f7880dbef5..4c7c5be7898 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwishForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/SwishForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.SwishAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.SwishAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -53,7 +54,7 @@ public SwishForm(PaymentAccount paymentAccount, InputValidator inputValidator, GridPane gridPane, int gridRow, - BSFormatter formatter) { + CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.swishAccount = (SwishAccount) paymentAccount; this.swishValidator = swishValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/USPostalMoneyOrderForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/USPostalMoneyOrderForm.java index fbb988e8c6e..d152c80900f 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/USPostalMoneyOrderForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/USPostalMoneyOrderForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.USPostalMoneyOrderAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.USPostalMoneyOrderAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextArea; @@ -56,7 +57,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, public USPostalMoneyOrderForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, USPostalMoneyOrderValidator usPostalMoneyOrderValidator, - InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.usPostalMoneyOrderAccount = (USPostalMoneyOrderAccount) paymentAccount; this.usPostalMoneyOrderValidator = usPostalMoneyOrderValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpholdForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpholdForm.java index 9e00124a9b1..ff9f2e3e5d0 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpholdForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/UpholdForm.java @@ -29,7 +29,8 @@ import bisq.core.payment.UpholdAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.UpholdAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.control.TextField; @@ -54,7 +55,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, public UpholdForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, UpholdValidator upholdValidator, InputValidator inputValidator, GridPane gridPane, - int gridRow, BSFormatter formatter) { + int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.upholdAccount = (UpholdAccount) paymentAccount; this.upholdValidator = upholdValidator; diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/WeChatPayForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/WeChatPayForm.java index 60ba1bd3eee..f91163aa157 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/WeChatPayForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/WeChatPayForm.java @@ -25,7 +25,8 @@ import bisq.core.payment.WeChatPayAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.WeChatPayAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import javafx.scene.layout.GridPane; @@ -41,7 +42,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, PaymentAccount return gridRow; } - public WeChatPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, WeChatPayValidator weChatPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, BSFormatter formatter) { + public WeChatPayForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, WeChatPayValidator weChatPayValidator, InputValidator inputValidator, GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.weChatPayAccount = (WeChatPayAccount) paymentAccount; } diff --git a/desktop/src/main/java/bisq/desktop/components/paymentmethods/WesternUnionForm.java b/desktop/src/main/java/bisq/desktop/components/paymentmethods/WesternUnionForm.java index 1526ece2842..774ce6454c6 100644 --- a/desktop/src/main/java/bisq/desktop/components/paymentmethods/WesternUnionForm.java +++ b/desktop/src/main/java/bisq/desktop/components/paymentmethods/WesternUnionForm.java @@ -34,7 +34,8 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.WesternUnionAccountPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.util.Tuple2; @@ -76,7 +77,7 @@ public static int addFormForBuyer(GridPane gridPane, int gridRow, private Country selectedCountry; public WesternUnionForm(PaymentAccount paymentAccount, AccountAgeWitnessService accountAgeWitnessService, InputValidator inputValidator, - GridPane gridPane, int gridRow, BSFormatter formatter) { + GridPane gridPane, int gridRow, CoinFormatter formatter) { super(paymentAccount, accountAgeWitnessService, inputValidator, gridPane, gridRow, formatter); this.westernUnionAccountPayload = (WesternUnionAccountPayload) paymentAccount.paymentAccountPayload; diff --git a/desktop/src/main/java/bisq/desktop/main/Chat/Chat.java b/desktop/src/main/java/bisq/desktop/main/Chat/Chat.java index d6a10383684..a028acad809 100644 --- a/desktop/src/main/java/bisq/desktop/main/Chat/Chat.java +++ b/desktop/src/main/java/bisq/desktop/main/Chat/Chat.java @@ -24,6 +24,7 @@ import bisq.desktop.components.TableGroupHeadline; import bisq.desktop.components.TextFieldWithIcon; import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.arbitration.Attachment; @@ -32,7 +33,8 @@ import bisq.core.chat.ChatSession; import bisq.core.locale.Res; import bisq.core.trade.TradeChatSession; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; @@ -137,11 +139,11 @@ public class Chat extends AnchorPane { private ChangeListener storedInMailboxPropertyListener, arrivedPropertyListener; private ChangeListener sendMessageErrorPropertyListener; - protected final BSFormatter formatter; + protected final CoinFormatter formatter; private EventHandler keyEventEventHandler; private ChatManager chatManager; - public Chat(ChatManager chatManager, BSFormatter formatter) { + public Chat(ChatManager chatManager, CoinFormatter formatter) { this.chatManager = chatManager; this.formatter = formatter; this.p2PService = chatManager.getP2PService(); @@ -404,7 +406,7 @@ public void updateItem(final DisputeCommunicationMessage message, boolean empty) AnchorPane.setLeftAnchor(statusHBox, padding); } AnchorPane.setBottomAnchor(statusHBox, 7d); - headerLabel.setText(formatter.formatDateTime(new Date(message.getDate()))); + headerLabel.setText(DisplayUtils.formatDateTime(new Date(message.getDate()))); messageLabel.setText(message.getMessage()); attachmentsBox.getChildren().clear(); if (allowAttachments && diff --git a/desktop/src/main/java/bisq/desktop/main/MainView.java b/desktop/src/main/java/bisq/desktop/main/MainView.java index d578150e99b..690bbb2e132 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainView.java +++ b/desktop/src/main/java/bisq/desktop/main/MainView.java @@ -37,13 +37,14 @@ import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.portfolio.PortfolioView; import bisq.desktop.main.settings.SettingsView; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.Transitions; import bisq.core.dao.monitoring.DaoStateMonitoringService; import bisq.core.exceptions.BisqException; import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.common.Timer; import bisq.common.UserThread; @@ -139,7 +140,6 @@ public static void removeEffect() { private final ViewLoader viewLoader; private final Navigation navigation; - private final BSFormatter formatter; private final ToggleGroup navButtons = new ToggleGroup(); private ChangeListener walletServiceErrorMsgListener; @@ -159,12 +159,10 @@ public MainView(MainViewModel model, CachingViewLoader viewLoader, Navigation navigation, Transitions transitions, - BSFormatter formatter, DaoStateMonitoringService daoStateMonitoringService) { super(model); this.viewLoader = viewLoader; this.navigation = navigation; - this.formatter = formatter; MainView.transitions = transitions; this.daoStateMonitoringService = daoStateMonitoringService; } @@ -522,14 +520,14 @@ private String getPriceProviderTooltipString() { res = Res.get("mainView.marketPrice.tooltip", "https://bitcoinaverage.com", "", - formatter.formatTime(model.getPriceFeedService().getLastRequestTimeStampBtcAverage()), + DisplayUtils.formatTime(model.getPriceFeedService().getLastRequestTimeStampBtcAverage()), model.getPriceFeedService().getProviderNodeAddress()); } else { String altcoinExtra = "\n" + Res.get("mainView.marketPrice.tooltip.altcoinExtra"); res = Res.get("mainView.marketPrice.tooltip", "https://poloniex.com", altcoinExtra, - formatter.formatTime(model.getPriceFeedService().getLastRequestTimeStampPoloniex()), + DisplayUtils.formatTime(model.getPriceFeedService().getLastRequestTimeStampPoloniex()), model.getPriceFeedService().getProviderNodeAddress()); } return res; diff --git a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java index 61aefb01d4f..7a7a8066781 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/MainViewModel.java @@ -32,6 +32,7 @@ import bisq.desktop.main.overlays.windows.downloadupdate.DisplayUpdateDownloadWindow; import bisq.desktop.main.presentation.DaoPresentation; import bisq.desktop.main.presentation.MarketPricePresentation; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.account.witness.AccountAgeWitnessService; @@ -54,7 +55,7 @@ import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.BootstrapListener; import bisq.network.p2p.P2PService; @@ -117,7 +118,6 @@ public class MainViewModel implements ViewModel, BisqSetup.BisqSetupCompleteList @Getter private final TorNetworkSettingsWindow torNetworkSettingsWindow; private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler; - private final BSFormatter formatter; @Getter private BooleanProperty showAppScreen = new SimpleBooleanProperty(); @@ -157,8 +157,7 @@ public MainViewModel(BisqSetup bisqSetup, BisqEnvironment bisqEnvironment, AccountAgeWitnessService accountAgeWitnessService, TorNetworkSettingsWindow torNetworkSettingsWindow, - CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler, - BSFormatter formatter) { + CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) { this.bisqSetup = bisqSetup; this.walletsSetup = walletsSetup; this.user = user; @@ -179,7 +178,6 @@ public MainViewModel(BisqSetup bisqSetup, this.accountAgeWitnessService = accountAgeWitnessService; this.torNetworkSettingsWindow = torNetworkSettingsWindow; this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler; - this.formatter = formatter; TxIdTextField.setPreferences(preferences); @@ -218,7 +216,7 @@ public void onSetupComplete() { DontShowAgainLookup.dontShowAgain(key, true); new Popup<>().warning(Res.get("popup.warning.tradePeriod.halfReached", trade.getShortId(), - formatter.formatDateTime(maxTradePeriodDate))) + DisplayUtils.formatDateTime(maxTradePeriodDate))) .show(); } break; @@ -228,7 +226,7 @@ public void onSetupComplete() { DontShowAgainLookup.dontShowAgain(key, true); new Popup<>().warning(Res.get("popup.warning.tradePeriod.ended", trade.getShortId(), - formatter.formatDateTime(maxTradePeriodDate))) + DisplayUtils.formatDateTime(maxTradePeriodDate))) .show(); } break; diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsView.java b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsView.java index ba0048bccdf..c9d39cb6825 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/altcoinaccounts/AltCoinAccountsView.java @@ -38,7 +38,8 @@ import bisq.core.payment.payload.PaymentMethod; import bisq.core.payment.validation.AltCoinAddressValidator; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import bisq.core.util.validation.InputValidator; import bisq.asset.AltCoinAccountDisclaimer; @@ -48,6 +49,7 @@ import bisq.common.util.Tuple3; import javax.inject.Inject; +import javax.inject.Named; import javafx.stage.Stage; @@ -75,7 +77,7 @@ public class AltCoinAccountsView extends PaymentAccountsView paymentMethodComboBox; private PaymentMethodForm paymentMethodForm; private TitledGroupBg accountTitledGroupBg; @@ -167,7 +169,7 @@ public FiatAccountsView(FiatAccountsViewModel model, PromptPayValidator promptPayValidator, AdvancedCashValidator advancedCashValidator, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { super(model); this.ibanValidator = ibanValidator; diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/notifications/ManageMarketAlertsWindow.java b/desktop/src/main/java/bisq/desktop/main/account/content/notifications/ManageMarketAlertsWindow.java index 71cd1bfe583..0297645fabb 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/notifications/ManageMarketAlertsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/notifications/ManageMarketAlertsWindow.java @@ -26,10 +26,14 @@ import bisq.core.locale.Res; import bisq.core.notifications.alerts.market.MarketAlertFilter; import bisq.core.notifications.alerts.market.MarketAlerts; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.UserThread; +import javax.inject.Named; + import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TableCell; @@ -53,11 +57,9 @@ public class ManageMarketAlertsWindow extends Overlay { private final MarketAlerts marketAlerts; - private final BSFormatter formatter; - ManageMarketAlertsWindow(MarketAlerts marketAlerts, BSFormatter formatter) { + ManageMarketAlertsWindow(MarketAlerts marketAlerts) { this.marketAlerts = marketAlerts; - this.formatter = formatter; type = Type.Attention; } @@ -140,7 +142,7 @@ public TableCell call(TableColumn { private final PriceFeedService priceFeedService; private final MarketAlerts marketAlerts; private final MobileNotificationService mobileNotificationService; - private final BSFormatter formatter; private WebCamWindow webCamWindow; private QrCodeReader qrCodeReader; @@ -124,15 +126,13 @@ private MobileNotificationsView(Preferences preferences, User user, PriceFeedService priceFeedService, MarketAlerts marketAlerts, - MobileNotificationService mobileNotificationService, - BSFormatter formatter) { + MobileNotificationService mobileNotificationService) { super(); this.preferences = preferences; this.user = user; this.priceFeedService = priceFeedService; this.marketAlerts = marketAlerts; this.mobileNotificationService = mobileNotificationService; - this.formatter = formatter; } @Override @@ -347,7 +347,7 @@ private void onPaymentAccountSelected() { private void onAddMarketAlert() { PaymentAccount paymentAccount = paymentAccountsComboBox.getSelectionModel().getSelectedItem(); - double percentAsDouble = formatter.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); @@ -356,7 +356,7 @@ private void onAddMarketAlert() { } private void onManageMarketAlerts() { - new ManageMarketAlertsWindow(marketAlerts, formatter) + new ManageMarketAlertsWindow(marketAlerts) .onClose(this::updateMarketAlertFields) .show(); } @@ -510,8 +510,8 @@ public PaymentAccount fromString(String string) { marketAlertTriggerFocusListener = (observable, oldValue, newValue) -> { if (oldValue && !newValue) { try { - double percentAsDouble = formatter.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100; - marketAlertTriggerInputTextField.setText(formatter.formatRoundedDoubleWithPrecision(percentAsDouble, 2) + "%"); + double percentAsDouble = ParsingUtils.parsePercentStringToDouble(marketAlertTriggerInputTextField.getText()) * 100; + marketAlertTriggerInputTextField.setText(FormattingUtils.formatRoundedDoubleWithPrecision(percentAsDouble, 2) + "%"); } catch (Throwable ignore) { } @@ -695,8 +695,8 @@ private void fillPriceAlertFields() { currencyComboBox.getSelectionModel().select(optionalTradeCurrency.get()); onSelectedTradeCurrency(); - priceAlertHighInputTextField.setText(formatter.formatMarketPrice(priceAlertFilter.getHigh() / 10000d, currencyCode)); - priceAlertLowInputTextField.setText(formatter.formatMarketPrice(priceAlertFilter.getLow() / 10000d, currencyCode)); + priceAlertHighInputTextField.setText(FormattingUtils.formatMarketPrice(priceAlertFilter.getHigh() / 10000d, currencyCode)); + priceAlertLowInputTextField.setText(FormattingUtils.formatMarketPrice(priceAlertFilter.getLow() / 10000d, currencyCode)); } else { currencyComboBox.getSelectionModel().clearSelection(); } @@ -747,15 +747,15 @@ private long getPriceAsLong(InputTextField inputTextField) { try { String inputValue = inputTextField.getText(); if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) { - double priceAsDouble = formatter.parseNumberStringToDouble(inputValue); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue); String currencyCode = selectedPriceAlertTradeCurrency; int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : 2; // We want to use the converted value not the inout value as we apply the converted value at focus out. // 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 = formatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision); - return formatter.parsePriceStringToLong(currencyCode, stringValue, precision); + String stringValue = FormattingUtils.formatRoundedDoubleWithPrecision(priceAsDouble, precision); + return ParsingUtils.parsePriceStringToLong(currencyCode, stringValue, precision); } else { return 0; } @@ -768,11 +768,11 @@ private void applyPriceFormatting(InputTextField inputTextField) { try { String inputValue = inputTextField.getText(); if (inputValue != null && !inputValue.isEmpty() && selectedPriceAlertTradeCurrency != null) { - double priceAsDouble = formatter.parseNumberStringToDouble(inputValue); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(inputValue); String currencyCode = selectedPriceAlertTradeCurrency; int precision = CurrencyUtil.isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : 2; - String stringValue = formatter.formatRoundedDoubleWithPrecision(priceAsDouble, precision); + String stringValue = FormattingUtils.formatRoundedDoubleWithPrecision(priceAsDouble, precision); inputTextField.setText(stringValue); } } catch (Throwable ignore) { diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java index bd0a998099e..e22f02162a7 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/BondingViewUtils.java @@ -34,9 +34,11 @@ import bisq.core.dao.state.model.governance.Role; import bisq.core.dao.state.model.governance.RoleProposal; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinUtil; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; @@ -47,6 +49,7 @@ import org.bitcoinj.core.InsufficientMoneyException; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import java.util.Optional; @@ -66,6 +69,7 @@ public class BondingViewUtils { private final DaoFacade daoFacade; private final Navigation navigation; private final BsqFormatter bsqFormatter; + private final CoinFormatter btcFormatter; @Inject public BondingViewUtils(P2PService p2PService, @@ -74,6 +78,7 @@ public BondingViewUtils(P2PService p2PService, WalletsSetup walletsSetup, DaoFacade daoFacade, Navigation navigation, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { this.p2PService = p2PService; this.myReputationListService = myReputationListService; @@ -82,6 +87,7 @@ public BondingViewUtils(P2PService p2PService, this.daoFacade = daoFacade; this.navigation = navigation; this.bsqFormatter = bsqFormatter; + this.btcFormatter = btcFormatter; } public void lockupBondForBondedRole(Role role, Consumer resultHandler) { @@ -112,14 +118,13 @@ private void lockupBond(byte[] hash, Coin lockupAmount, int lockupTime, LockupRe Tuple2 miningFeeAndTxSize = daoFacade.getLockupTxMiningFeeAndTxSize(lockupAmount, lockupTime, lockupReason, hash); Coin miningFee = miningFeeAndTxSize.first; int txSize = miningFeeAndTxSize.second; - BSFormatter formatter = new BSFormatter(); - String duration = formatter.formatDurationAsWords(lockupTime * 10 * 60 * 1000L, false, false); + String duration = FormattingUtils.formatDurationAsWords(lockupTime * 10 * 60 * 1000L, false, false); new Popup<>().headLine(Res.get("dao.bond.reputation.lockup.headline")) .confirmation(Res.get("dao.bond.reputation.lockup.details", bsqFormatter.formatCoinWithCode(lockupAmount), lockupTime, duration, - formatter.formatCoinWithCode(miningFee), + btcFormatter.formatCoinWithCode(miningFee), CoinUtil.getFeePerByte(miningFee, txSize), txSize / 1000d )) @@ -173,14 +178,13 @@ public void unLock(String lockupTxId, Consumer resultHandler) { Tuple2 miningFeeAndTxSize = daoFacade.getUnlockTxMiningFeeAndTxSize(lockupTxId); Coin miningFee = miningFeeAndTxSize.first; int txSize = miningFeeAndTxSize.second; - BSFormatter formatter = new BSFormatter(); - String duration = formatter.formatDurationAsWords(lockTime * 10 * 60 * 1000L, false, false); + String duration = FormattingUtils.formatDurationAsWords(lockTime * 10 * 60 * 1000L, false, false); new Popup<>().headLine(Res.get("dao.bond.reputation.unlock.headline")) .confirmation(Res.get("dao.bond.reputation.unlock.details", bsqFormatter.formatCoinWithCode(unlockAmount), lockTime, duration, - formatter.formatCoinWithCode(miningFee), + btcFormatter.formatCoinWithCode(miningFee), CoinUtil.getFeePerByte(miningFee, txSize), txSize / 1000d )) diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java index 72844399373..6164a6a3409 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondListItem.java @@ -17,11 +17,13 @@ package bisq.desktop.main.dao.bonding.bonds; +import bisq.desktop.util.DisplayUtils; + import bisq.core.dao.governance.bond.Bond; import bisq.core.dao.governance.bond.BondState; import bisq.core.dao.governance.bond.role.BondedRole; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Utilities; @@ -58,7 +60,7 @@ class BondListItem { bondDetails = Utilities.bytesAsHexString(bond.getBondedAsset().getHash()); } lockupTxId = bond.getLockupTxId(); - lockupDateString = bond.getLockupDate() > 0 ? bsqFormatter.formatDateTime(new Date(bond.getLockupDate())) : "-"; + lockupDateString = bond.getLockupDate() > 0 ? DisplayUtils.formatDateTime(new Date(bond.getLockupDate())) : "-"; bondState = bond.getBondState(); bondStateString = Res.get("dao.bond.bondState." + bond.getBondState().name()); } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java index 6bff38ff018..fd60be4f428 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/bonds/BondsView.java @@ -32,7 +32,7 @@ import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import javax.inject.Inject; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationListItem.java index 631f34202bd..d3e75f1010f 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/reputation/MyReputationListItem.java @@ -17,11 +17,13 @@ package bisq.desktop.main.dao.bonding.reputation; +import bisq.desktop.util.DisplayUtils; + import bisq.core.dao.governance.bond.BondState; import bisq.core.dao.governance.bond.reputation.MyBondedReputation; import bisq.core.dao.governance.bond.reputation.MyReputation; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Utilities; @@ -57,7 +59,7 @@ class MyReputationListItem { txId = myBondedReputation.getLockupTxId(); amount = bsqFormatter.formatCoin(Coin.valueOf(myBondedReputation.getAmount())); lockupDate = new Date(myBondedReputation.getLockupDate()); - lockupDateString = bsqFormatter.formatDateTime(lockupDate); + lockupDateString = DisplayUtils.formatDateTime(lockupDate); lockTime = Integer.toString(myBondedReputation.getLockTime()); lockupTxId = myBondedReputation.getLockupTxId(); bondState = myBondedReputation.getBondState(); 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..ca44744d394 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 @@ -37,7 +37,8 @@ import bisq.core.dao.governance.bond.reputation.MyBondedReputation; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.BsqFormatter; 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/bonding/roles/RoleDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RoleDetailsWindow.java index fa3813800ec..34af93981e5 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RoleDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RoleDetailsWindow.java @@ -19,12 +19,13 @@ import bisq.desktop.main.overlays.Overlay; import bisq.desktop.util.FormBuilder; +import bisq.desktop.util.DisplayUtils; import bisq.core.dao.DaoFacade; import bisq.core.dao.state.model.governance.BondedRoleType; import bisq.core.dao.state.model.governance.RoleProposal; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import org.bitcoinj.core.Coin; @@ -97,6 +98,6 @@ private void addContent() { bondedRoleType.getLink(), bondedRoleType.getLink(), 0); FormBuilder.addTopLabelTextField(gridPane, ++rowIndex, Res.get("dao.bond.details.isSingleton"), - bsqFormatter.booleanToYesNo(bondedRoleType.isAllowMultipleHolders())); + DisplayUtils.booleanToYesNo(bondedRoleType.isAllowMultipleHolders())); } } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RolesView.java b/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RolesView.java index 0e8c4078312..a346fbcdea5 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RolesView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/bonding/roles/RolesView.java @@ -33,7 +33,7 @@ import bisq.core.dao.state.model.governance.RoleProposal; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import javax.inject.Inject; 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..c1e46be70cf 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 @@ -34,8 +34,10 @@ import bisq.core.dao.governance.proposal.TxException; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.app.DevEnv; @@ -44,6 +46,7 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; @@ -85,7 +88,7 @@ public class AssetFeeView extends ActivatableView implements Bsq private final BsqWalletService bsqWalletService; private final BsqValidator bsqValidator; private final AssetService assetService; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final ObservableList observableList = FXCollections.observableArrayList(); private final SortedList sortedList = new SortedList<>(observableList); @@ -108,7 +111,7 @@ private AssetFeeView(BsqFormatter bsqFormatter, BsqWalletService bsqWalletService, BsqValidator bsqValidator, AssetService assetService, - BSFormatter btcFormatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter) { this.bsqFormatter = bsqFormatter; this.bsqWalletService = bsqWalletService; this.bsqValidator = bsqValidator; @@ -273,7 +276,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/assetfee/AssetListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetListItem.java index 4e3a4063645..3f49e0edabe 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/assetfee/AssetListItem.java @@ -19,7 +19,7 @@ import bisq.core.dao.governance.asset.StatefulAsset; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import lombok.Value; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/MyProofOfBurnListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/MyProofOfBurnListItem.java index b1764e4e001..0fe3afe1894 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/MyProofOfBurnListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/MyProofOfBurnListItem.java @@ -17,11 +17,13 @@ package bisq.desktop.main.dao.burnbsq.proofofburn; +import bisq.desktop.util.DisplayUtils; + import bisq.core.dao.governance.proofofburn.MyProofOfBurn; import bisq.core.dao.governance.proofofburn.ProofOfBurnService; import bisq.core.dao.state.model.blockchain.Tx; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Utilities; @@ -52,7 +54,7 @@ class MyProofOfBurnListItem { if (optionalTx.isPresent()) { Tx tx = optionalTx.get(); date = new Date(tx.getTime()); - dateAsString = bsqFormatter.formatDateTime(date); + dateAsString = DisplayUtils.formatDateTime(date); amount = proofOfBurnService.getAmount(tx); amountAsString = bsqFormatter.formatCoinWithCode(Coin.valueOf(amount)); txId = tx.getId(); diff --git a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnListItem.java index 2e1254b1376..5dfe0fbdf8b 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/burnbsq/proofofburn/ProofOfBurnListItem.java @@ -17,9 +17,11 @@ package bisq.desktop.main.dao.burnbsq.proofofburn; +import bisq.desktop.util.DisplayUtils; + import bisq.core.dao.governance.proofofburn.ProofOfBurnService; import bisq.core.dao.state.model.blockchain.Tx; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Utilities; @@ -46,6 +48,6 @@ class ProofOfBurnListItem { hashAsHex = Utilities.bytesAsHexString(proofOfBurnService.getHashFromOpReturnData(tx)); pubKey = Utilities.bytesAsHexString(proofOfBurnService.getPubKey(txId)); date = new Date(tx.getTime()); - dateAsString = bsqFormatter.formatDateTime(date); + dateAsString = DisplayUtils.formatDateTime(date); } } 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..06024837a54 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 @@ -36,8 +36,11 @@ import bisq.core.dao.governance.proposal.TxException; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.InputValidator; import bisq.common.app.DevEnv; @@ -47,6 +50,7 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -81,7 +85,7 @@ public class ProofOfBurnView extends ActivatableView implements private final ProofOfBurnService proofOfBurnService; private final MyProofOfBurnListService myProofOfBurnListService; private final Preferences preferences; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private final BsqWalletService bsqWalletService; private final BsqValidator bsqValidator; @@ -116,7 +120,7 @@ private ProofOfBurnView(BsqFormatter bsqFormatter, ProofOfBurnService proofOfBurnService, MyProofOfBurnListService myProofOfBurnListService, Preferences preferences, - BSFormatter btcFormatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter) { this.bsqFormatter = bsqFormatter; this.bsqWalletService = bsqWalletService; this.bsqValidator = bsqValidator; @@ -273,7 +277,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/economy/dashboard/BsqDashboardView.java b/desktop/src/main/java/bisq/desktop/main/dao/economy/dashboard/BsqDashboardView.java index 0de2e7e6252..bc1ffdf939c 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/economy/dashboard/BsqDashboardView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/economy/dashboard/BsqDashboardView.java @@ -32,8 +32,9 @@ import bisq.core.trade.statistics.TradeStatistics2; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.util.Tuple3; @@ -93,7 +94,6 @@ public class BsqDashboardView extends ActivatableView implements private final DaoStateService daoStateService; private final Preferences preferences; private final BsqFormatter bsqFormatter; - private final BSFormatter btcFormatter; private ChangeListener priceChangeListener; @@ -118,15 +118,13 @@ private BsqDashboardView(DaoFacade daoFacade, PriceFeedService priceFeedService, DaoStateService daoStateService, Preferences preferences, - BsqFormatter bsqFormatter, - BSFormatter btcFormatter) { + BsqFormatter bsqFormatter) { this.daoFacade = daoFacade; this.tradeStatisticsManager = tradeStatisticsManager; this.priceFeedService = priceFeedService; this.daoStateService = daoStateService; this.preferences = preferences; this.bsqFormatter = bsqFormatter; - this.btcFormatter = btcFormatter; } @Override @@ -308,7 +306,7 @@ private void updatePrice() { Optional optionalBsqPrice = priceFeedService.getBsqPrice(); if (optionalBsqPrice.isPresent()) { Price bsqPrice = optionalBsqPrice.get(); - marketPriceLabel.setText(bsqFormatter.formatPrice(bsqPrice) + " BSQ/BTC"); + marketPriceLabel.setText(FormattingUtils.formatPrice(bsqPrice) + " BSQ/BTC"); marketCapTextField.setText(bsqFormatter.formatMarketCap(priceFeedService.getMarketPrice("BSQ"), priceFeedService.getMarketPrice(preferences.getPreferredTradeCurrency().getCode()), diff --git a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java index 6cb4b51519f..a8054c4b68f 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/SupplyView.java @@ -31,7 +31,7 @@ import bisq.core.dao.state.model.governance.IssuanceType; import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple3; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java index 203fa4d1929..3df143e9aee 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/ProposalDisplay.java @@ -58,7 +58,7 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.InputValidator; import bisq.asset.Asset; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/dashboard/GovernanceDashboardView.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/dashboard/GovernanceDashboardView.java index 8a691ff4a6e..d6926cb24d5 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/dashboard/GovernanceDashboardView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/dashboard/GovernanceDashboardView.java @@ -30,7 +30,6 @@ import bisq.core.dao.state.model.blockchain.Block; import bisq.core.dao.state.model.governance.DaoPhase; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; import javax.inject.Inject; @@ -48,7 +47,6 @@ public class GovernanceDashboardView extends ActivatableView imp private final DaoFacade daoFacade; private final PeriodService periodService; private final PhasesView phasesView; - private final BSFormatter formatter; private int gridRow = 0; private TextField currentPhaseTextField, currentBlockHeightTextField, proposalTextField, blindVoteTextField, voteRevealTextField, voteResultTextField; @@ -59,11 +57,10 @@ public class GovernanceDashboardView extends ActivatableView imp /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public GovernanceDashboardView(DaoFacade daoFacade, PeriodService periodService, PhasesView phasesView, BSFormatter formatter) { + public GovernanceDashboardView(DaoFacade daoFacade, PeriodService periodService, PhasesView phasesView) { this.daoFacade = daoFacade; this.periodService = periodService; this.phasesView = phasesView; - this.formatter = formatter; } @Override @@ -125,9 +122,9 @@ private void applyData(int height) { phase = periodService.getPhaseForHeight(height + 1); } currentPhaseTextField.setText(Res.get("dao.phase." + phase.name())); - proposalTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade, formatter)); - blindVoteTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.BLIND_VOTE, daoFacade, formatter)); - voteRevealTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.VOTE_REVEAL, daoFacade, formatter)); - voteResultTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.RESULT, daoFacade, formatter)); + proposalTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade)); + blindVoteTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.BLIND_VOTE, daoFacade)); + voteRevealTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.VOTE_REVEAL, daoFacade)); + voteResultTextField.setText(DaoUtil.getPhaseDuration(height, DaoPhase.Phase.RESULT, daoFacade)); } } 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..570e9984133 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 @@ -50,8 +50,11 @@ import bisq.core.dao.state.model.governance.Proposal; import bisq.core.dao.state.model.governance.Role; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.asset.Asset; @@ -66,6 +69,7 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; @@ -107,7 +111,7 @@ public class MakeProposalView extends ActivatableView implements private final P2PService p2PService; private final PhasesView phasesView; private final ChangeParamValidator changeParamValidator; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private final Navigation navigation; private final BsqWalletService bsqWalletService; @@ -143,7 +147,7 @@ private MakeProposalView(DaoFacade daoFacade, BsqWalletService bsqWalletService, PhasesView phasesView, ChangeParamValidator changeParamValidator, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter, Navigation navigation) { this.daoFacade = daoFacade; @@ -268,7 +272,7 @@ public void onParseBlockCompleteAfterBatchProcessing(Block block) { /////////////////////////////////////////////////////////////////////////////////////////// private void updateTimeUntilNextProposalPhase(int height) { - nextProposalTextField.setText(DaoUtil.getNextPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade, btcFormatter)); + nextProposalTextField.setText(DaoUtil.getNextPhaseDuration(height, DaoPhase.Phase.PROPOSAL, daoFacade)); } private void publishMyProposal(ProposalType type) { @@ -395,13 +399,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/ProposalsListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsListItem.java index 005d42c52b4..9fd0b1bf072 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/proposals/ProposalsListItem.java @@ -25,7 +25,7 @@ import bisq.core.dao.state.model.governance.Proposal; import bisq.core.dao.state.model.governance.Vote; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import de.jensd.fx.fontawesome.AwesomeIcon; 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 e00e1dbbad2..7cde970f75d 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 @@ -30,6 +30,7 @@ import bisq.desktop.main.dao.governance.PhasesView; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.SelectProposalWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; import bisq.desktop.util.validation.BsqValidator; @@ -52,8 +53,11 @@ import bisq.core.dao.state.model.governance.Vote; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -65,6 +69,7 @@ import org.bitcoinj.core.InsufficientMoneyException; import javax.inject.Inject; +import javax.inject.Named; import com.jfoenix.controls.JFXButton; @@ -117,7 +122,7 @@ public class ProposalsView extends ActivatableView implements Bs private final MyBlindVoteListService myBlindVoteListService; private final Preferences preferences; private final BsqFormatter bsqFormatter; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final SelectProposalWindow selectProposalWindow; private final ObservableList listItems = FXCollections.observableArrayList(); @@ -168,7 +173,7 @@ private ProposalsView(DaoFacade daoFacade, MyBlindVoteListService myBlindVoteListService, Preferences preferences, BsqFormatter bsqFormatter, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, SelectProposalWindow selectProposalWindow) { this.daoFacade = daoFacade; this.bsqWalletService = bsqWalletService; @@ -462,7 +467,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); @@ -718,7 +723,7 @@ public TableCell call( public void updateItem(final ProposalsListItem item, boolean empty) { super.updateItem(item, empty); if (item != null) - setText(bsqFormatter.formatDateTime(item.getProposal().getCreationDateAsDate())); + setText(DisplayUtils.formatDateTime(item.getProposal().getCreationDateAsDate())); else setText(""); } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/CycleListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/CycleListItem.java index 7ad3508121f..773df3a0766 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/CycleListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/CycleListItem.java @@ -20,7 +20,8 @@ import bisq.core.dao.governance.proposal.IssuanceProposal; import bisq.core.dao.state.model.governance.EvaluatedProposal; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.FormattingUtils; import org.bitcoinj.core.Coin; @@ -45,7 +46,7 @@ public String getCycle() { public String getCycleDateTime(boolean useLocaleAndLocalTimezone) { long cycleStartTime = resultsOfCycle.getCycleStartTime(); - return cycleStartTime > 0 ? bsqFormatter.formatDateTime(new Date(cycleStartTime), useLocaleAndLocalTimezone) : Res.get("shared.na"); + return cycleStartTime > 0 ? FormattingUtils.formatDateTime(new Date(cycleStartTime), useLocaleAndLocalTimezone) : Res.get("shared.na"); } public int getCycleIndex() { diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/ProposalListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/ProposalListItem.java index 6c91dc49182..d90af7def03 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/ProposalListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/ProposalListItem.java @@ -32,7 +32,7 @@ import bisq.core.dao.state.model.governance.Vote; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import org.bitcoinj.core.Coin; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteListItem.java index 823e44d2bfc..8fc531824c4 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteListItem.java @@ -21,7 +21,7 @@ import bisq.core.dao.state.model.governance.Ballot; import bisq.core.dao.state.model.governance.DecryptedBallotsWithMerits; import bisq.core.dao.state.model.governance.Proposal; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple2; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteResultView.java b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteResultView.java index 4b524f671d6..a1533d1c548 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteResultView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/governance/result/VoteResultView.java @@ -26,6 +26,7 @@ import bisq.desktop.main.dao.governance.PhasesView; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.ProposalResultsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.FormBuilder; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; @@ -57,7 +58,7 @@ import bisq.core.dao.state.model.governance.RoleProposal; import bisq.core.dao.state.model.governance.Vote; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.UserThread; import bisq.common.util.Utilities; @@ -637,7 +638,7 @@ public TableCell call( public void updateItem(final ProposalListItem item, boolean empty) { super.updateItem(item, empty); if (item != null) - setText(bsqFormatter.formatDateTime(item.getProposal().getCreationDateAsDate())); + setText(DisplayUtils.formatDateTime(item.getProposal().getCreationDateAsDate())); else setText(""); } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/news/NewsView.java b/desktop/src/main/java/bisq/desktop/main/dao/news/NewsView.java index 9029119ce36..38a562e0291 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/news/NewsView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/news/NewsView.java @@ -4,13 +4,13 @@ import bisq.desktop.common.view.FxmlView; import bisq.desktop.components.BsqAddressTextField; import bisq.desktop.components.TitledGroupBg; +import bisq.desktop.util.BsqAddressHelper; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; import bisq.common.util.Tuple3; @@ -37,15 +37,15 @@ public class NewsView extends ActivatableView { private final Preferences preferences; private final BsqWalletService bsqWalletService; - private final BsqFormatter bsqFormatter; + private final BsqAddressHelper bsqAddressHelper; private BsqAddressTextField addressTextField; @Inject private NewsView(Preferences preferences, BsqWalletService bsqWalletService, - BsqFormatter bsqFormatter) { + BsqAddressHelper bsqFormatter) { this.preferences = preferences; this.bsqWalletService = bsqWalletService; - this.bsqFormatter = bsqFormatter; + this.bsqAddressHelper = bsqFormatter; } @Override @@ -156,7 +156,7 @@ private AnchorPane createBisqDAOContent() { @Override protected void activate() { - addressTextField.setAddress(bsqFormatter.getBsqAddressStringFromAddress(bsqWalletService.getUnusedAddress())); + addressTextField.setAddress(bsqAddressHelper.getBsqAddressStringFromAddress(bsqWalletService.getUnusedAddress())); } @Override diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/BsqBalanceUtil.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/BsqBalanceUtil.java index 9e7dc5b36a9..3ab09309525 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/BsqBalanceUtil.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/BsqBalanceUtil.java @@ -27,7 +27,7 @@ import bisq.core.dao.state.DaoStateService; import bisq.core.dao.state.model.blockchain.Block; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple3; diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/receive/BsqReceiveView.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/receive/BsqReceiveView.java index 343ef09e145..1ca227b4184 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/receive/BsqReceiveView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/receive/BsqReceiveView.java @@ -22,11 +22,12 @@ import bisq.desktop.components.BsqAddressTextField; import bisq.desktop.components.TitledGroupBg; import bisq.desktop.main.dao.wallet.BsqBalanceUtil; +import bisq.desktop.util.BsqAddressHelper; import bisq.desktop.util.Layout; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.app.DevEnv; import bisq.common.util.Tuple3; @@ -45,7 +46,7 @@ public class BsqReceiveView extends ActivatableView { private BsqAddressTextField addressTextField; private final BsqWalletService bsqWalletService; - private final BsqFormatter bsqFormatter; + private final BsqAddressHelper bsqAddressHelper; private final BsqBalanceUtil bsqBalanceUtil; private int gridRow = 0; @@ -54,9 +55,9 @@ public class BsqReceiveView extends ActivatableView { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private BsqReceiveView(BsqWalletService bsqWalletService, BsqFormatter bsqFormatter, BsqBalanceUtil bsqBalanceUtil) { + private BsqReceiveView(BsqWalletService bsqWalletService, BsqAddressHelper bsqAddressHelper, BsqBalanceUtil bsqBalanceUtil) { this.bsqWalletService = bsqWalletService; - this.bsqFormatter = bsqFormatter; + this.bsqAddressHelper = bsqAddressHelper; this.bsqBalanceUtil = bsqBalanceUtil; } @@ -82,7 +83,7 @@ protected void activate() { if (DevEnv.isDaoActivated()) bsqBalanceUtil.activate(); - addressTextField.setAddress(bsqFormatter.getBsqAddressStringFromAddress(bsqWalletService.getUnusedAddress())); + addressTextField.setAddress(bsqAddressHelper.getBsqAddressStringFromAddress(bsqWalletService.getUnusedAddress())); } @Override 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..fccdac626f7 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 @@ -27,6 +27,7 @@ import bisq.desktop.main.funds.FundsView; import bisq.desktop.main.funds.deposit.DepositView; import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.util.BsqAddressHelper; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; import bisq.desktop.util.validation.BsqAddressValidator; @@ -44,9 +45,12 @@ import bisq.core.btc.wallet.WalletsManager; import bisq.core.dao.state.model.blockchain.TxType; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.CoinUtil; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -58,6 +62,7 @@ import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.control.Button; import javafx.scene.layout.GridPane; @@ -76,7 +81,8 @@ public class BsqSendView extends ActivatableView implements BsqB private final WalletsSetup walletsSetup; private final P2PService p2PService; private final BsqFormatter bsqFormatter; - private final BSFormatter btcFormatter; + private final BsqAddressHelper bsqAddressHelper; + private final CoinFormatter btcFormatter; private final Navigation navigation; private final BsqBalanceUtil bsqBalanceUtil; private final BsqValidator bsqValidator; @@ -104,11 +110,12 @@ private BsqSendView(BsqWalletService bsqWalletService, WalletsSetup walletsSetup, P2PService p2PService, BsqFormatter bsqFormatter, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, Navigation navigation, BsqBalanceUtil bsqBalanceUtil, BsqValidator bsqValidator, BtcValidator btcValidator, + BsqAddressHelper bsqAddressHelper, BsqAddressValidator bsqAddressValidator, BtcAddressValidator btcAddressValidator) { this.bsqWalletService = bsqWalletService; @@ -117,6 +124,7 @@ private BsqSendView(BsqWalletService bsqWalletService, this.walletsSetup = walletsSetup; this.p2PService = p2PService; this.bsqFormatter = bsqFormatter; + this.bsqAddressHelper = bsqAddressHelper; this.btcFormatter = btcFormatter; this.navigation = navigation; this.bsqBalanceUtil = bsqBalanceUtil; @@ -233,8 +241,8 @@ private void addSendBsqGroup() { sendBsqButton.setOnAction((event) -> { // TODO break up in methods if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) { - String receiversAddressString = bsqFormatter.getAddressFromBsqAddress(receiversAddressInputTextField.getText()).toString(); - Coin receiverAmount = bsqFormatter.parseToCoin(amountInputTextField.getText()); + String receiversAddressString = bsqAddressHelper.getAddressFromBsqAddress(receiversAddressInputTextField.getText()).toString(); + Coin receiverAmount = ParsingUtils.parseToCoin(amountInputTextField.getText(), bsqFormatter); try { Transaction preparedSendTx = bsqWalletService.getPreparedSendBsqTx(receiversAddressString, receiverAmount); Transaction txWithBtcFee = btcWalletService.completePreparedSendBsqTx(preparedSendTx, true); @@ -350,8 +358,8 @@ private void showPublishTxPopup(Coin receiverAmount, TxType txType, Coin miningFee, int txSize, String address, - BSFormatter amountFormatter, // can be BSQ or BTC formatter - BSFormatter feeFormatter, + CoinFormatter amountFormatter, // can be BSQ or BTC formatter + CoinFormatter feeFormatter, ResultHandler resultHandler) { new Popup<>().headLine(Res.get("dao.wallet.send.sendFunds.headline")) .confirmation(Res.get("dao.wallet.send.sendFunds.details", diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxListItem.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxListItem.java index de8c4b35166..c72c8411c37 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxListItem.java @@ -18,6 +18,7 @@ package bisq.desktop.main.dao.wallet.tx; import bisq.desktop.components.TxConfidenceListItem; +import bisq.desktop.util.BsqAddressHelper; import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BtcWalletService; @@ -25,7 +26,6 @@ import bisq.core.dao.DaoFacade; import bisq.core.dao.state.model.blockchain.TxType; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; @@ -44,7 +44,7 @@ @Data class BsqTxListItem extends TxConfidenceListItem { private final DaoFacade daoFacade; - private final BsqFormatter bsqFormatter; + private final BsqAddressHelper addressHelper; private final Date date; private final boolean isBurnedBsqTx; private final boolean withdrawalToBTCWallet; @@ -61,13 +61,13 @@ class BsqTxListItem extends TxConfidenceListItem { BtcWalletService btcWalletService, DaoFacade daoFacade, Date date, - BsqFormatter bsqFormatter) { + BsqAddressHelper bsqAddressHelper) { super(transaction, bsqWalletService); this.daoFacade = daoFacade; this.isBurnedBsqTx = daoFacade.hasTxBurntFee(transaction.getHashAsString()); this.date = date; - this.bsqFormatter = bsqFormatter; + this.addressHelper = bsqAddressHelper; checkNotNull(transaction, "transaction must not be null as we only have list items from transactions " + "which are available in the wallet"); @@ -102,7 +102,7 @@ class BsqTxListItem extends TxConfidenceListItem { WalletService.isOutputScriptConvertibleToAddress(output)) { // We don't support send txs with multiple outputs to multiple receivers, so we can // assume that only one output is not from our own wallets. - sendToAddress = bsqFormatter.getBsqAddressStringFromAddress(WalletService.getAddressFromOutput(output)); + sendToAddress = bsqAddressHelper.getBsqAddressStringFromAddress(WalletService.getAddressFromOutput(output)); break; } } @@ -113,7 +113,7 @@ class BsqTxListItem extends TxConfidenceListItem { if (sendToAddress != null) { for (TransactionOutput output : transaction.getOutputs()) { if (WalletService.isOutputScriptConvertibleToAddress(output)) { - receivedWithAddress = bsqFormatter.getBsqAddressStringFromAddress(WalletService.getAddressFromOutput(output)); + receivedWithAddress = bsqAddressHelper.getBsqAddressStringFromAddress(WalletService.getAddressFromOutput(output)); break; } } diff --git a/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxView.java b/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxView.java index ed34c304ac4..8b3474f8ff4 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxView.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/wallet/tx/BsqTxView.java @@ -24,6 +24,8 @@ import bisq.desktop.components.AutoTooltipTableColumn; import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.main.dao.wallet.BsqBalanceUtil; +import bisq.desktop.util.BsqAddressHelper; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.FormBuilder; import bisq.desktop.util.GUIUtil; @@ -38,7 +40,7 @@ import bisq.core.dao.state.model.governance.IssuanceType; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.Timer; import bisq.common.UserThread; @@ -91,6 +93,7 @@ public class BsqTxView extends ActivatableView implements BsqBal private final DaoFacade daoFacade; private final DaoStateService daoStateService; private final BsqFormatter bsqFormatter; + private final BsqAddressHelper bsqAddressHelper; private final BsqWalletService bsqWalletService; private final BtcWalletService btcWalletService; private final BsqBalanceUtil bsqBalanceUtil; @@ -120,7 +123,7 @@ private BsqTxView(DaoFacade daoFacade, Preferences preferences, BtcWalletService btcWalletService, BsqBalanceUtil bsqBalanceUtil, - BsqFormatter bsqFormatter) { + BsqFormatter bsqFormatter, BsqAddressHelper bsqAddressHelper) { this.daoFacade = daoFacade; this.daoStateService = daoStateService; this.bsqFormatter = bsqFormatter; @@ -128,6 +131,7 @@ private BsqTxView(DaoFacade daoFacade, this.preferences = preferences; this.btcWalletService = btcWalletService; this.bsqBalanceUtil = bsqBalanceUtil; + this.bsqAddressHelper = bsqAddressHelper; } @Override @@ -314,7 +318,7 @@ private void updateList() { daoFacade, // Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime() transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(), - bsqFormatter); + bsqAddressHelper); }) .collect(Collectors.toList()); observableList.setAll(items); @@ -367,7 +371,7 @@ public void updateItem(final BsqTxListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - setText(bsqFormatter.formatDateTime(item.getDate())); + setText(DisplayUtils.formatDateTime(item.getDate())); } else { setText(""); } @@ -630,7 +634,7 @@ public void updateItem(final BsqTxListItem item, boolean empty) { style = "dao-tx-type-issuance-icon"; int issuanceBlockHeight = daoFacade.getIssuanceBlockHeight(txId); long blockTime = daoFacade.getBlockTime(issuanceBlockHeight); - String formattedDate = bsqFormatter.formatDateTime(new Date(blockTime)); + String formattedDate = DisplayUtils.formatDateTime(new Date(blockTime)); toolTipText = Res.get("dao.tx.issuanceFromCompReq.tooltip", formattedDate); } else { awesomeIcon = AwesomeIcon.FILE_TEXT; @@ -644,7 +648,7 @@ public void updateItem(final BsqTxListItem item, boolean empty) { style = "dao-tx-type-issuance-icon"; int issuanceBlockHeight = daoFacade.getIssuanceBlockHeight(txId); long blockTime = daoFacade.getBlockTime(issuanceBlockHeight); - String formattedDate = bsqFormatter.formatDateTime(new Date(blockTime)); + String formattedDate = DisplayUtils.formatDateTime(new Date(blockTime)); toolTipText = Res.get("dao.tx.issuanceFromReimbursement.tooltip", formattedDate); } else { awesomeIcon = AwesomeIcon.FILE_TEXT; diff --git a/desktop/src/main/java/bisq/desktop/main/disputes/arbitrator/ArbitratorDisputeView.java b/desktop/src/main/java/bisq/desktop/main/disputes/arbitrator/ArbitratorDisputeView.java index f21f53fa395..26b7c4c36a6 100644 --- a/desktop/src/main/java/bisq/desktop/main/disputes/arbitrator/ArbitratorDisputeView.java +++ b/desktop/src/main/java/bisq/desktop/main/disputes/arbitrator/ArbitratorDisputeView.java @@ -22,15 +22,16 @@ import bisq.desktop.main.overlays.windows.ContractWindow; import bisq.desktop.main.overlays.windows.DisputeSummaryWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.alert.PrivateNotificationManager; import bisq.core.app.AppOptionKeys; import bisq.core.arbitration.DisputeManager; import bisq.core.trade.TradeManager; -import bisq.core.util.BSFormatter; - -import bisq.network.p2p.P2PService; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.common.crypto.KeyRing; @@ -45,12 +46,11 @@ public class ArbitratorDisputeView extends TraderDisputeView { public ArbitratorDisputeView(DisputeManager disputeManager, KeyRing keyRing, TradeManager tradeManager, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, DisputeSummaryWindow disputeSummaryWindow, PrivateNotificationManager privateNotificationManager, ContractWindow contractWindow, TradeDetailsWindow tradeDetailsWindow, - P2PService p2PService, AccountAgeWitnessService accountAgeWitnessService, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { super(disputeManager, @@ -61,7 +61,6 @@ public ArbitratorDisputeView(DisputeManager disputeManager, privateNotificationManager, contractWindow, tradeDetailsWindow, - p2PService, accountAgeWitnessService, useDevPrivilegeKeys); } @@ -79,7 +78,7 @@ protected void applyFilteredListPredicate(String filterString) { // If in arbitrator view we must only display disputes where we are selected as arbitrator (must not receive others anyway) filteredList.setPredicate(dispute -> { boolean matchesTradeId = dispute.getTradeId().contains(filterString); - boolean matchesDate = formatter.formatDate(dispute.getOpeningDate()).contains(filterString); + boolean matchesDate = DisplayUtils.formatDate(dispute.getOpeningDate()).contains(filterString); boolean isBuyerOnion = dispute.getContract().getBuyerNodeAddress().getFullAddress().contains(filterString); boolean isSellerOnion = dispute.getContract().getSellerNodeAddress().getFullAddress().contains(filterString); boolean matchesBuyersPaymentAccountData = dispute.getContract().getBuyerPaymentAccountPayload().getPaymentDetails().contains(filterString); diff --git a/desktop/src/main/java/bisq/desktop/main/disputes/trader/TraderDisputeView.java b/desktop/src/main/java/bisq/desktop/main/disputes/trader/TraderDisputeView.java index 13783cfd5f4..d042920fa3d 100644 --- a/desktop/src/main/java/bisq/desktop/main/disputes/trader/TraderDisputeView.java +++ b/desktop/src/main/java/bisq/desktop/main/disputes/trader/TraderDisputeView.java @@ -30,6 +30,7 @@ import bisq.desktop.main.overlays.windows.DisputeSummaryWindow; import bisq.desktop.main.overlays.windows.SendPrivateNotificationWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.account.witness.AccountAgeWitnessService; @@ -43,10 +44,10 @@ import bisq.core.trade.Contract; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.P2PService; import bisq.common.app.Version; import bisq.common.crypto.KeyRing; @@ -109,12 +110,11 @@ public class TraderDisputeView extends ActivatableView { private final DisputeManager disputeManager; protected final KeyRing keyRing; private final TradeManager tradeManager; - protected final BSFormatter formatter; + protected final CoinFormatter formatter; private final DisputeSummaryWindow disputeSummaryWindow; private final PrivateNotificationManager privateNotificationManager; private final ContractWindow contractWindow; private final TradeDetailsWindow tradeDetailsWindow; - private final P2PService p2PService; private final AccountAgeWitnessService accountAgeWitnessService; private final boolean useDevPrivilegeKeys; @@ -145,12 +145,11 @@ public class TraderDisputeView extends ActivatableView { public TraderDisputeView(DisputeManager disputeManager, KeyRing keyRing, TradeManager tradeManager, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, DisputeSummaryWindow disputeSummaryWindow, PrivateNotificationManager privateNotificationManager, ContractWindow contractWindow, TradeDetailsWindow tradeDetailsWindow, - P2PService p2PService, AccountAgeWitnessService accountAgeWitnessService, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { this.disputeManager = disputeManager; @@ -161,7 +160,6 @@ public TraderDisputeView(DisputeManager disputeManager, this.privateNotificationManager = privateNotificationManager; this.contractWindow = contractWindow; this.tradeDetailsWindow = tradeDetailsWindow; - this.p2PService = p2PService; this.accountAgeWitnessService = accountAgeWitnessService; this.useDevPrivilegeKeys = useDevPrivilegeKeys; } @@ -224,7 +222,7 @@ public void initialize() { dateColumn.setComparator(Comparator.comparing(Dispute::getOpeningDate)); buyerOnionAddressColumn.setComparator(Comparator.comparing(this::getBuyerOnionAddressColumnLabel)); sellerOnionAddressColumn.setComparator(Comparator.comparing(this::getSellerOnionAddressColumnLabel)); - marketColumn.setComparator((o1, o2) -> formatter.getCurrencyPair(o1.getContract().getOfferPayload().getCurrencyCode()).compareTo(o2.getContract().getOfferPayload().getCurrencyCode())); + marketColumn.setComparator((o1, o2) -> CurrencyUtil.getCurrencyPair(o1.getContract().getOfferPayload().getCurrencyCode()).compareTo(o2.getContract().getOfferPayload().getCurrencyCode())); dateColumn.setSortType(TableColumn.SortType.DESCENDING); tableView.getSortOrder().add(dateColumn); @@ -257,7 +255,7 @@ public void initialize() { .append(dispute0.getTradeId()) .append("\n") .append("## Date: ") - .append(formatter.formatDateTime(dispute0.getOpeningDate())) + .append(DisplayUtils.formatDateTime(dispute0.getOpeningDate())) .append("\n") .append("## Is support ticket: ") .append(dispute0.isSupportTicket()) @@ -582,7 +580,7 @@ public TableCell call(TableColumn column) { public void updateItem(final Dispute item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setText(formatter.formatDateTime(item.getOpeningDate())); + setText(DisplayUtils.formatDateTime(item.getOpeningDate())); else setText(""); } @@ -693,7 +691,7 @@ private String getBuyerOnionAddressColumnLabel(Dispute item) { if (buyerNodeAddress != null) { String nrOfDisputes = disputeManager.getNrOfDisputes(true, contract); long accountAge = accountAgeWitnessService.getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing()); - String age = formatter.formatAccountAge(accountAge); + String age = DisplayUtils.formatAccountAge(accountAge); String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : ""; return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")"; } else @@ -710,7 +708,7 @@ private String getSellerOnionAddressColumnLabel(Dispute item) { if (sellerNodeAddress != null) { String nrOfDisputes = disputeManager.getNrOfDisputes(false, contract); long accountAge = accountAgeWitnessService.getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing()); - String age = formatter.formatAccountAge(accountAge); + String age = DisplayUtils.formatAccountAge(accountAge); String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : ""; return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")"; } else @@ -736,7 +734,7 @@ public TableCell call(TableColumn column) { public void updateItem(final Dispute item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setText(formatter.getCurrencyPair(item.getContract().getOfferPayload().getCurrencyCode())); + setText(CurrencyUtil.getCurrencyPair(item.getContract().getOfferPayload().getCurrencyCode())); else setText(""); } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java index 93b71ad2b99..37e004baa96 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java @@ -25,7 +25,8 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -53,7 +54,7 @@ class DepositListItem { private TxConfidenceListener txConfidenceListener; private int numTxOutputs = 0; - public DepositListItem(AddressEntry addressEntry, BtcWalletService walletService, BSFormatter formatter) { + public DepositListItem(AddressEntry addressEntry, BtcWalletService walletService, CoinFormatter formatter) { this.walletService = walletService; addressString = addressEntry.getAddressString(); 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..69df19c25a8 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 @@ -33,9 +33,10 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.locale.Res; -import bisq.core.provider.fee.FeeService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.ParsingUtils; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -47,6 +48,7 @@ import net.glxn.qrgen.image.ImageType; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -106,7 +108,7 @@ public class DepositView extends ActivatableView { private final BtcWalletService walletService; private final Preferences preferences; - private final BSFormatter formatter; + private final CoinFormatter formatter; private String paymentLabelString; private final ObservableList observableList = FXCollections.observableArrayList(); private final SortedList sortedList = new SortedList<>(observableList); @@ -121,9 +123,8 @@ public class DepositView extends ActivatableView { @Inject private DepositView(BtcWalletService walletService, - FeeService feeService, Preferences preferences, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.walletService = walletService; this.preferences = preferences; this.formatter = formatter; @@ -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/locked/LockedListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java index 1bbd53b836b..4b6d6585652 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java @@ -25,7 +25,8 @@ import bisq.core.btc.wallet.WalletService; import bisq.core.trade.Tradable; import bisq.core.trade.Trade; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -41,13 +42,13 @@ class LockedListItem { private final Trade trade; private final AddressEntry addressEntry; private final BtcWalletService btcWalletService; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final String addressString; @Nullable private final Address address; private Coin balance; - public LockedListItem(Trade trade, AddressEntry addressEntry, BtcWalletService btcWalletService, BSFormatter formatter) { + public LockedListItem(Trade trade, AddressEntry addressEntry, BtcWalletService btcWalletService, CoinFormatter formatter) { this.trade = trade; this.addressEntry = addressEntry; this.btcWalletService = btcWalletService; diff --git a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java index 38275c3ba23..63b20b6b860 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java @@ -23,6 +23,7 @@ import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.btc.listeners.BalanceListener; @@ -35,12 +36,14 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -78,7 +81,7 @@ public class LockedView extends ActivatableView { private final TradeManager tradeManager; private final OpenOfferManager openOfferManager; private final Preferences preferences; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final OfferDetailsWindow offerDetailsWindow; private final TradeDetailsWindow tradeDetailsWindow; private final ObservableList observableList = FXCollections.observableArrayList(); @@ -94,7 +97,7 @@ public class LockedView extends ActivatableView { @Inject private LockedView(BtcWalletService btcWalletService, TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences, - BSFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) { this.btcWalletService = btcWalletService; this.tradeManager = tradeManager; this.openOfferManager = openOfferManager; @@ -228,7 +231,7 @@ public void updateItem(final LockedListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { if (getTradable(item).isPresent()) - setGraphic(new AutoTooltipLabel(formatter.formatDateTime(getTradable(item).get().getDate()))); + setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate()))); else setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable"))); } else { diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java index 34cb41be4d2..27531beef81 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java @@ -24,7 +24,8 @@ import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.OpenOffer; import bisq.core.trade.Tradable; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -40,11 +41,11 @@ class ReservedListItem { private final OpenOffer openOffer; private final AddressEntry addressEntry; private final BtcWalletService btcWalletService; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final String addressString; private Coin balance; - public ReservedListItem(OpenOffer openOffer, AddressEntry addressEntry, BtcWalletService btcWalletService, BSFormatter formatter) { + public ReservedListItem(OpenOffer openOffer, AddressEntry addressEntry, BtcWalletService btcWalletService, CoinFormatter formatter) { this.openOffer = openOffer; this.addressEntry = addressEntry; this.btcWalletService = btcWalletService; diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java index 0146d9c14fd..c213764c9e3 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java @@ -23,6 +23,7 @@ import bisq.desktop.components.HyperlinkWithIcon; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.btc.listeners.BalanceListener; @@ -35,12 +36,14 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -78,7 +81,7 @@ public class ReservedView extends ActivatableView { private final TradeManager tradeManager; private final OpenOfferManager openOfferManager; private final Preferences preferences; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final OfferDetailsWindow offerDetailsWindow; private final TradeDetailsWindow tradeDetailsWindow; private final ObservableList observableList = FXCollections.observableArrayList(); @@ -94,7 +97,7 @@ public class ReservedView extends ActivatableView { @Inject private ReservedView(BtcWalletService btcWalletService, TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences, - BSFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) { this.btcWalletService = btcWalletService; this.tradeManager = tradeManager; this.openOfferManager = openOfferManager; @@ -228,7 +231,7 @@ public void updateItem(final ReservedListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { if (getTradable(item).isPresent()) - setGraphic(new AutoTooltipLabel(formatter.formatDateTime(getTradable(item).get().getDate()))); + setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate()))); else setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable"))); } else { diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java index e95974989d1..33f980d70d7 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java @@ -22,11 +22,13 @@ import bisq.core.dao.DaoFacade; import bisq.core.trade.Tradable; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import org.bitcoinj.core.Transaction; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import java.util.Optional; @@ -38,12 +40,12 @@ public class TransactionListItemFactory { private final BtcWalletService btcWalletService; private final BsqWalletService bsqWalletService; private final DaoFacade daoFacade; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final Preferences preferences; @Inject TransactionListItemFactory(BtcWalletService btcWalletService, BsqWalletService bsqWalletService, - DaoFacade daoFacade, BSFormatter formatter, Preferences preferences) { + DaoFacade daoFacade, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, Preferences preferences) { this.btcWalletService = btcWalletService; this.bsqWalletService = bsqWalletService; this.daoFacade = daoFacade; diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java index afd36b5861d..1c837e5e696 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java @@ -18,6 +18,7 @@ package bisq.desktop.main.funds.transactions; import bisq.desktop.components.indicator.TxConfidenceIndicator; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.btc.listeners.TxConfidenceListener; @@ -31,7 +32,8 @@ import bisq.core.offer.OpenOffer; import bisq.core.trade.Tradable; import bisq.core.trade.Trade; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; @@ -51,7 +53,7 @@ @Slf4j class TransactionsListItem { private final BtcWalletService btcWalletService; - private final BSFormatter formatter; + private final CoinFormatter formatter; private String dateString; private final Date date; private final String txId; @@ -86,7 +88,7 @@ class TransactionsListItem { BsqWalletService bsqWalletService, Optional tradableOptional, DaoFacade daoFacade, - BSFormatter formatter, + CoinFormatter formatter, long ignoreDustThreshold) { this.btcWalletService = btcWalletService; this.formatter = formatter; @@ -239,7 +241,7 @@ else if (details.isEmpty()) } // Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime() date = transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(); - dateString = formatter.formatDateTime(date); + dateString = DisplayUtils.formatDateTime(date); isDustAttackTx = received && valueSentToMe.value < ignoreDustThreshold; if (isDustAttackTx) { diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java index cb03b9b2366..37be5c1beef 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java @@ -35,7 +35,8 @@ import bisq.core.trade.Tradable; import bisq.core.trade.Trade; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import bisq.network.p2p.P2PService; @@ -54,6 +55,7 @@ import com.googlecode.jcsv.writer.CSVEntryConverter; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -110,7 +112,7 @@ public class TransactionsView extends ActivatableView { private final BtcWalletService btcWalletService; private final P2PService p2PService; private final WalletsSetup walletsSetup; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final Preferences preferences; private final TradeDetailsWindow tradeDetailsWindow; private final OfferDetailsWindow offerDetailsWindow; @@ -127,7 +129,7 @@ public class TransactionsView extends ActivatableView { private TransactionsView(BtcWalletService btcWalletService, P2PService p2PService, WalletsSetup walletsSetup, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, Preferences preferences, TradeDetailsWindow tradeDetailsWindow, OfferDetailsWindow offerDetailsWindow, diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java index acba8ef5bac..b9efd1e5eab 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java @@ -23,7 +23,8 @@ import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; @@ -39,7 +40,7 @@ class WithdrawalListItem { private final Label balanceLabel; private final AddressEntry addressEntry; private final BtcWalletService walletService; - private final BSFormatter formatter; + private final CoinFormatter formatter; private Coin balance; private final String addressString; @Setter @@ -47,7 +48,7 @@ class WithdrawalListItem { private boolean isSelected; public WithdrawalListItem(AddressEntry addressEntry, BtcWalletService walletService, - BSFormatter formatter) { + CoinFormatter formatter) { this.addressEntry = addressEntry; this.walletService = walletService; this.formatter = formatter; 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..433bb4dc411 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 @@ -39,8 +39,10 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.CoinUtil; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -56,6 +58,7 @@ import org.bitcoinj.wallet.Wallet; import javax.inject.Inject; +import javax.inject.Named; import com.google.common.util.concurrent.FutureCallback; @@ -126,7 +129,7 @@ public class WithdrawalView extends ActivatableView { private final TradeManager tradeManager; private final P2PService p2PService; private final WalletsSetup walletsSetup; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final Preferences preferences; private final BtcAddressValidator btcAddressValidator; private final WalletPasswordWindow walletPasswordWindow; @@ -156,7 +159,7 @@ private WithdrawalView(BtcWalletService walletService, TradeManager tradeManager, P2PService p2PService, WalletsSetup walletsSetup, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, Preferences preferences, BtcAddressValidator btcAddressValidator, WalletPasswordWindow walletPasswordWindow) { @@ -246,7 +249,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/market/MarketView.java b/desktop/src/main/java/bisq/desktop/main/market/MarketView.java index 7eddb314af3..be5c417dfc8 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/MarketView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/MarketView.java @@ -31,17 +31,21 @@ import bisq.desktop.main.offer.offerbook.OfferBook; import bisq.desktop.main.offer.offerbook.OfferBookListItem; import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.util.DisplayUtils; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.offer.OfferPayload; import bisq.core.trade.statistics.TradeStatistics2; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; import bisq.common.util.Utilities; import javax.inject.Inject; +import javax.inject.Named; import com.google.common.base.Joiner; @@ -70,7 +74,7 @@ public class MarketView extends ActivatableViewAndModel { private final ViewLoader viewLoader; private final P2PService p2PService; private final OfferBook offerBook; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final Navigation navigation; private Navigation.Listener navigationListener; private ChangeListener tabChangeListener; @@ -79,7 +83,7 @@ public class MarketView extends ActivatableViewAndModel { @Inject - public MarketView(CachingViewLoader viewLoader, P2PService p2PService, OfferBook offerBook, BSFormatter formatter, + public MarketView(CachingViewLoader viewLoader, P2PService p2PService, OfferBook offerBook, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, Navigation navigation) { this.viewLoader = viewLoader; this.p2PService = p2PService; @@ -183,11 +187,11 @@ private String getAllTradesWithReferralId() { .map(trade -> { StringBuilder sb = new StringBuilder(); sb.append("Trade ID: ").append(trade.getOfferId()).append("\n") - .append("Date: ").append(formatter.formatDateTime(trade.getTradeDate())).append("\n") - .append("Market: ").append(formatter.getCurrencyPair(trade.getCurrencyCode())).append("\n") - .append("Price: ").append(formatter.formatPrice(trade.getTradePrice())).append("\n") + .append("Date: ").append(DisplayUtils.formatDateTime(trade.getTradeDate())).append("\n") + .append("Market: ").append(CurrencyUtil.getCurrencyPair(trade.getCurrencyCode())).append("\n") + .append("Price: ").append(FormattingUtils.formatPrice(trade.getTradePrice())).append("\n") .append("Amount: ").append(formatter.formatCoin(trade.getTradeAmount())).append("\n") - .append("Volume: ").append(formatter.formatVolume(trade.getTradeVolume())).append("\n") + .append("Volume: ").append(DisplayUtils.formatVolume(trade.getTradeVolume())).append("\n") .append("Payment method: ").append(Res.get(trade.getOfferPaymentMethod())).append("\n") .append("ReferralID: ").append(trade.getExtraDataMap().get(OfferPayload.REFERRAL_ID)); return sb.toString(); @@ -205,9 +209,9 @@ private String getAllOffersWithReferralId() { StringBuilder sb = new StringBuilder(); sb.append("Offer ID: ").append(offer.getId()).append("\n") .append("Type: ").append(offer.getDirection().name()).append("\n") - .append("Market: ").append(formatter.getCurrencyPair(offer.getCurrencyCode())).append("\n") - .append("Price: ").append(formatter.formatPrice(offer.getPrice())).append("\n") - .append("Amount: ").append(formatter.formatAmount(offer)).append(" BTC\n") + .append("Market: ").append(CurrencyUtil.getCurrencyPair(offer.getCurrencyCode())).append("\n") + .append("Price: ").append(FormattingUtils.formatPrice(offer.getPrice())).append("\n") + .append("Amount: ").append(DisplayUtils.formatAmount(offer, formatter)).append(" BTC\n") .append("Payment method: ").append(Res.get(offer.getPaymentMethod().getId())).append("\n") .append("ReferralID: ").append(offer.getOfferPayload().getExtraDataMap().get(OfferPayload.REFERRAL_ID)); return sb.toString(); diff --git a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java index e3b13b2c6d2..ac9334d8c9d 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartView.java @@ -38,7 +38,9 @@ import bisq.core.locale.Res; import bisq.core.offer.Offer; import bisq.core.offer.OfferPayload; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.NodeAddress; @@ -104,7 +106,7 @@ public class OfferBookChartView extends ActivatableViewAndModel buyOfferTableView; private TableView sellOfferTableView; private AreaChart areaChart; @@ -135,7 +137,7 @@ public class OfferBookChartView extends ActivatableViewAndModel topBuyOfferList = FXCollections.observableArrayList(); private final ObservableList topSellOfferList = FXCollections.observableArrayList(); private final ChangeListener currenciesUpdatedListener; - private final BSFormatter formatter; private int selectedTabIndex; public final IntegerProperty maxPlacesForBuyPrice = new SimpleIntegerProperty(); public final IntegerProperty maxPlacesForBuyVolume = new SimpleIntegerProperty(); @@ -95,12 +95,11 @@ class OfferBookChartViewModel extends ActivatableViewModel { @SuppressWarnings("WeakerAccess") @Inject public OfferBookChartViewModel(OfferBook offerBook, Preferences preferences, PriceFeedService priceFeedService, - AccountAgeWitnessService accountAgeWitnessService, Navigation navigation, BSFormatter formatter) { + AccountAgeWitnessService accountAgeWitnessService, Navigation navigation) { this.offerBook = offerBook; this.preferences = preferences; this.priceFeedService = priceFeedService; this.navigation = navigation; - this.formatter = formatter; this.accountAgeWitnessService = accountAgeWitnessService; String code = preferences.getOfferBookChartScreenCurrencyCode(); @@ -254,7 +253,7 @@ public String getPrice(Offer offer) { } private String formatPrice(Offer offer, boolean decimalAligned) { - return formatter.formatPrice(offer.getPrice(), decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyPrice.get() : maxPlacesForSellPrice.get()); + return DisplayUtils.formatPrice(offer.getPrice(), decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyPrice.get() : maxPlacesForSellPrice.get()); } public String getVolume(Offer offer) { @@ -262,7 +261,7 @@ public String getVolume(Offer offer) { } private String formatVolume(Offer offer, boolean decimalAligned) { - return formatter.formatVolume(offer, decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyVolume.get() : maxPlacesForSellVolume.get(), false); + return DisplayUtils.formatVolume(offer, decimalAligned, offer.isBuyOffer() ? maxPlacesForBuyVolume.get() : maxPlacesForSellVolume.get(), false); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java index 167d547d48c..474ead5ebb1 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java @@ -26,11 +26,14 @@ import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.control.Label; import javafx.scene.control.TableCell; @@ -50,7 +53,7 @@ @FxmlView public class SpreadView extends ActivatableViewAndModel { - private final BSFormatter formatter; + private final CoinFormatter formatter; private TableView tableView; private SortedList sortedList; private ListChangeListener itemListChangeListener; @@ -61,7 +64,7 @@ public class SpreadView extends ActivatableViewAndModel offerBookListItems; private final ListChangeListener listChangeListener; final ObservableList spreadItems = FXCollections.observableArrayList(); @@ -73,7 +77,7 @@ class SpreadViewModel extends ActivatableViewModel { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public SpreadViewModel(OfferBook offerBook, PriceFeedService priceFeedService, BSFormatter formatter) { + public SpreadViewModel(OfferBook offerBook, PriceFeedService priceFeedService, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.offerBook = offerBook; this.priceFeedService = priceFeedService; this.formatter = formatter; @@ -185,7 +189,7 @@ private void update(ObservableList offerBookListItems) { .multiply(BigDecimal.valueOf(10000)) .divide(marketPriceAsBigDecimal, RoundingMode.HALF_UP) .doubleValue() / 10000; - percentage = formatter.formatPercentagePrice(percentageValue); + percentage = FormattingUtils.formatPercentagePrice(percentageValue); } } catch (Throwable t) { try { diff --git a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsView.java b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsView.java index 6aa8d19840a..25f3c0d3985 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsView.java @@ -27,6 +27,7 @@ import bisq.desktop.main.market.trades.charts.price.CandleStickChart; import bisq.desktop.main.market.trades.charts.volume.VolumeChart; import bisq.desktop.util.CurrencyListItem; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.locale.CurrencyUtil; @@ -35,7 +36,9 @@ import bisq.core.monetary.Volume; import bisq.core.offer.OfferPayload; import bisq.core.trade.statistics.TradeStatistics2; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.UserThread; import bisq.common.util.MathUtils; @@ -45,6 +48,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import com.jfoenix.controls.JFXTabPane; @@ -98,7 +102,7 @@ @FxmlView public class TradesChartsView extends ActivatableViewAndModel { - private final BSFormatter formatter; + private final CoinFormatter formatter; private TableView tableView; private AutocompleteComboBox currencyComboBox; @@ -138,7 +142,7 @@ public class TradesChartsView extends ActivatableViewAndModel call( public void updateItem(final TradeStatistics2 item, boolean empty) { super.updateItem(item, empty); if (item != null) - setText(formatter.formatDateTime(item.getTradeDate())); + setText(DisplayUtils.formatDateTime(item.getTradeDate())); else setText(""); } @@ -597,7 +601,7 @@ public TableCell call( public void updateItem(final TradeStatistics2 item, boolean empty) { super.updateItem(item, empty); if (item != null) - setText(formatter.getCurrencyPair(item.getCurrencyCode())); + setText(CurrencyUtil.getCurrencyPair(item.getCurrencyCode())); else setText(""); } @@ -621,7 +625,7 @@ public TableCell call( public void updateItem(final TradeStatistics2 item, boolean empty) { super.updateItem(item, empty); if (item != null) - setText(formatter.formatPrice(item.getTradePrice())); + setText(FormattingUtils.formatPrice(item.getTradePrice())); else setText(""); } @@ -671,8 +675,8 @@ public void updateItem(final TradeStatistics2 item, boolean empty) { super.updateItem(item, empty); if (item != null) setText(model.showAllTradeCurrenciesProperty.get() ? - formatter.formatVolumeWithCode(item.getTradeVolume()) : - formatter.formatVolume(item.getTradeVolume())); + DisplayUtils.formatVolumeWithCode(item.getTradeVolume()) : + DisplayUtils.formatVolume(item.getTradeVolume())); else setText(""); } @@ -744,7 +748,7 @@ public void updateItem(final TradeStatistics2 item, boolean empty) { @NotNull private String getDirectionLabel(TradeStatistics2 item) { - return formatter.getDirectionWithCode(OfferPayload.Direction.valueOf(item.getDirection().name()), item.getCurrencyCode()); + return DisplayUtils.getDirectionWithCode(OfferPayload.Direction.valueOf(item.getDirection().name()), item.getCurrencyCode()); } @NotNull diff --git a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java index c9da02597ec..1b96e45b194 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java @@ -25,6 +25,7 @@ import bisq.desktop.main.settings.preferences.PreferencesView; import bisq.desktop.util.CurrencyList; import bisq.desktop.util.CurrencyListItem; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.locale.CryptoCurrency; @@ -36,7 +37,7 @@ import bisq.core.trade.statistics.TradeStatistics2; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.common.util.MathUtils; @@ -98,7 +99,6 @@ public enum TickUnit { final Preferences preferences; private PriceFeedService priceFeedService; private Navigation navigation; - private BSFormatter formatter; private final SetChangeListener setChangeListener; final ObjectProperty selectedTradeCurrencyProperty = new SimpleObjectProperty<>(); @@ -120,12 +120,11 @@ public enum TickUnit { @SuppressWarnings("WeakerAccess") @Inject - public TradesChartsViewModel(TradeStatisticsManager tradeStatisticsManager, Preferences preferences, PriceFeedService priceFeedService, Navigation navigation, BSFormatter formatter) { + public TradesChartsViewModel(TradeStatisticsManager tradeStatisticsManager, Preferences preferences, PriceFeedService priceFeedService, Navigation navigation) { this.tradeStatisticsManager = tradeStatisticsManager; this.preferences = preferences; this.priceFeedService = priceFeedService; this.navigation = navigation; - this.formatter = formatter; setChangeListener = change -> { updateChartData(); @@ -345,12 +344,12 @@ CandleData getCandleData(long tick, Set set) { final Date dateFrom = new Date(getTimeFromTickIndex(tick)); final Date dateTo = new Date(getTimeFromTickIndex(tick + 1)); String dateString = tickUnit.ordinal() > TickUnit.DAY.ordinal() ? - formatter.formatDateTimeSpan(dateFrom, dateTo) : - formatter.formatDate(dateFrom) + " - " + formatter.formatDate(dateTo); + DisplayUtils.formatDateTimeSpan(dateFrom, dateTo) : + DisplayUtils.formatDate(dateFrom) + " - " + DisplayUtils.formatDate(dateTo); return new CandleData(tick, open, close, high, low, averagePrice, medianPrice, accumulatedAmount, accumulatedVolume, numTrades, isBullish, dateString); } - + Long findMedian(Long[] prices) { int middle = prices.length / 2; long median; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java index ab9a0f10f17..b24bd2a91a8 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java @@ -17,6 +17,8 @@ package bisq.desktop.main.offer; +import bisq.desktop.util.DisplayUtils; + import bisq.core.account.witness.AccountAgeRestrictions; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.arbitration.Arbitrator; @@ -46,8 +48,9 @@ import bisq.core.trade.statistics.ReferralIdService; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.CoinUtil; import bisq.network.p2p.P2PService; @@ -61,6 +64,8 @@ import com.google.inject.Inject; +import javax.inject.Named; + import com.google.common.collect.Lists; import javafx.beans.property.BooleanProperty; @@ -105,7 +110,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs private final FeeService feeService; private final TxFeeEstimationService txFeeEstimationService; private final ReferralIdService referralIdService; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private MakerFeeProvider makerFeeProvider; private final String offerId; private final BalanceListener btcBalanceListener; @@ -158,7 +163,7 @@ public MutableOfferDataModel(OpenOfferManager openOfferManager, FeeService feeService, TxFeeEstimationService txFeeEstimationService, ReferralIdService referralIdService, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, MakerFeeProvider makerFeeProvider) { super(btcWalletService); @@ -646,7 +651,7 @@ void calculateAmount() { !price.get().isZero() && allowAmountUpdate) { try { - Coin value = btcFormatter.reduceTo4Decimals(price.get().getAmountByVolume(volume.get())); + Coin value = DisplayUtils.reduceTo4Decimals(price.get().getAmountByVolume(volume.get()), btcFormatter); if (isHalCashAccount()) value = OfferUtil.getAdjustedAmountForHalCash(value, price.get(), getMaxTradeLimit()); else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java index 75770ae7bdd..b78de82dee8 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -57,8 +57,10 @@ import bisq.core.payment.payload.PaymentMethod; import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -71,6 +73,8 @@ import net.glxn.qrgen.QRCode; import net.glxn.qrgen.image.ImageType; +import javax.inject.Named; + import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; import javafx.scene.Node; @@ -128,7 +132,7 @@ public abstract class MutableOfferView extends private final Preferences preferences; private final Transitions transitions; private final OfferDetailsWindow offerDetailsWindow; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private ScrollPane scrollPane; @@ -182,7 +186,7 @@ public abstract class MutableOfferView extends /////////////////////////////////////////////////////////////////////////////////////////// public MutableOfferView(M model, Navigation navigation, Preferences preferences, Transitions transitions, - OfferDetailsWindow offerDetailsWindow, BSFormatter btcFormatter, BsqFormatter bsqFormatter) { + OfferDetailsWindow offerDetailsWindow, CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(model); this.navigation = navigation; @@ -567,11 +571,11 @@ protected void close() { /////////////////////////////////////////////////////////////////////////////////////////// private void addBindings() { - priceCurrencyLabel.textProperty().bind(createStringBinding(() -> btcFormatter.getCounterCurrency(model.tradeCurrencyCode.get()), model.tradeCurrencyCode)); + priceCurrencyLabel.textProperty().bind(createStringBinding(() -> CurrencyUtil.getCounterCurrency(model.tradeCurrencyCode.get()), model.tradeCurrencyCode)); marketBasedPriceLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty()); volumeCurrencyLabel.textProperty().bind(model.tradeCurrencyCode); - priceDescriptionLabel.textProperty().bind(createStringBinding(() -> btcFormatter.getPriceWithCurrencyCode(model.tradeCurrencyCode.get(), "shared.fixedPriceInCurForCur"), model.tradeCurrencyCode)); + priceDescriptionLabel.textProperty().bind(createStringBinding(() -> CurrencyUtil.getPriceWithCurrencyCode(model.tradeCurrencyCode.get(), "shared.fixedPriceInCurForCur"), model.tradeCurrencyCode)); volumeDescriptionLabel.textProperty().bind(createStringBinding(model.volumeDescriptionLabel::get, model.tradeCurrencyCode, model.volumeDescriptionLabel)); amountTextField.textProperty().bindBidirectional(model.amount); minAmountTextField.textProperty().bindBidirectional(model.minAmount); 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 917ded3f4f1..c850c1959a0 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java @@ -25,6 +25,7 @@ import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.settings.SettingsView; import bisq.desktop.main.settings.preferences.PreferencesView; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.validation.AltcoinValidator; import bisq.desktop.util.validation.BsqValidator; @@ -50,8 +51,10 @@ import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.InputValidator; import bisq.network.p2p.P2PService; @@ -66,6 +69,7 @@ import org.bitcoinj.utils.Fiat; import javax.inject.Inject; +import javax.inject.Named; import javafx.beans.property.BooleanProperty; import javafx.beans.property.IntegerProperty; @@ -91,7 +95,7 @@ public abstract class MutableOfferViewModel ext private final PriceFeedService priceFeedService; private final Navigation navigation; private final Preferences preferences; - protected final BSFormatter btcFormatter; + protected final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private final FiatVolumeValidator fiatVolumeValidator; private final FiatPriceValidator fiatPriceValidator; @@ -192,7 +196,7 @@ public MutableOfferViewModel(M dataModel, PriceFeedService priceFeedService, Navigation navigation, Preferences preferences, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(dataModel); @@ -315,7 +319,7 @@ private void createListeners() { if (marketPrice != null && marketPrice.isRecentExternalPriceAvailable()) { double marketPriceAsDouble = marketPrice.getPrice(); try { - double priceAsDouble = btcFormatter.parseNumberStringToDouble(price.get()); + double priceAsDouble = ParsingUtils.parseNumberStringToDouble(price.get()); double relation = priceAsDouble / marketPriceAsDouble; final OfferPayload.Direction compareDirection = CurrencyUtil.isCryptoCurrency(currencyCode) ? OfferPayload.Direction.SELL : @@ -323,7 +327,7 @@ private void createListeners() { double percentage = dataModel.getDirection() == compareDirection ? 1 - relation : relation - 1; percentage = MathUtils.roundDouble(percentage, 4); dataModel.setMarketPriceMargin(percentage); - marketPriceMargin.set(btcFormatter.formatToPercent(percentage)); + marketPriceMargin.set(FormattingUtils.formatToPercent(percentage)); applyMakerFee(); } catch (NumberFormatException t) { marketPriceMargin.set(""); @@ -341,7 +345,7 @@ private void createListeners() { if (inputIsMarketBasedPrice) { try { if (!newValue.isEmpty() && !newValue.equals("-")) { - double percentage = btcFormatter.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")) @@ -364,7 +368,7 @@ private void createListeners() { Altcoin.SMALLEST_UNIT_EXPONENT : Fiat.SMALLEST_UNIT_EXPONENT; // protect from triggering unwanted updates ignorePriceStringListener = true; - price.set(btcFormatter.formatRoundedDoubleWithPrecision(targetPrice, precision)); + price.set(FormattingUtils.formatRoundedDoubleWithPrecision(targetPrice, precision)); ignorePriceStringListener = false; setPriceToModel(); dataModel.setMarketPriceMargin(percentage); @@ -441,7 +445,7 @@ private void createListeners() { priceListener = (ov, oldValue, newValue) -> { ignorePriceStringListener = true; if (newValue != null) - price.set(btcFormatter.formatPrice(newValue)); + price.set(FormattingUtils.formatPrice(newValue)); else price.set(""); @@ -451,7 +455,7 @@ private void createListeners() { volumeListener = (ov, oldValue, newValue) -> { ignoreVolumeStringListener = true; if (newValue != null) - volume.set(btcFormatter.formatVolume(newValue)); + volume.set(DisplayUtils.formatVolume(newValue)); else volume.set(""); @@ -461,7 +465,7 @@ private void createListeners() { securityDepositAsDoubleListener = (ov, oldValue, newValue) -> { if (newValue != null) { - buyerSecurityDeposit.set(btcFormatter.formatToPercent((double) newValue)); + buyerSecurityDeposit.set(FormattingUtils.formatToPercent((double) newValue)); if (dataModel.getAmount().get() != null) buyerSecurityDepositInBTC.set(btcFormatter.formatCoinWithCode(dataModel.getBuyerSecurityDepositAsCoin())); } else { @@ -492,7 +496,7 @@ private void applyMakerFee() { Coin makerFeeInBtc = dataModel.getMakerFeeInBtc(); Optional optionalBtcFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBtc, true, preferences, priceFeedService, bsqFormatter); - String btcFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter); + String btcFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter); if (DevEnv.isDaoActivated()) { tradeFeeInBtcWithFiat.set(btcFeeWithFiatAmount); } else { @@ -502,14 +506,14 @@ private void applyMakerFee() { Coin makerFeeInBsq = dataModel.getMakerFeeInBsq(); Optional optionalBsqFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBsq, false, preferences, priceFeedService, bsqFormatter); - String bsqFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter); + String bsqFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter); if (DevEnv.isDaoActivated()) { tradeFeeInBsqWithFiat.set(bsqFeeWithFiatAmount); } else { // Before DAO is enabled we show fee as fiat and % in second line String feeInFiatAsString; if (optionalBtcFeeInFiat != null && optionalBtcFeeInFiat.isPresent()) { - feeInFiatAsString = btcFormatter.formatVolumeWithCode(optionalBtcFeeInFiat.get()); + feeInFiatAsString = DisplayUtils.formatVolumeWithCode(optionalBtcFeeInFiat.get()); } else { feeInFiatAsString = Res.get("shared.na"); } @@ -520,7 +524,7 @@ private void applyMakerFee() { tradeFeeInBsqWithFiat.set(Res.get("createOffer.tradeFee.fiatAndPercent", feeInFiatAsString, - btcFormatter.formatToPercentWithSymbol(percent))); + FormattingUtils.formatToPercentWithSymbol(percent))); } } tradeFeeCurrencyCode.set(dataModel.isCurrencyForMakerFeeBtc() ? Res.getBaseCurrencyCode() : "BSQ"); @@ -601,7 +605,7 @@ boolean initWithData(OfferPayload.Direction direction, TradeCurrency tradeCurren isBuy ? Res.get("shared.buy") : Res.get("shared.sell")); securityDepositValidator.setPaymentAccount(dataModel.paymentAccount); - buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); + buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); buyerSecurityDepositLabel.set(getSecurityDepositLabel()); applyMakerFee(); @@ -757,7 +761,7 @@ public void onFocusOutMinAmountTextField(boolean oldValue, boolean newValue) { if (dataModel.getMinVolume().get() != null) { InputValidator.ValidationResult minVolumeResult = isVolumeInputValid( - btcFormatter.formatVolume(dataModel.getMinVolume().get())); + DisplayUtils.formatVolume(dataModel.getMinVolume().get())); volumeValidationResult.set(minVolumeResult); @@ -788,7 +792,7 @@ void onFocusOutPriceTextField(boolean oldValue, boolean newValue) { setPriceToModel(); ignorePriceStringListener = true; if (dataModel.getPrice().get() != null) - price.set(btcFormatter.formatPrice(dataModel.getPrice().get())); + price.set(FormattingUtils.formatPrice(dataModel.getPrice().get())); ignorePriceStringListener = false; dataModel.calculateVolume(); dataModel.calculateAmount(); @@ -812,7 +816,7 @@ public void onFocusOutPriceAsPercentageTextField(boolean oldValue, boolean newVa // field wasn't set manually inputIsMarketBasedPrice = true; } - marketPriceMargin.set(btcFormatter.formatRoundedDoubleWithPrecision(dataModel.getMarketPriceMargin() * 100, 2)); + marketPriceMargin.set(FormattingUtils.formatRoundedDoubleWithPrecision(dataModel.getMarketPriceMargin() * 100, 2)); // We want to trigger a recalculation of the volume UserThread.execute(() -> { @@ -836,7 +840,7 @@ void onFocusOutVolumeTextField(boolean oldValue, boolean newValue) { else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) volume = OfferUtil.getRoundedFiatVolume(volume); - this.volume.set(btcFormatter.formatVolume(volume)); + this.volume.set(DisplayUtils.formatVolume(volume)); } ignoreVolumeStringListener = false; @@ -865,20 +869,20 @@ void onFocusOutBuyerSecurityDepositTextField(boolean oldValue, boolean newValue) if (result.isValid) { double defaultSecurityDeposit = Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount()); String key = "buyerSecurityDepositIsLowerAsDefault"; - double depositAsDouble = btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get()); + double depositAsDouble = ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get()); if (preferences.showAgain(key) && depositAsDouble < defaultSecurityDeposit) { String postfix = dataModel.isBuyOffer() ? Res.get("createOffer.tooLowSecDeposit.makerIsBuyer") : Res.get("createOffer.tooLowSecDeposit.makerIsSeller"); new Popup<>() .warning(Res.get("createOffer.tooLowSecDeposit.warning", - btcFormatter.formatToPercentWithSymbol(defaultSecurityDeposit)) + "\n\n" + postfix) + FormattingUtils.formatToPercentWithSymbol(defaultSecurityDeposit)) + "\n\n" + postfix) .width(800) .actionButtonText(Res.get("createOffer.resetToDefault")) .onAction(() -> { dataModel.setBuyerSecurityDeposit(defaultSecurityDeposit); ignoreSecurityDepositStringListener = true; - buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); + buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); ignoreSecurityDepositStringListener = false; }) .closeButtonText(Res.get("createOffer.useLowerValue")) @@ -895,7 +899,7 @@ void onFocusOutBuyerSecurityDepositTextField(boolean oldValue, boolean newValue) private void applyBuyerSecurityDepositOnFocusOut() { setBuyerSecurityDepositToModel(); ignoreSecurityDepositStringListener = true; - buyerSecurityDeposit.set(btcFormatter.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); + buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get())); ignoreSecurityDepositStringListener = false; } @@ -905,7 +909,7 @@ private void applyBuyerSecurityDepositOnFocusOut() { public boolean isPriceInRange() { if (marketPriceMargin.get() != null && !marketPriceMargin.get().isEmpty()) { - if (Math.abs(btcFormatter.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) { + if (Math.abs(ParsingUtils.parsePercentStringToDouble(marketPriceMargin.get())) > preferences.getMaxPriceDistanceInPercent()) { displayPriceOutOfRangePopup(); return false; } else { @@ -919,7 +923,7 @@ public boolean isPriceInRange() { private void displayPriceOutOfRangePopup() { Popup popup = new Popup<>(); popup.warning(Res.get("createOffer.priceOutSideOfDeviation", - btcFormatter.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent()))) + FormattingUtils.formatToPercentWithSymbol(preferences.getMaxPriceDistanceInPercent()))) .actionButtonText(Res.get("createOffer.changePrice")) .onAction(popup::hide) .closeButtonTextWithGoTo("navigation.settings.preferences") @@ -927,7 +931,7 @@ private void displayPriceOutOfRangePopup() { .show(); } - BSFormatter getBtcFormatter() { + CoinFormatter getBtcFormatter() { return btcFormatter; } @@ -954,7 +958,7 @@ public String getSecurityDepositPopOverLabel(String depositInBTC) { public String getSecurityDepositInfo() { return btcFormatter.formatCoinWithCode(dataModel.getSecurityDeposit()) + - GUIUtil.getPercentageOfTradeAmount(dataModel.getSecurityDeposit(), dataModel.getAmount().get(), btcFormatter); + GUIUtil.getPercentageOfTradeAmount(dataModel.getSecurityDeposit(), dataModel.getAmount().get()); } public String getSecurityDepositWithCode() { @@ -966,7 +970,7 @@ public String getTradeFee() { final Coin makerFeeAsCoin = dataModel.getMakerFee(); final String makerFee = getFormatterForMakerFee().formatCoinWithCode(makerFeeAsCoin); if (dataModel.isCurrencyForMakerFeeBtc()) - return makerFee + GUIUtil.getPercentageOfTradeAmount(makerFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + return makerFee + GUIUtil.getPercentageOfTradeAmount(makerFeeAsCoin, dataModel.getAmount().get()); else return makerFee + " (" + Res.get("shared.tradingFeeInBsqInfo", btcFormatter.formatCoinWithCode(makerFeeAsCoin)) + ")"; } @@ -974,7 +978,7 @@ public String getTradeFee() { public String getMakerFeePercentage() { final Coin makerFeeAsCoin = dataModel.getMakerFee(); if (dataModel.isCurrencyForMakerFeeBtc()) - return GUIUtil.getPercentage(makerFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + return GUIUtil.getPercentage(makerFeeAsCoin, dataModel.getAmount().get()); else return Res.get("dao.paidWithBsq"); } @@ -1002,13 +1006,13 @@ public String getFundsStructure() { public String getTxFee() { Coin txFeeAsCoin = dataModel.getTxFee(); return btcFormatter.formatCoinWithCode(txFeeAsCoin) + - GUIUtil.getPercentageOfTradeAmount(txFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + GUIUtil.getPercentageOfTradeAmount(txFeeAsCoin, dataModel.getAmount().get()); } public String getTxFeePercentage() { Coin txFeeAsCoin = dataModel.getTxFee(); - return GUIUtil.getPercentage(txFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + return GUIUtil.getPercentage(txFeeAsCoin, dataModel.getAmount().get()); } public PaymentAccount getPaymentAccount() { @@ -1062,7 +1066,7 @@ public M getDataModel() { private void setAmountToModel() { if (amount.get() != null && !amount.get().isEmpty()) { - Coin amount = btcFormatter.parseToCoinWith4Decimals(this.amount.get()); + Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter); long maxTradeLimit = dataModel.getMaxTradeLimit(); Price price = dataModel.getPrice().get(); @@ -1086,7 +1090,7 @@ else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get())) private void setMinAmountToModel() { if (minAmount.get() != null && !minAmount.get().isEmpty()) { - Coin minAmount = btcFormatter.parseToCoinWith4Decimals(this.minAmount.get()); + Coin minAmount = DisplayUtils.parseToCoinWith4Decimals(this.minAmount.get(), btcFormatter); Price price = dataModel.getPrice().get(); long maxTradeLimit = dataModel.getMaxTradeLimit(); @@ -1129,7 +1133,7 @@ private void setVolumeToModel() { private void setBuyerSecurityDepositToModel() { if (buyerSecurityDeposit.get() != null && !buyerSecurityDeposit.get().isEmpty()) { - dataModel.setBuyerSecurityDeposit(btcFormatter.parsePercentStringToDouble(buyerSecurityDeposit.get())); + dataModel.setBuyerSecurityDeposit(ParsingUtils.parsePercentStringToDouble(buyerSecurityDeposit.get())); } else { dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent(getPaymentAccount())); } @@ -1188,7 +1192,7 @@ private void updateButtonDisableState() { dataModel.getPrice().get() != null && dataModel.getPrice().get().getValue() != 0 && isVolumeInputValid(volume.get()).isValid && - isVolumeInputValid(btcFormatter.formatVolume(dataModel.getMinVolume().get())).isValid && + isVolumeInputValid(DisplayUtils.formatVolume(dataModel.getMinVolume().get())).isValid && dataModel.isMinAmountLessOrEqualAmount(); isNextButtonDisabled.set(!inputDataValid); @@ -1204,7 +1208,7 @@ private void stopTimeoutTimer() { } } - private BSFormatter getFormatterForMakerFee() { + private CoinFormatter getFormatterForMakerFee() { return dataModel.isCurrencyForMakerFeeBtc() ? btcFormatter : bsqFormatter; } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferDataModel.java index bed681ae255..990e1161cb4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferDataModel.java @@ -35,7 +35,9 @@ import bisq.core.trade.statistics.ReferralIdService; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.P2PService; @@ -43,6 +45,8 @@ import com.google.inject.Inject; +import javax.inject.Named; + /** * Domain for that UI element. * Note that the create offer domain has a deeper scope in the application domain (TradeManager). @@ -64,7 +68,7 @@ public CreateOfferDataModel(OpenOfferManager openOfferManager, FeeService feeService, TxFeeEstimationService txFeeEstimationService, ReferralIdService referralIdService, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, MakerFeeProvider makerFeeProvider) { super(openOfferManager, btcWalletService, diff --git a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferView.java index f87ae6b6c1e..4a33d239b9a 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferView.java @@ -24,16 +24,20 @@ import bisq.desktop.util.Transitions; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import com.google.inject.Inject; +import javax.inject.Named; + @FxmlView public class CreateOfferView extends MutableOfferView { @Inject - public CreateOfferView(CreateOfferViewModel model, Navigation navigation, Preferences preferences, Transitions transitions, OfferDetailsWindow offerDetailsWindow, BSFormatter btcFormatter, BsqFormatter bsqFormatter) { + public CreateOfferView(CreateOfferViewModel model, Navigation navigation, Preferences preferences, Transitions transitions, OfferDetailsWindow offerDetailsWindow, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(model, navigation, preferences, transitions, offerDetailsWindow, btcFormatter, bsqFormatter); } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java index 65e0d84dcc7..7fbb5e82cd4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java @@ -30,17 +30,21 @@ import bisq.core.btc.setup.WalletsSetup; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.network.p2p.P2PService; import com.google.inject.Inject; +import javax.inject.Named; + class CreateOfferViewModel extends MutableOfferViewModel implements ViewModel { @Inject - public CreateOfferViewModel(CreateOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, FiatPriceValidator fiatPriceValidator, AltcoinValidator altcoinValidator, BtcValidator btcValidator, BsqValidator bsqValidator, SecurityDepositValidator securityDepositValidator, P2PService p2PService, WalletsSetup walletsSetup, PriceFeedService priceFeedService, Navigation navigation, Preferences preferences, BSFormatter btcFormatter, BsqFormatter bsqFormatter) { + public CreateOfferViewModel(CreateOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, FiatPriceValidator fiatPriceValidator, AltcoinValidator altcoinValidator, BtcValidator btcValidator, BsqValidator bsqValidator, SecurityDepositValidator securityDepositValidator, P2PService p2PService, WalletsSetup walletsSetup, PriceFeedService priceFeedService, Navigation navigation, Preferences preferences, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(dataModel, fiatVolumeValidator, fiatPriceValidator, altcoinValidator, btcValidator, bsqValidator, securityDepositValidator, p2PService, walletsSetup, priceFeedService, navigation, preferences, btcFormatter, bsqFormatter); } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index fc93632c935..aa36e51c535 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -37,6 +37,7 @@ import bisq.desktop.main.offer.OfferView; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.FormBuilder; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; @@ -54,7 +55,9 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentMethod; import bisq.core.user.DontShowAgainLookup; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.NodeAddress; @@ -115,7 +118,7 @@ public class OfferBookView extends ActivatableViewAndModel { - String str1 = formatter.getCurrencyPair(o1.getOffer().getCurrencyCode()); - String str2 = formatter.getCurrencyPair(o2.getOffer().getCurrencyCode()); + String str1 = CurrencyUtil.getCurrencyPair(o1.getOffer().getCurrencyCode()); + String str2 = CurrencyUtil.getCurrencyPair(o2.getOffer().getCurrencyCode()); return str1 != null && str2 != null ? str1.compareTo(str2) : 0; }); priceColumn.setComparator((o1, o2) -> { @@ -324,7 +327,7 @@ protected void activate() { tableView.getColumns().add(0, marketColumn); } else { volumeColumn.setTitleWithHelpText(Res.get("offerbook.volume", code), Res.get("shared.amountHelp")); - priceColumn.setTitle(formatter.getPriceWithCurrencyCode(code)); + priceColumn.setTitle(CurrencyUtil.getPriceWithCurrencyCode(code)); priceColumn.getStyleClass().add("first-column"); tableView.getColumns().remove(marketColumn); @@ -573,7 +576,7 @@ private void onShowInfo(Offer offer, final long tradeLimit = model.accountAgeWitnessService.getMyTradeLimit(account.get(), offer.getCurrencyCode()); new Popup<>() .warning(Res.get("offerbook.warning.tradeLimitNotMatching", - formatter.formatAccountAge(model.accountAgeWitnessService.getMyAccountAge(account.get().getPaymentAccountPayload())), + DisplayUtils.formatAccountAge(model.accountAgeWitnessService.getMyAccountAge(account.get().getPaymentAccountPayload())), formatter.formatCoinWithCode(Coin.valueOf(tradeLimit)), formatter.formatCoinWithCode(offer.getMinAmount()))) .show(); @@ -603,7 +606,7 @@ private void onRemoveOpenOffer(Offer offer) { if (model.isBootstrapped()) { String key = "RemoveOfferWarning"; if (DontShowAgainLookup.showAgain(key)) - new Popup<>().warning(Res.get("popup.warning.removeOffer", model.formatter.formatCoinWithCode(offer.getMakerFee()))) + new Popup<>().warning(Res.get("popup.warning.removeOffer", model.btcFormatter.formatCoinWithCode(offer.getMakerFee()))) .actionButtonText(Res.get("shared.removeOffer")) .onAction(() -> doRemoveOffer(offer)) .closeButtonText(Res.get("shared.dontRemoveOffer")) @@ -693,7 +696,7 @@ public void updateItem(final OfferBookListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setText(formatter.getCurrencyPair(item.getOffer().getCurrencyCode())); + setText(CurrencyUtil.getCurrencyPair(item.getOffer().getCurrencyCode())); else setText(""); } @@ -1077,7 +1080,6 @@ public void updateItem(final OfferBookListItem newItem, boolean empty) { offer, model.preferences, model.accountAgeWitnessService, - formatter, useDevPrivilegeKeys); setGraphic(peerInfoIcon); } else { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java index dfc527a600c..09200e54b80 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -22,6 +22,7 @@ import bisq.desktop.main.MainView; import bisq.desktop.main.settings.SettingsView; import bisq.desktop.main.settings.preferences.PreferencesView; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.account.witness.AccountAgeWitnessService; @@ -46,7 +47,9 @@ import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.NodeAddress; import bisq.network.p2p.P2PService; @@ -59,6 +62,8 @@ import com.google.inject.Inject; +import javax.inject.Named; + import com.google.common.base.Joiner; import javafx.scene.control.TableColumn; @@ -100,7 +105,7 @@ class OfferBookViewModel extends ActivatableViewModel { private final FilterManager filterManager; final AccountAgeWitnessService accountAgeWitnessService; private final Navigation navigation; - final BSFormatter formatter; + final CoinFormatter btcFormatter; final ObjectProperty priceSortTypeProperty = new SimpleObjectProperty<>(); @@ -143,7 +148,7 @@ public OfferBookViewModel(User user, FilterManager filterManager, AccountAgeWitnessService accountAgeWitnessService, Navigation navigation, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter) { super(); this.openOfferManager = openOfferManager; @@ -156,7 +161,7 @@ public OfferBookViewModel(User user, this.filterManager = filterManager; this.accountAgeWitnessService = accountAgeWitnessService; this.navigation = navigation; - this.formatter = formatter; + this.btcFormatter = btcFormatter; this.filteredItems = new FilteredList<>(offerBook.getOfferBookListItems()); this.sortedItems = new SortedList<>(filteredItems); @@ -175,9 +180,9 @@ public OfferBookViewModel(User user, final OfferBookListItem item = highestAmountOffer.get(); if (!item.getOffer().isRange() && containsRangeAmount) { maxPlacesForAmount.set(formatAmount(item.getOffer(), false) - .length() * 2 + BSFormatter.RANGE_SEPARATOR.length()); + .length() * 2 + FormattingUtils.RANGE_SEPARATOR.length()); maxPlacesForVolume.set(formatVolume(item.getOffer(), false) - .length() * 2 + BSFormatter.RANGE_SEPARATOR.length()); + .length() * 2 + FormattingUtils.RANGE_SEPARATOR.length()); } else { maxPlacesForAmount.set(formatAmount(item.getOffer(), false).length()); maxPlacesForVolume.set(formatVolume(item.getOffer(), false).length()); @@ -341,7 +346,7 @@ String getAmount(OfferBookListItem item) { } private String formatAmount(Offer offer, boolean decimalAligned) { - return formatter.formatAmount(offer, GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get()); + return DisplayUtils.formatAmount(offer, GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get(), btcFormatter ); } @@ -359,22 +364,22 @@ String getPrice(OfferBookListItem item) { } String getAbsolutePriceMargin(Offer offer) { - return formatter.formatPercentagePrice(Math.abs(offer.getMarketPriceMargin())); + return FormattingUtils.formatPercentagePrice(Math.abs(offer.getMarketPriceMargin())); } private String formatPrice(Offer offer, boolean decimalAligned) { - return formatter.formatPrice(offer.getPrice(), decimalAligned, maxPlacesForPrice.get()); + return DisplayUtils.formatPrice(offer.getPrice(), decimalAligned, maxPlacesForPrice.get()); } private String formatMarketPriceMargin(Offer offer, boolean decimalAligned) { String postFix = ""; if (offer.isUseMarketBasedPrice()) { - postFix = " (" + formatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")"; + postFix = " (" + FormattingUtils.formatPercentagePrice(offer.getMarketPriceMargin()) + ")"; } if (decimalAligned) { - postFix = formatter.fillUpPlacesWithEmptyStrings(postFix, maxPlacesForMarketPriceMargin.get()); + postFix = FormattingUtils.fillUpPlacesWithEmptyStrings(postFix, maxPlacesForMarketPriceMargin.get()); } return postFix; @@ -390,7 +395,7 @@ private String formatVolume(Offer offer, boolean decimalAligned) { if (offerVolume != null && minOfferVolume != null) { String postFix = showAllTradeCurrenciesProperty.get() ? " " + offer.getCurrencyCode() : ""; decimalAligned = decimalAligned && !showAllTradeCurrenciesProperty.get(); - return formatter.formatVolume(offer, decimalAligned, maxPlacesForVolume.get()) + postFix; + return DisplayUtils.formatVolume(offer, decimalAligned, maxPlacesForVolume.get()) + postFix; } else { return Res.get("shared.na"); } @@ -471,7 +476,7 @@ private boolean isF2F(Offer offer) { } String getDirectionLabelTooltip(Offer offer) { - return formatter.getDirectionWithCodeDetailed(offer.getMirroredDirection(), offer.getCurrencyCode()); + return getDirectionWithCodeDetailed(offer.getMirroredDirection(), offer.getCurrencyCode()); } Optional getMostMaturePaymentAccountForOffer(Offer offer) { @@ -617,4 +622,11 @@ int getNumTrades(Offer offer) { .collect(Collectors.toSet()) .size(); } + + private String getDirectionWithCodeDetailed(OfferPayload.Direction direction, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) + return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyingBTCWith", currencyCode) : Res.get("shared.sellingBTCFor", currencyCode); + else + return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyingCurrency", currencyCode) : Res.get("shared.sellingCurrency", currencyCode); + } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 3b9f5a78507..bddf64e26e4 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -47,7 +47,7 @@ import bisq.core.trade.handlers.TradeResultHandler; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.CoinUtil; +import bisq.core.util.coin.CoinUtil; import bisq.common.util.Tuple2; diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index f7a4c75c496..76e66f50a60 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -54,8 +54,10 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentMethod; import bisq.core.user.DontShowAgainLookup; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.UserThread; import bisq.common.app.DevEnv; @@ -70,6 +72,7 @@ import net.glxn.qrgen.image.ImageType; import javax.inject.Inject; +import javax.inject.Named; import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon; @@ -118,7 +121,7 @@ @FxmlView public class TakeOfferView extends ActivatableViewAndModel { private final Navigation navigation; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final BsqFormatter bsqFormatter; private final OfferDetailsWindow offerDetailsWindow; private final Transitions transitions; @@ -172,7 +175,7 @@ public class TakeOfferView extends ActivatableViewAndModel 1) { @@ -616,7 +619,7 @@ private void addBindings() { totalToPayTextField.textProperty().bind(model.totalToPay); addressTextField.amountAsCoinProperty().bind(model.dataModel.getMissingCoin()); amountTextField.validationResultProperty().bind(model.amountValidationResult); - priceCurrencyLabel.textProperty().bind(createStringBinding(() -> formatter.getCounterCurrency(model.dataModel.getCurrencyCode()))); + priceCurrencyLabel.textProperty().bind(createStringBinding(() -> CurrencyUtil.getCounterCurrency(model.dataModel.getCurrencyCode()))); priceAsPercentageLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty()); nextButton.disableProperty().bind(model.isNextButtonDisabled); tradeFeeInBtcLabel.textProperty().bind(model.tradeFeeInBtcWithFiat); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java index 55dcbe0b2e5..a1629c41519 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -24,6 +24,7 @@ import bisq.desktop.main.funds.FundsView; import bisq.desktop.main.funds.deposit.DepositView; import bisq.desktop.main.overlays.popups.Popup; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.validation.BtcValidator; @@ -41,8 +42,10 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.Trade; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.core.util.validation.InputValidator; import bisq.network.p2p.P2PService; @@ -55,6 +58,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; @@ -81,7 +85,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel im private final Preferences preferences; private final PriceFeedService priceFeedService; private final Navigation navigation; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private String amountRange; @@ -141,7 +145,7 @@ public TakeOfferViewModel(TakeOfferDataModel dataModel, Preferences preferences, PriceFeedService priceFeedService, Navigation navigation, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(dataModel); this.dataModel = dataModel; @@ -205,8 +209,8 @@ void initWithData(Offer offer) { } amountRange = btcFormatter.formatCoin(offer.getMinAmount()) + " - " + btcFormatter.formatCoin(offer.getAmount()); - price = btcFormatter.formatPrice(dataModel.tradePrice); - marketPriceMargin = btcFormatter.formatToPercent(offer.getMarketPriceMargin()); + price = FormattingUtils.formatPrice(dataModel.tradePrice); + marketPriceMargin = FormattingUtils.formatToPercent(offer.getMarketPriceMargin()); paymentLabel = Res.get("takeOffer.fundsBox.paymentLabel", offer.getShortId()); checkNotNull(dataModel.getAddressEntry(), "dataModel.getAddressEntry() must not be null"); @@ -288,7 +292,7 @@ private void applyTakerFee() { Coin makerFeeInBtc = dataModel.getTakerFeeInBtc(); Optional optionalBtcFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBtc, true, preferences, priceFeedService, bsqFormatter); - String btcFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter); + String btcFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBtc, optionalBtcFeeInFiat, btcFormatter); if (DevEnv.isDaoActivated()) { tradeFeeInBtcWithFiat.set(btcFeeWithFiatAmount); } else { @@ -298,14 +302,14 @@ private void applyTakerFee() { Coin makerFeeInBsq = dataModel.getTakerFeeInBsq(); Optional optionalBsqFeeInFiat = OfferUtil.getFeeInUserFiatCurrency(makerFeeInBsq, false, preferences, priceFeedService, bsqFormatter); - String bsqFeeWithFiatAmount = OfferUtil.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter); + String bsqFeeWithFiatAmount = DisplayUtils.getFeeWithFiatAmount(makerFeeInBsq, optionalBsqFeeInFiat, bsqFormatter); if (DevEnv.isDaoActivated()) { tradeFeeInBsqWithFiat.set(bsqFeeWithFiatAmount); } else { // Before DAO is enabled we show fee as fiat and % in second line String feeInFiatAsString; if (optionalBtcFeeInFiat != null && optionalBtcFeeInFiat.isPresent()) { - feeInFiatAsString = btcFormatter.formatVolumeWithCode(optionalBtcFeeInFiat.get()); + feeInFiatAsString = DisplayUtils.formatVolumeWithCode(optionalBtcFeeInFiat.get()); } else { feeInFiatAsString = Res.get("shared.na"); } @@ -316,7 +320,7 @@ private void applyTakerFee() { tradeFeeInBsqWithFiat.set(Res.get("createOffer.tradeFee.fiatAndPercent", feeInFiatAsString, - btcFormatter.formatToPercentWithSymbol(percent))); + FormattingUtils.formatToPercentWithSymbol(percent))); } } tradeFeeDescription.set(DevEnv.isDaoActivated() ? Res.get("createOffer.tradeFee.descriptionBSQEnabled") : @@ -334,7 +338,7 @@ void onFocusOutAmountTextField(boolean oldValue, boolean newValue, String userIn InputValidator.ValidationResult result = isBtcInputValid(amount.get()); amountValidationResult.set(result); if (result.isValid) { - showWarningInvalidBtcDecimalPlaces.set(!btcFormatter.hasBtcValidDecimals(userInput)); + showWarningInvalidBtcDecimalPlaces.set(!DisplayUtils.hasBtcValidDecimals(userInput, btcFormatter)); // only allow max 4 decimal places for btc values setAmountToModel(); // reformat input @@ -503,7 +507,7 @@ private void updateButtonDisableState() { /////////////////////////////////////////////////////////////////////////////////////////// private void addBindings() { - volume.bind(createStringBinding(() -> btcFormatter.formatVolume(dataModel.volume.get()), dataModel.volume)); + volume.bind(createStringBinding(() -> DisplayUtils.formatVolume(dataModel.volume.get()), dataModel.volume)); if (dataModel.getDirection() == OfferPayload.Direction.SELL) { volumeDescriptionLabel.set(Res.get("createOffer.amountPriceBox.buy.volumeDescription", dataModel.getCurrencyCode())); @@ -626,7 +630,7 @@ private void calculateVolume() { private void setAmountToModel() { if (amount.get() != null && !amount.get().isEmpty()) { - Coin amount = btcFormatter.parseToCoinWith4Decimals(this.amount.get()); + Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter); long maxTradeLimit = dataModel.getMaxTradeLimit(); Price price = dataModel.tradePrice; if (price != null) { @@ -651,7 +655,7 @@ private boolean isAmountEqualMinAmount(Coin amount) { // Getters /////////////////////////////////////////////////////////////////////////////////////////// - BSFormatter getBtcFormatter() { + CoinFormatter getBtcFormatter() { return btcFormatter; } @@ -697,7 +701,7 @@ String getTradeAmount() { public String getSecurityDepositInfo() { return btcFormatter.formatCoinWithCode(dataModel.getSecurityDeposit()) + - GUIUtil.getPercentageOfTradeAmount(dataModel.getSecurityDeposit(), dataModel.getAmount().get(), btcFormatter); + GUIUtil.getPercentageOfTradeAmount(dataModel.getSecurityDeposit(), dataModel.getAmount().get()); } public String getSecurityDepositWithCode() { @@ -709,7 +713,7 @@ public String getTradeFee() { final Coin takerFeeAsCoin = dataModel.getTakerFee(); final String takerFee = getFormatterForTakerFee().formatCoinWithCode(takerFeeAsCoin); if (dataModel.isCurrencyForTakerFeeBtc()) - return takerFee + GUIUtil.getPercentageOfTradeAmount(takerFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + return takerFee + GUIUtil.getPercentageOfTradeAmount(takerFeeAsCoin, dataModel.getAmount().get()); else return takerFee + " (" + Res.get("shared.tradingFeeInBsqInfo", btcFormatter.formatCoinWithCode(takerFeeAsCoin)) + ")"; } @@ -717,7 +721,7 @@ public String getTradeFee() { public String getTakerFeePercentage() { final Coin takerFeeAsCoin = dataModel.getTakerFee(); if (dataModel.isCurrencyForTakerFeeBtc()) - return takerFeeAsCoin != null ? GUIUtil.getPercentage(takerFeeAsCoin, dataModel.getAmount().get(), btcFormatter) : Res.get("shared.na"); + return takerFeeAsCoin != null ? GUIUtil.getPercentage(takerFeeAsCoin, dataModel.getAmount().get()) : Res.get("shared.na"); else return Res.get("dao.paidWithBsq"); } @@ -733,13 +737,13 @@ public String getTotalToPayInfo() { public String getTxFee() { Coin txFeeAsCoin = dataModel.getTotalTxFee(); return btcFormatter.formatCoinWithCode(txFeeAsCoin) + - GUIUtil.getPercentageOfTradeAmount(txFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + GUIUtil.getPercentageOfTradeAmount(txFeeAsCoin, dataModel.getAmount().get()); } public String getTxFeePercentage() { Coin txFeeAsCoin = dataModel.getTotalTxFee(); - return GUIUtil.getPercentage(txFeeAsCoin, dataModel.getAmount().get(), btcFormatter); + return GUIUtil.getPercentage(txFeeAsCoin, dataModel.getAmount().get()); } public PaymentMethod getPaymentMethod() { @@ -786,7 +790,7 @@ public String getSellerSecurityDeposit() { return btcFormatter.formatCoin(dataModel.getSellerSecurityDeposit()); } - private BSFormatter getFormatterForTakerFee() { + private CoinFormatter getFormatterForTakerFee() { return dataModel.isCurrencyForTakerFeeBtc() ? btcFormatter : bsqFormatter; } } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java index 0d04a448960..a99ae93a4b3 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java @@ -21,6 +21,7 @@ import bisq.desktop.main.MainView; import bisq.desktop.main.overlays.Overlay; import bisq.desktop.util.Layout; +import bisq.desktop.util.DisplayUtils; import bisq.core.account.witness.AccountAgeWitnessService; import bisq.core.arbitration.Dispute; @@ -32,7 +33,9 @@ import bisq.core.payment.payload.PaymentAccountPayload; import bisq.core.payment.payload.PaymentMethod; import bisq.core.trade.Contract; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.UserThread; import bisq.common.crypto.PubKeyRing; @@ -40,6 +43,7 @@ import org.bitcoinj.core.Utils; import javax.inject.Inject; +import javax.inject.Named; import com.google.common.base.Joiner; @@ -68,7 +72,7 @@ public class ContractWindow extends Overlay { private final DisputeManager disputeManager; private final AccountAgeWitnessService accountAgeWitnessService; - private final BSFormatter formatter; + private final CoinFormatter formatter; private Dispute dispute; @@ -78,7 +82,7 @@ public class ContractWindow extends Overlay { @Inject public ContractWindow(DisputeManager disputeManager, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.disputeManager = disputeManager; this.accountAgeWitnessService = accountAgeWitnessService; this.formatter = formatter; @@ -133,16 +137,16 @@ private void addContent() { addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.offerId"), offer.getId(), Layout.TWICE_FIRST_ROW_DISTANCE).second.setMouseTransparent(false); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("contractWindow.dates"), - formatter.formatDateTime(offer.getDate()) + " / " + formatter.formatDateTime(dispute.getTradeDate())); + DisplayUtils.formatDateTime(offer.getDate()) + " / " + DisplayUtils.formatDateTime(dispute.getTradeDate())); String currencyCode = offer.getCurrencyCode(); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.offerType"), - formatter.getDirectionBothSides(offer.getDirection(), currencyCode)); + DisplayUtils.getDirectionBothSides(offer.getDirection(), currencyCode)); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"), - formatter.formatPrice(contract.getTradePrice())); + FormattingUtils.formatPrice(contract.getTradePrice())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeAmount"), formatter.formatCoinWithCode(contract.getTradeAmount())); - addConfirmationLabelLabel(gridPane, ++rowIndex, formatter.formatVolumeLabel(currencyCode, ":"), - formatter.formatVolumeWithCode(contract.getTradeVolume())); + addConfirmationLabelLabel(gridPane, ++rowIndex, DisplayUtils.formatVolumeLabel(currencyCode, ":"), + DisplayUtils.formatVolumeWithCode(contract.getTradeVolume())); String securityDeposit = Res.getWithColAndCap("shared.buyer") + " " + formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) + @@ -261,7 +265,7 @@ private void addContent() { private String getAccountAge(PaymentAccountPayload paymentAccountPayload, PubKeyRing pubKeyRing, String currencyCode) { long age = accountAgeWitnessService.getAccountAge(paymentAccountPayload, pubKeyRing); return CurrencyUtil.isFiatCurrency(currencyCode) ? - age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) : + age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) : Res.get("peerInfoIcon.tooltip.unknownAge") : ""; } 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 4cd1d6b55a2..e6693583ec0 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 @@ -24,6 +24,7 @@ import bisq.desktop.main.overlays.Overlay; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.Layout; +import bisq.desktop.util.DisplayUtils; import bisq.core.arbitration.Dispute; import bisq.core.arbitration.DisputeManager; @@ -35,7 +36,10 @@ import bisq.core.locale.Res; import bisq.core.offer.Offer; import bisq.core.trade.Contract; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import bisq.common.UserThread; import bisq.common.util.Tuple2; @@ -45,6 +49,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.Scene; import javafx.scene.control.Button; @@ -79,7 +84,7 @@ public class DisputeSummaryWindow extends Overlay { private static final Logger log = LoggerFactory.getLogger(DisputeSummaryWindow.class); - private final BSFormatter formatter; + private final CoinFormatter formatter; private final DisputeManager disputeManager; private final BtcWalletService walletService; private final TradeWalletService tradeWalletService; @@ -109,7 +114,7 @@ public class DisputeSummaryWindow extends Overlay { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public DisputeSummaryWindow(BSFormatter formatter, DisputeManager disputeManager, BtcWalletService walletService, + public DisputeSummaryWindow(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, DisputeManager disputeManager, BtcWalletService walletService, TradeWalletService tradeWalletService) { this.formatter = formatter; @@ -249,7 +254,7 @@ private void addInfoPane() { addTitledGroupBg(gridPane, ++rowIndex, 17, Res.get("disputeSummaryWindow.title")).getStyleClass().add("last"); addConfirmationLabelLabel(gridPane, rowIndex, Res.get("shared.tradeId"), dispute.getShortTradeId(), Layout.TWICE_FIRST_ROW_DISTANCE); - addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.openDate"), formatter.formatDateTime(dispute.getOpeningDate())); + addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.openDate"), DisplayUtils.formatDateTime(dispute.getOpeningDate())); if (dispute.isDisputeOpenerIsMaker()) { if (dispute.isDisputeOpenerIsBuyer()) role = Res.get("support.buyerOfferer"); @@ -265,9 +270,9 @@ private void addInfoPane() { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeAmount"), formatter.formatCoinWithCode(contract.getTradeAmount())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"), - formatter.formatPrice(contract.getTradePrice())); + FormattingUtils.formatPrice(contract.getTradePrice())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeVolume"), - formatter.formatVolumeWithCode(contract.getTradeVolume())); + DisplayUtils.formatVolumeWithCode(contract.getTradeVolume())); String securityDeposit = Res.getWithColAndCap("shared.buyer") + " " + formatter.formatCoinWithCode(contract.getOfferPayload().getBuyerSecurityDeposit()) + @@ -356,8 +361,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()); @@ -370,8 +375,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()) @@ -566,13 +571,13 @@ private void addButtons(Contract contract) { disputeResult.setLoserPublisher(isLoserPublisherCheckBox.isSelected()); disputeResult.setCloseDate(new Date()); String text = Res.get("disputeSummaryWindow.close.msg", - formatter.formatDateTime(disputeResult.getCloseDate()), + DisplayUtils.formatDateTime(disputeResult.getCloseDate()), role, - formatter.booleanToYesNo(disputeResult.tamperProofEvidenceProperty().get()), + DisplayUtils.booleanToYesNo(disputeResult.tamperProofEvidenceProperty().get()), role, - formatter.booleanToYesNo(disputeResult.idVerificationProperty().get()), + DisplayUtils.booleanToYesNo(disputeResult.idVerificationProperty().get()), role, - formatter.booleanToYesNo(disputeResult.screenCastProperty().get()), + DisplayUtils.booleanToYesNo(disputeResult.screenCastProperty().get()), formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()), formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()), disputeResult.summaryNotesProperty().get()); diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/EmptyWalletWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/EmptyWalletWindow.java index c6d0af5bbb7..48d2f96fe81 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/EmptyWalletWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/EmptyWalletWindow.java @@ -31,8 +31,10 @@ import bisq.core.btc.wallet.WalletService; import bisq.core.locale.Res; import bisq.core.offer.OpenOfferManager; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.network.p2p.P2PService; @@ -43,6 +45,7 @@ import org.bitcoinj.core.InsufficientMoneyException; import javax.inject.Inject; +import javax.inject.Named; import javafx.scene.Scene; import javafx.scene.control.Button; @@ -71,7 +74,7 @@ public class EmptyWalletWindow extends Overlay { private final WalletsSetup walletsSetup; private final BtcWalletService btcWalletService; private final BsqWalletService bsqWalletService; - private final BSFormatter btcFormatter; + private final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; private final OpenOfferManager openOfferManager; @@ -92,7 +95,7 @@ public EmptyWalletWindow(WalletPasswordWindow walletPasswordWindow, WalletsSetup walletsSetup, BtcWalletService btcWalletService, BsqWalletService bsqWalletService, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { this.walletPasswordWindow = walletPasswordWindow; this.openOfferManager = openOfferManager; @@ -252,7 +255,7 @@ private WalletService getWalletService() { return isBtc ? btcWalletService : bsqWalletService; } - private BSFormatter getFormatter() { + private CoinFormatter getFormatter() { return isBtc ? btcFormatter : bsqFormatter; } } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java index 6111bd47de3..5c954dbe8be 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java @@ -23,9 +23,11 @@ import bisq.desktop.main.overlays.Overlay; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.util.Layout; +import bisq.desktop.util.DisplayUtils; import bisq.core.locale.BankUtil; import bisq.core.locale.CountryUtil; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.monetary.Price; import bisq.core.offer.Offer; @@ -33,7 +35,11 @@ import bisq.core.payment.PaymentAccount; import bisq.core.payment.payload.PaymentMethod; import bisq.core.user.User; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; + +import bisq.network.p2p.NodeAddress; import bisq.common.crypto.KeyRing; import bisq.common.util.Tuple2; @@ -42,6 +48,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import com.google.common.base.Joiner; @@ -58,6 +65,7 @@ import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,7 +75,7 @@ public class OfferDetailsWindow extends Overlay { protected static final Logger log = LoggerFactory.getLogger(OfferDetailsWindow.class); - private final BSFormatter formatter; + private final CoinFormatter formatter; private final User user; private final KeyRing keyRing; private Offer offer; @@ -83,7 +91,7 @@ public class OfferDetailsWindow extends Overlay { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public OfferDetailsWindow(BSFormatter formatter, User user, KeyRing keyRing, + public OfferDetailsWindow(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, User user, KeyRing keyRing, Navigation navigation) { this.formatter = formatter; this.user = user; @@ -170,49 +178,49 @@ private void addContent() { double firstRowDistance = Layout.TWICE_FIRST_ROW_DISTANCE; if (takeOfferHandlerOptional.isPresent()) { addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel, - formatter.getDirectionForTakeOffer(direction, currencyCode), firstRowDistance); + getDirectionForTakeOffer(direction, currencyCode), firstRowDistance); fiatDirectionInfo = direction == OfferPayload.Direction.BUY ? toReceive : toSpend; btcDirectionInfo = direction == OfferPayload.Direction.SELL ? toReceive : toSpend; } else if (placeOfferHandlerOptional.isPresent()) { addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel, - formatter.getOfferDirectionForCreateOffer(direction, currencyCode), firstRowDistance); + getOfferDirectionForCreateOffer(direction, currencyCode), firstRowDistance); fiatDirectionInfo = direction == OfferPayload.Direction.SELL ? toReceive : toSpend; btcDirectionInfo = direction == OfferPayload.Direction.BUY ? toReceive : toSpend; } else { addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel, - formatter.getDirectionBothSides(direction, currencyCode), firstRowDistance); + DisplayUtils.getDirectionBothSides(direction, currencyCode), firstRowDistance); } String btcAmount = Res.get("shared.btcAmount"); if (takeOfferHandlerOptional.isPresent()) { addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo, formatter.formatCoinWithCode(tradeAmount)); - addConfirmationLabelLabel(gridPane, ++rowIndex, formatter.formatVolumeLabel(currencyCode) + fiatDirectionInfo, - formatter.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount))); + addConfirmationLabelLabel(gridPane, ++rowIndex, DisplayUtils.formatVolumeLabel(currencyCode) + fiatDirectionInfo, + DisplayUtils.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount))); } else { addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo, formatter.formatCoinWithCode(offer.getAmount())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.minBtcAmount"), formatter.formatCoinWithCode(offer.getMinAmount())); - String volume = formatter.formatVolumeWithCode(offer.getVolume()); + String volume = DisplayUtils.formatVolumeWithCode(offer.getVolume()); String minVolume = ""; if (offer.getVolume() != null && offer.getMinVolume() != null && !offer.getVolume().equals(offer.getMinVolume())) - minVolume = " " + Res.get("offerDetailsWindow.min", formatter.formatVolumeWithCode(offer.getMinVolume())); + minVolume = " " + Res.get("offerDetailsWindow.min", DisplayUtils.formatVolumeWithCode(offer.getMinVolume())); addConfirmationLabelLabel(gridPane, ++rowIndex, - formatter.formatVolumeLabel(currencyCode) + fiatDirectionInfo, volume + minVolume); + DisplayUtils.formatVolumeLabel(currencyCode) + fiatDirectionInfo, volume + minVolume); } String priceLabel = Res.get("shared.price"); if (takeOfferHandlerOptional.isPresent()) { - addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(tradePrice)); + addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, FormattingUtils.formatPrice(tradePrice)); } else { Price price = offer.getPrice(); if (offer.isUseMarketBasedPrice()) { - addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(price) + + addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, FormattingUtils.formatPrice(price) + " " + Res.get("offerDetailsWindow.distance", - formatter.formatPercentagePrice(offer.getMarketPriceMargin()))); + FormattingUtils.formatPercentagePrice(offer.getMarketPriceMargin()))); } else { - addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, formatter.formatPrice(price)); + addConfirmationLabelLabel(gridPane, ++rowIndex, priceLabel, FormattingUtils.formatPrice(price)); } } final PaymentMethod paymentMethod = offer.getPaymentMethod(); @@ -307,7 +315,7 @@ else if (BankUtil.isBankNameRequired(countryCode)) addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("offerDetailsWindow.makersOnion"), offer.getMakerNodeAddress().getFullAddress()); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.creationDate"), - formatter.formatDateTime(offer.getDate())); + DisplayUtils.formatDateTime(offer.getDate())); String value = Res.getWithColAndCap("shared.buyer") + " " + formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) + @@ -322,7 +330,7 @@ else if (BankUtil.isBankNameRequired(countryCode)) CountryUtil.getNameAndCode(countryCode)); addConfirmationLabelTextFieldWithCopyIcon(gridPane, ++rowIndex, Res.get("offerDetailsWindow.acceptedArbitrators"), - formatter.arbitratorAddressesToString(offer.getArbitratorNodeAddresses())); + arbitratorAddressesToString(offer.getArbitratorNodeAddresses())); if (offer.getOfferFeePaymentTxId() != null) addLabelTxIdTextField(gridPane, ++rowIndex, Res.get("shared.makerFeeTxId"), offer.getOfferFeePaymentTxId()); @@ -408,4 +416,35 @@ private void addConfirmAndCancelButtons(boolean isPlaceOffer) { } }); } + + private String getDirectionForTakeOffer(OfferPayload.Direction direction, String currencyCode) { + String baseCurrencyCode = Res.getBaseCurrencyCode(); + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + return direction == OfferPayload.Direction.BUY ? + Res.get("formatter.youAre", Res.get("shared.selling"), baseCurrencyCode, Res.get("shared.buying"), currencyCode) : + Res.get("formatter.youAre", Res.get("shared.buying"), baseCurrencyCode, Res.get("shared.selling"), currencyCode); + } else { + + return direction == OfferPayload.Direction.SELL ? + Res.get("formatter.youAre", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), baseCurrencyCode) : + Res.get("formatter.youAre", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), baseCurrencyCode); + } + } + + private String getOfferDirectionForCreateOffer(OfferPayload.Direction direction, String currencyCode) { + String baseCurrencyCode = Res.getBaseCurrencyCode(); + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + return direction == OfferPayload.Direction.BUY ? + Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.buy"), baseCurrencyCode) : + Res.get("formatter.youAreCreatingAnOffer.fiat", Res.get("shared.sell"), baseCurrencyCode); + } else { + return direction == OfferPayload.Direction.SELL ? + Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.buy"), currencyCode, Res.get("shared.selling"), baseCurrencyCode) : + Res.get("formatter.youAreCreatingAnOffer.altcoin", Res.get("shared.sell"), currencyCode, Res.get("shared.buying"), baseCurrencyCode); + } + } + + private String arbitratorAddressesToString(List nodeAddresses) { + return nodeAddresses.stream().map(NodeAddress::getFullAddress).collect(Collectors.joining(", ")); + } } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ProposalResultsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ProposalResultsWindow.java index 5229240439b..8bd6559308e 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ProposalResultsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ProposalResultsWindow.java @@ -25,6 +25,7 @@ import bisq.desktop.main.dao.governance.ProposalDisplay; import bisq.desktop.main.dao.governance.result.VoteListItem; import bisq.desktop.main.overlays.TabbedOverlay; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.desktop.util.Layout; @@ -34,7 +35,7 @@ import bisq.core.dao.state.model.governance.Proposal; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple2; @@ -240,7 +241,7 @@ public void updateItem(final VoteListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - setText(bsqFormatter.formatDateTime(item.getBlindVoteDate())); + setText(DisplayUtils.formatDateTime(item.getBlindVoteDate())); } else { setText(""); } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/SelectProposalWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/SelectProposalWindow.java index 3327d26875e..82017d8303c 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/SelectProposalWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/SelectProposalWindow.java @@ -15,7 +15,7 @@ import bisq.core.dao.state.model.governance.Vote; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple2; import bisq.common.util.Tuple3; diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index 6c3d94152da..c23ae379c2a 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -21,6 +21,7 @@ import bisq.desktop.components.TextFieldWithCopyIcon; import bisq.desktop.main.MainView; import bisq.desktop.main.overlays.Overlay; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.Layout; import bisq.core.account.witness.AccountAgeWitnessService; @@ -32,13 +33,16 @@ import bisq.core.trade.Contract; import bisq.core.trade.Trade; import bisq.core.trade.TradeManager; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.UserThread; import org.bitcoinj.core.Utils; import javax.inject.Inject; +import javax.inject.Named; import javafx.stage.Modality; import javafx.stage.Stage; @@ -66,7 +70,7 @@ public class TradeDetailsWindow extends Overlay { protected static final Logger log = LoggerFactory.getLogger(TradeDetailsWindow.class); - private final BSFormatter formatter; + private final CoinFormatter formatter; private final DisputeManager disputeManager; private final TradeManager tradeManager; private final AccountAgeWitnessService accountAgeWitnessService; @@ -82,7 +86,7 @@ public class TradeDetailsWindow extends Overlay { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - public TradeDetailsWindow(BSFormatter formatter, DisputeManager disputeManager, TradeManager tradeManager, + public TradeDetailsWindow(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, DisputeManager disputeManager, TradeManager tradeManager, AccountAgeWitnessService accountAgeWitnessService) { this.formatter = formatter; this.disputeManager = disputeManager; @@ -134,12 +138,12 @@ private void addContent() { String offerType = Res.get("shared.offerType"); if (tradeManager.isBuyer(offer)) { addConfirmationLabelLabel(gridPane, rowIndex, offerType, - formatter.getDirectionForBuyer(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE); + getDirectionForBuyer(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE); fiatDirectionInfo = toSpend; btcDirectionInfo = toReceive; } else { addConfirmationLabelLabel(gridPane, rowIndex, offerType, - formatter.getDirectionForSeller(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE); + getDirectionForSeller(myOffer, offer.getCurrencyCode()), Layout.TWICE_FIRST_ROW_DISTANCE); fiatDirectionInfo = toReceive; btcDirectionInfo = toSpend; } @@ -147,10 +151,10 @@ private void addContent() { addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.btcAmount") + btcDirectionInfo, formatter.formatCoinWithCode(trade.getTradeAmount())); addConfirmationLabelLabel(gridPane, ++rowIndex, - formatter.formatVolumeLabel(offer.getCurrencyCode()) + fiatDirectionInfo, - formatter.formatVolumeWithCode(trade.getTradeVolume())); + DisplayUtils.formatVolumeLabel(offer.getCurrencyCode()) + fiatDirectionInfo, + DisplayUtils.formatVolumeWithCode(trade.getTradeVolume())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"), - formatter.formatPrice(trade.getTradePrice())); + FormattingUtils.formatPrice(trade.getTradePrice())); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.paymentMethod"), Res.get(offer.getPaymentMethod().getId())); @@ -198,7 +202,7 @@ private void addContent() { addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.tradeId"), trade.getId(), Layout.TWICE_FIRST_ROW_AND_GROUP_DISTANCE); addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("tradeDetailsWindow.tradeDate"), - formatter.formatDateTime(trade.getDate())); + DisplayUtils.formatDateTime(trade.getDate())); String securityDeposit = Res.getWithColAndCap("shared.buyer") + " " + formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) + @@ -226,7 +230,7 @@ private void addContent() { String paymentDetails = buyerPaymentAccountPayload.getPaymentDetails(); long age = accountAgeWitnessService.getAccountAge(buyerPaymentAccountPayload, contract.getBuyerPubKeyRing()); buyersAccountAge = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ? - age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) : + age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) : Res.get("peerInfoIcon.tooltip.unknownAge") : ""; @@ -240,7 +244,7 @@ private void addContent() { String paymentDetails = sellerPaymentAccountPayload.getPaymentDetails(); long age = accountAgeWitnessService.getAccountAge(sellerPaymentAccountPayload, contract.getSellerPubKeyRing()); sellersAccountAge = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode()) ? - age > -1 ? Res.get("peerInfoIcon.tooltip.age", formatter.formatAccountAge(age)) : + age > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(age)) : Res.get("peerInfoIcon.tooltip.unknownAge") : ""; String postFix = sellersAccountAge.isEmpty() ? "" : " / " + sellersAccountAge; @@ -346,4 +350,30 @@ private void addContent() { hide(); }); } + + private String getDirectionForBuyer(boolean isMyOffer, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + String code = Res.getBaseCurrencyCode(); + return isMyOffer ? + Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code) : + Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), code, Res.get("shared.selling"), code); + } else { + return isMyOffer ? + Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode) : + Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), currencyCode, Res.get("shared.buying"), currencyCode); + } + } + + private String getDirectionForSeller(boolean isMyOffer, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + String code = Res.getBaseCurrencyCode(); + return isMyOffer ? + Res.get("formatter.youAreAsMaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code) : + Res.get("formatter.youAreAsTaker", Res.get("shared.selling"), code, Res.get("shared.buying"), code); + } else { + return isMyOffer ? + Res.get("formatter.youAreAsMaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode) : + Res.get("formatter.youAreAsTaker", Res.get("shared.buying"), currencyCode, Res.get("shared.selling"), currencyCode); + } + } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java index ebc12ed3893..b5253097b92 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java @@ -26,6 +26,7 @@ import bisq.desktop.components.PeerInfoIcon; import bisq.desktop.main.overlays.windows.OfferDetailsWindow; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.alert.PrivateNotificationManager; @@ -39,7 +40,9 @@ import bisq.core.trade.Tradable; import bisq.core.trade.Trade; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.network.p2p.NodeAddress; @@ -100,7 +103,6 @@ public class ClosedTradesView extends ActivatableViewAndModel sortedList; @@ -113,14 +115,12 @@ public ClosedTradesView(ClosedTradesViewModel model, Preferences preferences, TradeDetailsWindow tradeDetailsWindow, PrivateNotificationManager privateNotificationManager, - BSFormatter formatter, @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) { super(model); this.offerDetailsWindow = offerDetailsWindow; this.preferences = preferences; this.tradeDetailsWindow = tradeDetailsWindow; this.privateNotificationManager = privateNotificationManager; - this.formatter = formatter; this.useDevPrivilegeKeys = useDevPrivilegeKeys; } @@ -317,7 +317,7 @@ private void applyFilteredListPredicate(String filterString) { Offer offer = item.getTradable().getOffer(); boolean matchesId = offer.getId().contains(filterString); - boolean matchesOfferDate = formatter.formatDate(offer.getDate()).contains(filterString); + boolean matchesOfferDate = DisplayUtils.formatDate(offer.getDate()).contains(filterString); boolean isMakerOnion = offer.getMakerNodeAddress().getFullAddress().contains(filterString); if (item.getTradable() instanceof Trade) { @@ -327,7 +327,7 @@ private void applyFilteredListPredicate(String filterString) { boolean matchesSellersPaymentAccountData = false; Trade trade = (Trade) item.getTradable(); - boolean matchesTradeDate = formatter.formatDate(trade.getTakeOfferDate()).contains(filterString); + boolean matchesTradeDate = DisplayUtils.formatDate(trade.getTakeOfferDate()).contains(filterString); Contract contract = trade.getContract(); if (contract != null) { isBuyerOnion = contract.getBuyerNodeAddress().getFullAddress().contains(filterString); @@ -467,7 +467,6 @@ public void updateItem(final ClosedTradableListItem newItem, boolean empty) { trade, preferences, model.accountAgeWitnessService, - formatter, useDevPrivilegeKeys); setPadding(new Insets(1, 15, 0, 0)); setGraphic(peerInfoIcon); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesViewModel.java index cabac69b222..e291e38a49a 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesViewModel.java @@ -19,28 +19,34 @@ import bisq.desktop.common.model.ActivatableWithDataModel; import bisq.desktop.common.model.ViewModel; +import bisq.desktop.util.DisplayUtils; import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.offer.OpenOffer; import bisq.core.trade.Tradable; import bisq.core.trade.Trade; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import com.google.inject.Inject; +import javax.inject.Named; + import javafx.collections.ObservableList; import java.util.stream.Collectors; class ClosedTradesViewModel extends ActivatableWithDataModel implements ViewModel { - private final BSFormatter formatter; + private final CoinFormatter formatter; final AccountAgeWitnessService accountAgeWitnessService; @Inject public ClosedTradesViewModel(ClosedTradesDataModel dataModel, AccountAgeWitnessService accountAgeWitnessService, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { super(dataModel); this.accountAgeWitnessService = accountAgeWitnessService; this.formatter = formatter; @@ -68,14 +74,14 @@ String getPrice(ClosedTradableListItem item) { return ""; Tradable tradable = item.getTradable(); if (tradable instanceof Trade) - return formatter.formatPrice(((Trade) tradable).getTradePrice()); + return FormattingUtils.formatPrice(((Trade) tradable).getTradePrice()); else - return formatter.formatPrice(tradable.getOffer().getPrice()); + return FormattingUtils.formatPrice(tradable.getOffer().getPrice()); } String getVolume(ClosedTradableListItem item) { if (item != null && item.getTradable() instanceof Trade) - return formatter.formatVolumeWithCode(((Trade) item.getTradable()).getTradeVolume()); + return DisplayUtils.formatVolumeWithCode(((Trade) item.getTradable()).getTradeVolume()); else if (item != null && item.getTradable() instanceof OpenOffer) return "-"; else @@ -123,18 +129,18 @@ String getSellerSecurityDeposit(ClosedTradableListItem item) { } String getDirectionLabel(ClosedTradableListItem item) { - return (item != null) ? formatter.getDirectionWithCode(dataModel.getDirection(item.getTradable().getOffer()), item.getTradable().getOffer().getCurrencyCode()) : ""; + return (item != null) ? DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getTradable().getOffer()), item.getTradable().getOffer().getCurrencyCode()) : ""; } String getDate(ClosedTradableListItem item) { - return formatter.formatDateTime(item.getTradable().getDate()); + return DisplayUtils.formatDateTime(item.getTradable().getDate()); } String getMarketLabel(ClosedTradableListItem item) { if ((item == null)) return ""; - return formatter.getCurrencyPair(item.getTradable().getOffer().getCurrencyCode()); + return CurrencyUtil.getCurrencyPair(item.getTradable().getOffer().getCurrencyCode()); } String getState(ClosedTradableListItem item) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java index a575e5bbddd..ef89ef4f3bb 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java @@ -40,8 +40,10 @@ import bisq.core.trade.statistics.ReferralIdService; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.CoinUtil; import bisq.network.p2p.P2PService; @@ -51,6 +53,8 @@ import com.google.inject.Inject; +import javax.inject.Named; + import java.util.Optional; class EditOfferDataModel extends MutableOfferDataModel { @@ -73,7 +77,7 @@ class EditOfferDataModel extends MutableOfferDataModel { FeeService feeService, TxFeeEstimationService txFeeEstimationService, ReferralIdService referralIdService, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, CorePersistenceProtoResolver corePersistenceProtoResolver, MakerFeeProvider makerFeeProvider) { super(openOfferManager, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java index 8d253569c8c..14bb0a0320d 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferView.java @@ -30,13 +30,16 @@ import bisq.core.locale.Res; import bisq.core.offer.OpenOffer; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.common.util.Tuple4; import com.google.inject.Inject; +import javax.inject.Named; + import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.image.ImageView; @@ -61,7 +64,7 @@ public class EditOfferView extends MutableOfferView { /////////////////////////////////////////////////////////////////////////////////////////// @Inject - private EditOfferView(EditOfferViewModel model, Navigation navigation, Preferences preferences, Transitions transitions, OfferDetailsWindow offerDetailsWindow, BSFormatter btcFormatter, BsqFormatter bsqFormatter) { + private EditOfferView(EditOfferViewModel model, Navigation navigation, Preferences preferences, Transitions transitions, OfferDetailsWindow offerDetailsWindow, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(model, navigation, preferences, transitions, offerDetailsWindow, btcFormatter, bsqFormatter); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java index d3896f2782a..cf27299cfde 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java @@ -30,8 +30,10 @@ import bisq.core.offer.OpenOffer; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; @@ -40,10 +42,16 @@ import com.google.inject.Inject; +import javax.inject.Named; + + + +import com.subgraph.orchid.misc.Immutable; + class EditOfferViewModel extends MutableOfferViewModel { @Inject - public EditOfferViewModel(EditOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, FiatPriceValidator fiatPriceValidator, AltcoinValidator altcoinValidator, BtcValidator btcValidator, BsqValidator bsqValidator, SecurityDepositValidator securityDepositValidator, P2PService p2PService, WalletsSetup walletsSetup, PriceFeedService priceFeedService, Navigation navigation, Preferences preferences, BSFormatter btcFormatter, BsqFormatter bsqFormatter) { + public EditOfferViewModel(EditOfferDataModel dataModel, FiatVolumeValidator fiatVolumeValidator, FiatPriceValidator fiatPriceValidator, AltcoinValidator altcoinValidator, BtcValidator btcValidator, BsqValidator bsqValidator, SecurityDepositValidator securityDepositValidator, P2PService p2PService, WalletsSetup walletsSetup, PriceFeedService priceFeedService, Navigation navigation, Preferences preferences, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter) { super(dataModel, fiatVolumeValidator, fiatPriceValidator, altcoinValidator, btcValidator, bsqValidator, securityDepositValidator, p2PService, walletsSetup, priceFeedService, navigation, preferences, btcFormatter, bsqFormatter); syncMinAmountWithAmount = false; } @@ -73,12 +81,12 @@ public void onCancelEditOffer(ErrorMessageHandler errorMessageHandler) { public void onInvalidateMarketPriceMargin() { marketPriceMargin.set("0.00%"); - marketPriceMargin.set(btcFormatter.formatToPercent(dataModel.getMarketPriceMargin())); + marketPriceMargin.set(FormattingUtils.formatToPercent(dataModel.getMarketPriceMargin())); } public void onInvalidatePrice() { - price.set(btcFormatter.formatPrice(null)); - price.set(btcFormatter.formatPrice(dataModel.getPrice().get())); + price.set(FormattingUtils.formatPrice(null)); + price.set(FormattingUtils.formatPrice(dataModel.getPrice().get())); } public boolean isSecurityDepositValid() { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java index ea270cb9961..dee51162d19 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java @@ -19,20 +19,26 @@ import bisq.desktop.common.model.ActivatableWithDataModel; import bisq.desktop.common.model.ViewModel; +import bisq.desktop.util.DisplayUtils; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import com.google.inject.Inject; +import javax.inject.Named; + import javafx.collections.ObservableList; class FailedTradesViewModel extends ActivatableWithDataModel implements ViewModel { - private final BSFormatter formatter; + private final CoinFormatter formatter; @Inject - public FailedTradesViewModel(FailedTradesDataModel dataModel, BSFormatter formatter) { + public FailedTradesViewModel(FailedTradesDataModel dataModel, @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { super(dataModel); this.formatter = formatter; @@ -54,29 +60,29 @@ String getAmount(FailedTradesListItem item) { } String getPrice(FailedTradesListItem item) { - return (item != null) ? formatter.formatPrice(item.getTrade().getTradePrice()) : ""; + return (item != null) ? FormattingUtils.formatPrice(item.getTrade().getTradePrice()) : ""; } String getVolume(FailedTradesListItem item) { if (item != null && item.getTrade() != null) - return formatter.formatVolumeWithCode(item.getTrade().getTradeVolume()); + return DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume()); else return ""; } String getDirectionLabel(FailedTradesListItem item) { - return (item != null) ? formatter.getDirectionWithCode(dataModel.getDirection(item.getTrade().getOffer()), item.getTrade().getOffer().getCurrencyCode()) : ""; + return (item != null) ? DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getTrade().getOffer()), item.getTrade().getOffer().getCurrencyCode()) : ""; } String getMarketLabel(FailedTradesListItem item) { if ((item == null)) return ""; - return formatter.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode()); + return CurrencyUtil.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode()); } String getDate(FailedTradesListItem item) { - return formatter.formatDateTime(item.getTrade().getDate()); + return DisplayUtils.formatDateTime(item.getTrade().getDate()); } String getState(FailedTradesListItem item) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java index 06959d78f48..9d02bc0f9c5 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java @@ -19,12 +19,16 @@ import bisq.desktop.common.model.ActivatableWithDataModel; import bisq.desktop.common.model.ViewModel; +import bisq.desktop.util.DisplayUtils; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.monetary.Price; import bisq.core.offer.Offer; import bisq.core.offer.OpenOffer; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; @@ -33,17 +37,19 @@ import com.google.inject.Inject; +import javax.inject.Named; + import javafx.collections.ObservableList; class OpenOffersViewModel extends ActivatableWithDataModel implements ViewModel { private final P2PService p2PService; - final BSFormatter formatter; + final CoinFormatter formatter; @Inject public OpenOffersViewModel(OpenOffersDataModel dataModel, P2PService p2PService, - BSFormatter formatter) { + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { super(dataModel); this.p2PService = p2PService; @@ -71,7 +77,7 @@ String getTradeId(OpenOfferListItem item) { } String getAmount(OpenOfferListItem item) { - return (item != null) ? formatter.formatAmount(item.getOffer()) : ""; + return (item != null) ? DisplayUtils.formatAmount(item.getOffer(), formatter) : ""; } String getPrice(OpenOfferListItem item) { @@ -83,33 +89,33 @@ String getPrice(OpenOfferListItem item) { if (price != null) { String postFix = ""; if (offer.isUseMarketBasedPrice()) - postFix = " (" + formatter.formatPercentagePrice(offer.getMarketPriceMargin()) + ")"; - return formatter.formatPrice(price) + postFix; + postFix = " (" + FormattingUtils.formatPercentagePrice(offer.getMarketPriceMargin()) + ")"; + return FormattingUtils.formatPrice(price) + postFix; } else { return Res.get("shared.na"); } } String getVolume(OpenOfferListItem item) { - return (item != null) ? formatter.formatVolume(item.getOffer(), false, 0) + " " + item.getOffer().getCurrencyCode() : ""; + return (item != null) ? DisplayUtils.formatVolume(item.getOffer(), false, 0) + " " + item.getOffer().getCurrencyCode() : ""; } String getDirectionLabel(OpenOfferListItem item) { if ((item == null)) return ""; - return formatter.getDirectionWithCode(dataModel.getDirection(item.getOffer()), item.getOffer().getCurrencyCode()); + return DisplayUtils.getDirectionWithCode(dataModel.getDirection(item.getOffer()), item.getOffer().getCurrencyCode()); } String getMarketLabel(OpenOfferListItem item) { if ((item == null)) return ""; - return formatter.getCurrencyPair(item.getOffer().getCurrencyCode()); + return CurrencyUtil.getCurrencyPair(item.getOffer().getCurrencyCode()); } String getDate(OpenOfferListItem item) { - return formatter.formatDateTime(item.getOffer().getDate()); + return DisplayUtils.formatDateTime(item.getOffer().getDate()); } boolean isDeactivated(OpenOfferListItem item) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index bbe3ec78813..6c956b99389 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -26,6 +26,7 @@ import bisq.desktop.main.MainView; import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.overlays.windows.TradeDetailsWindow; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.FormBuilder; import bisq.desktop.util.CssTheme; @@ -36,7 +37,9 @@ import bisq.core.trade.Trade; import bisq.core.trade.TradeChatSession; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.NodeAddress; @@ -96,7 +99,7 @@ public class PendingTradesView extends ActivatableViewAndModel { private final TradeDetailsWindow tradeDetailsWindow; - private final BSFormatter formatter; + private final CoinFormatter formatter; private final PrivateNotificationManager privateNotificationManager; private final boolean useDevPrivilegeKeys; private final Preferences preferences; @@ -133,7 +136,7 @@ public class PendingTradesView extends ActivatableViewAndModel call( public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - setGraphic(new AutoTooltipLabel(formatter.formatDateTime(item.getTrade().getDate()))); + setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(item.getTrade().getDate()))); } else { setGraphic(null); } @@ -536,7 +539,7 @@ public TableCell call( public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setGraphic(new AutoTooltipLabel(formatter.formatPrice(item.getPrice()))); + setGraphic(new AutoTooltipLabel(FormattingUtils.formatPrice(item.getPrice()))); else setGraphic(null); } @@ -557,7 +560,7 @@ public TableCell call( public void updateItem(final PendingTradesListItem item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) - setGraphic(new AutoTooltipLabel(formatter.formatVolumeWithCode(item.getTrade().getTradeVolume()))); + setGraphic(new AutoTooltipLabel(DisplayUtils.formatVolumeWithCode(item.getTrade().getTradeVolume()))); else setGraphic(null); } @@ -652,7 +655,6 @@ public void updateItem(final PendingTradesListItem newItem, boolean empty) { trade, preferences, model.accountAgeWitnessService, - formatter, useDevPrivilegeKeys); setPadding(new Insets(1, 0, 0, 0)); setGraphic(peerInfoIcon); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java index 2236da49631..0cc16dc1def 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -19,9 +19,11 @@ import bisq.desktop.common.model.ActivatableWithDataModel; import bisq.desktop.common.model.ViewModel; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.GUIUtil; import bisq.core.account.witness.AccountAgeWitnessService; +import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; import bisq.core.network.MessageState; import bisq.core.offer.Offer; @@ -29,8 +31,10 @@ import bisq.core.trade.Trade; import bisq.core.trade.closed.ClosedTradableManager; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.BtcAddressValidator; import bisq.network.p2p.P2PService; @@ -42,6 +46,8 @@ import com.google.inject.Inject; +import javax.inject.Named; + import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; @@ -83,7 +89,7 @@ enum SellerState implements State { STEP4 } - public final BSFormatter btcFormatter; + public final CoinFormatter btcFormatter; private final BsqFormatter bsqFormatter; public final BtcAddressValidator btcAddressValidator; final AccountAgeWitnessService accountAgeWitnessService; @@ -107,7 +113,7 @@ enum SellerState implements State { @Inject public PendingTradesViewModel(PendingTradesDataModel dataModel, - BSFormatter btcFormatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter btcFormatter, BsqFormatter bsqFormatter, BtcAddressValidator btcAddressValidator, P2PService p2PService, @@ -198,7 +204,7 @@ String getMarketLabel(PendingTradesListItem item) { if ((item == null)) return ""; - return btcFormatter.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode()); + return CurrencyUtil.getCurrencyPair(item.getTrade().getOffer().getCurrencyCode()); } private long getMaxTradePeriod() { @@ -220,7 +226,7 @@ private long getRemainingTradeDuration() { } public String getRemainingTradeDurationAsWords() { - return btcFormatter.formatDurationAsWords(Math.max(0, getRemainingTradeDuration())); + return FormattingUtils.formatDurationAsWords(Math.max(0, getRemainingTradeDuration())); } public double getRemainingTradeDurationAsPercentage() { @@ -233,7 +239,7 @@ public double getRemainingTradeDurationAsPercentage() { } public String getDateForOpenDispute() { - return btcFormatter.formatDateTime(new Date(new Date().getTime() + getRemainingTradeDuration())); + return DisplayUtils.formatDateTime(new Date(new Date().getTime() + getRemainingTradeDuration())); } public boolean showWarning() { @@ -251,7 +257,7 @@ String getMyRole(PendingTradesListItem item) { Contract contract = trade.getContract(); if (contract != null) { Offer offer = trade.getOffer(); - return btcFormatter.getRole(contract.isBuyerMakerAndSellerTaker(), dataModel.isMaker(offer), offer.getCurrencyCode()); + return getRole(contract.isBuyerMakerAndSellerTaker(), dataModel.isMaker(offer), offer.getCurrencyCode()); } else { return ""; } @@ -278,13 +284,13 @@ public String getTradeVolume() { } public String getFiatVolume() { - return dataModel.getTrade() != null ? btcFormatter.formatVolumeWithCode(dataModel.getTrade().getTradeVolume()) : ""; + return dataModel.getTrade() != null ? DisplayUtils.formatVolumeWithCode(dataModel.getTrade().getTradeVolume()) : ""; } public String getTxFee() { if (trade != null && trade.getTradeAmount() != null) { Coin txFee = dataModel.getTxFee(); - String percentage = GUIUtil.getPercentageOfTradeAmount(txFee, trade.getTradeAmount(), btcFormatter); + String percentage = GUIUtil.getPercentageOfTradeAmount(txFee, trade.getTradeAmount()); return btcFormatter.formatCoinWithCode(txFee) + percentage; } else { return ""; @@ -296,7 +302,7 @@ public String getTradeFee() { if (dataModel.isMaker() && dataModel.getOffer().isCurrencyForMakerFeeBtc() || !dataModel.isMaker() && dataModel.getTrade().isCurrencyForTakerFeeBtc()) { Coin tradeFeeInBTC = dataModel.getTradeFeeInBTC(); - String percentage = GUIUtil.getPercentageOfTradeAmount(tradeFeeInBTC, trade.getTradeAmount(), btcFormatter); + String percentage = GUIUtil.getPercentageOfTradeAmount(tradeFeeInBTC, trade.getTradeAmount()); return btcFormatter.formatCoinWithCode(tradeFeeInBTC) + percentage; } else { return bsqFormatter.formatCoinWithCode(dataModel.getTradeFeeAsBsq()); @@ -313,7 +319,7 @@ public String getSecurityDeposit() { Coin securityDeposit = dataModel.isBuyer() ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); - String percentage = GUIUtil.getPercentageOfTradeAmount(securityDeposit, trade.getTradeAmount(), btcFormatter); + String percentage = GUIUtil.getPercentageOfTradeAmount(securityDeposit, trade.getTradeAmount()); return btcFormatter.formatCoinWithCode(securityDeposit) + percentage; } else { return ""; @@ -455,4 +461,28 @@ private void onTradeStateChanged(Trade.State tradeState) { break; } } + + private String getRole(boolean isBuyerMakerAndSellerTaker, boolean isMaker, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + String baseCurrencyCode = Res.getBaseCurrencyCode(); + if (isBuyerMakerAndSellerTaker) + return isMaker ? + Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.buyer")) : + Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.seller")); + else + return isMaker ? + Res.get("formatter.asMaker", baseCurrencyCode, Res.get("shared.seller")) : + Res.get("formatter.asTaker", baseCurrencyCode, Res.get("shared.buyer")); + } else { + if (isBuyerMakerAndSellerTaker) + return isMaker ? + Res.get("formatter.asMaker", currencyCode, Res.get("shared.seller")) : + Res.get("formatter.asTaker", currencyCode, Res.get("shared.buyer")); + else + return isMaker ? + Res.get("formatter.asMaker", currencyCode, Res.get("shared.buyer")) : + Res.get("formatter.asTaker", currencyCode, Res.get("shared.seller")); + } + + } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java index 9c12794ede0..cb71e6fcdc5 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep2View.java @@ -49,6 +49,7 @@ import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.portfolio.pendingtrades.PendingTradesViewModel; import bisq.desktop.main.portfolio.pendingtrades.steps.TradeStepView; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.Layout; import bisq.core.locale.CurrencyUtil; @@ -500,7 +501,7 @@ private void showPopup() { String fees = Res.get("portfolio.pending.step2_buyer.fees"); String id = trade.getShortId(); String paddedId = " " + id + " "; - String amount = model.btcFormatter.formatVolumeWithCode(trade.getTradeVolume()); + String amount = DisplayUtils.formatVolumeWithCode(trade.getTradeVolume()); if (paymentAccountPayload instanceof AssetsAccountPayload) { //noinspection UnusedAssignment message += Res.get("portfolio.pending.step2_buyer.altcoin", diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java index 96d94c4c668..9071279310d 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/buyer/BuyerStep4View.java @@ -38,8 +38,9 @@ import bisq.core.btc.wallet.Restrictions; import bisq.core.locale.Res; import bisq.core.user.DontShowAgainLookup; -import bisq.core.util.BSFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.coin.CoinUtil; import bisq.core.util.validation.BtcAddressValidator; import bisq.common.UserThread; @@ -214,7 +215,7 @@ private void reviewWithdrawal() { if (toAddresses.isEmpty()) { validateWithdrawAddress(); } else if (Restrictions.isAboveDust(receiverAmount)) { - BSFormatter formatter = model.btcFormatter; + CoinFormatter formatter = model.btcFormatter; int txSize = feeEstimationTransaction.bitcoinSerialize().length; double feePerByte = CoinUtil.getFeePerByte(fee, txSize); double kb = txSize / 1000d; diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java index 846e6d33747..f79ae3f655e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/seller/SellerStep3View.java @@ -23,6 +23,7 @@ import bisq.desktop.main.overlays.popups.Popup; import bisq.desktop.main.portfolio.pendingtrades.PendingTradesViewModel; import bisq.desktop.main.portfolio.pendingtrades.steps.TradeStepView; +import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.Layout; import bisq.core.locale.CurrencyUtil; @@ -320,7 +321,7 @@ private void showPopup() { //noinspection UnusedAssignment String key = "confirmPayment" + trade.getId(); String message = ""; - String tradeVolumeWithCode = model.btcFormatter.formatVolumeWithCode(trade.getTradeVolume()); + String tradeVolumeWithCode = DisplayUtils.formatVolumeWithCode(trade.getTradeVolume()); String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()); String part1 = Res.get("portfolio.pending.step3_seller.part", currencyName); String id = trade.getShortId(); diff --git a/desktop/src/main/java/bisq/desktop/main/presentation/MarketPricePresentation.java b/desktop/src/main/java/bisq/desktop/main/presentation/MarketPricePresentation.java index 870304ecf60..fb69085e5ce 100644 --- a/desktop/src/main/java/bisq/desktop/main/presentation/MarketPricePresentation.java +++ b/desktop/src/main/java/bisq/desktop/main/presentation/MarketPricePresentation.java @@ -30,7 +30,8 @@ import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.common.UserThread; @@ -64,7 +65,6 @@ @Singleton public class MarketPricePresentation { private final Preferences preferences; - private final BSFormatter formatter; private final PriceFeedService priceFeedService; @Getter private final ObservableList priceFeedComboBoxItems = FXCollections.observableArrayList(); @@ -92,11 +92,9 @@ public class MarketPricePresentation { public MarketPricePresentation(BtcWalletService btcWalletService, PriceFeedService priceFeedService, Preferences preferences, - FeeService feeService, - BSFormatter formatter) { + FeeService feeService) { this.priceFeedService = priceFeedService; this.preferences = preferences; - this.formatter = formatter; TxIdTextField.setPreferences(preferences); @@ -138,12 +136,12 @@ private void fillPriceFeedComboBoxItems() { } private void setupMarketPriceFeed() { - priceFeedService.requestPriceFeed(price -> marketPrice.set(formatter.formatMarketPrice(price, priceFeedService.getCurrencyCode())), + priceFeedService.requestPriceFeed(price -> marketPrice.set(FormattingUtils.formatMarketPrice(price, priceFeedService.getCurrencyCode())), (errorMessage, throwable) -> marketPrice.set(Res.get("shared.na"))); marketPriceBinding = EasyBind.combine( marketPriceCurrencyCode, marketPrice, - (currencyCode, price) -> formatter.getCurrencyPair(currencyCode) + ": " + price); + (currencyCode, price) -> CurrencyUtil.getCurrencyPair(currencyCode) + ": " + price); marketPriceBinding.subscribe((observable, oldValue, newValue) -> { if (newValue != null && !newValue.equals(oldValue)) { @@ -195,14 +193,14 @@ private void setMarketPriceInItems() { MarketPrice marketPrice = priceFeedService.getMarketPrice(currencyCode); String priceString; if (marketPrice != null && marketPrice.isPriceAvailable()) { - priceString = formatter.formatMarketPrice(marketPrice.getPrice(), currencyCode); + priceString = FormattingUtils.formatMarketPrice(marketPrice.getPrice(), currencyCode); item.setPriceAvailable(true); item.setExternallyProvidedPrice(marketPrice.isExternallyProvidedPrice()); } else { priceString = Res.get("shared.na"); item.setPriceAvailable(false); } - item.setDisplayString(formatter.getCurrencyPair(currencyCode) + ": " + priceString); + item.setDisplayString(CurrencyUtil.getCurrencyPair(currencyCode) + ": " + priceString); final String code = item.currencyCode; if (selectedPriceFeedComboBoxItemProperty.get() != null && diff --git a/desktop/src/main/java/bisq/desktop/main/settings/network/NetworkSettingsView.java b/desktop/src/main/java/bisq/desktop/main/settings/network/NetworkSettingsView.java index f0eaef9464c..d51414fd9d2 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/network/NetworkSettingsView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/network/NetworkSettingsView.java @@ -36,7 +36,9 @@ import bisq.core.filter.FilterManager; import bisq.core.locale.Res; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; import bisq.network.p2p.network.Statistic; @@ -47,6 +49,7 @@ import org.bitcoinj.core.Peer; import javax.inject.Inject; +import javax.inject.Named; import javafx.fxml.FXML; @@ -112,7 +115,6 @@ public class NetworkSettingsView extends ActivatableViewAndModel Res.get("settings.net.sentReceived", - formatter.formatBytes((long) sent), - formatter.formatBytes((long) received)))); + FormattingUtils.formatBytes((long) sent), + FormattingUtils.formatBytes((long) received)))); sortedList.comparatorProperty().bind(tableView.comparatorProperty()); tableView.setItems(sortedList); @@ -425,7 +425,7 @@ private void updateP2PTable() { tableView.getItems().forEach(P2pNetworkListItem::cleanup); networkListItems.clear(); networkListItems.setAll(p2PService.getNetworkNode().getAllConnections().stream() - .map(connection -> new P2pNetworkListItem(connection, clockWatcher, formatter)) + .map(connection -> new P2pNetworkListItem(connection, clockWatcher)) .collect(Collectors.toList())); } diff --git a/desktop/src/main/java/bisq/desktop/main/settings/network/P2pNetworkListItem.java b/desktop/src/main/java/bisq/desktop/main/settings/network/P2pNetworkListItem.java index 20b6f6f7be3..bf9610b50e8 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/network/P2pNetworkListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/network/P2pNetworkListItem.java @@ -17,8 +17,11 @@ package bisq.desktop.main.settings.network; +import bisq.desktop.util.DisplayUtils; + import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.network.Connection; import bisq.network.p2p.network.OutboundConnection; @@ -44,7 +47,6 @@ public class P2pNetworkListItem { private final Connection connection; private final Subscription sentBytesSubscription, receivedBytesSubscription, onionAddressSubscription, roundTripTimeSubscription; private final ClockWatcher clockWatcher; - private final BSFormatter formatter; private final StringProperty lastActivity = new SimpleStringProperty(); private final StringProperty sentBytes = new SimpleStringProperty(); @@ -55,16 +57,15 @@ public class P2pNetworkListItem { private final StringProperty onionAddress = new SimpleStringProperty(); private final ClockWatcher.Listener listener; - public P2pNetworkListItem(Connection connection, ClockWatcher clockWatcher, BSFormatter formatter) { + public P2pNetworkListItem(Connection connection, ClockWatcher clockWatcher) { this.connection = connection; this.clockWatcher = clockWatcher; - this.formatter = formatter; this.statistic = connection.getStatistic(); sentBytesSubscription = EasyBind.subscribe(statistic.sentBytesProperty(), - e -> sentBytes.set(formatter.formatBytes((long) e))); + e -> sentBytes.set(FormattingUtils.formatBytes((long) e))); receivedBytesSubscription = EasyBind.subscribe(statistic.receivedBytesProperty(), - e -> receivedBytes.set(formatter.formatBytes((long) e))); + e -> receivedBytes.set(FormattingUtils.formatBytes((long) e))); onionAddressSubscription = EasyBind.subscribe(connection.getPeersNodeAddressProperty(), nodeAddress -> onionAddress.set(nodeAddress != null ? nodeAddress.getFullAddress() : Res.get("settings.net.notKnownYet"))); roundTripTimeSubscription = EasyBind.subscribe(statistic.roundTripTimeProperty(), @@ -118,7 +119,7 @@ else if (connection.getPeerType() == Connection.PeerType.DIRECT_MSG_PEER) } public String getCreationDate() { - return formatter.formatDateTime(statistic.getCreationDate()); + return DisplayUtils.formatDateTime(statistic.getCreationDate()); } public String getOnionAddress() { 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 dce3bf9e706..d7657d9f523 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 @@ -30,7 +30,6 @@ import bisq.desktop.util.Layout; import bisq.core.app.BisqEnvironment; -import bisq.core.btc.BaseCurrencyNetwork; import bisq.core.btc.wallet.Restrictions; import bisq.core.dao.DaoFacade; import bisq.core.dao.DaoOptionKeys; @@ -47,7 +46,10 @@ import bisq.core.provider.fee.FeeService; import bisq.core.user.BlockChainExplorer; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import bisq.core.util.validation.IntegerValidator; import bisq.common.UserThread; @@ -122,7 +124,7 @@ public class PreferencesView extends ActivatableViewAndModel fiatCurrenciesListView; private ComboBox fiatCurrenciesComboBox; @@ -158,7 +160,7 @@ public PreferencesView(PreferencesViewModel model, AssetService assetService, FilterManager filterManager, DaoFacade daoFacade, - BSFormatter formatter, + @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, @Named(DaoOptionKeys.FULL_DAO_NODE) String fullDaoNode, @Named(DaoOptionKeys.RPC_USER) String rpcUser, @Named(DaoOptionKeys.RPC_PASSWORD) String rpcPassword, @@ -315,22 +317,22 @@ public BaseCurrencyNetwork fromString(String string) { deviationListener = (observable, oldValue, newValue) -> { try { - double value = formatter.parsePercentStringToDouble(newValue); + double value = ParsingUtils.parsePercentStringToDouble(newValue); final double maxDeviation = 0.5; if (value <= maxDeviation) { preferences.setMaxPriceDistanceInPercent(value); } else { new Popup<>().warning(Res.get("setting.preferences.deviationToLarge", maxDeviation * 100)).show(); - UserThread.runAfter(() -> deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); + UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); } } catch (NumberFormatException t) { log.error("Exception at parseDouble deviation: " + t.toString()); - UserThread.runAfter(() -> deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); + UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); } }; deviationFocusedListener = (observable1, oldValue1, newValue1) -> { if (oldValue1 && !newValue1) - UserThread.runAfter(() -> deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); + UserThread.runAfter(() -> deviationInputTextField.setText(FormattingUtils.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())), 100, TimeUnit.MILLISECONDS); }; // ignoreTraders @@ -746,7 +748,7 @@ public BlockChainExplorer fromString(String string) { }); blockChainExplorerComboBox.setOnAction(e -> preferences.setBlockChainExplorer(blockChainExplorerComboBox.getSelectionModel().getSelectedItem())); - deviationInputTextField.setText(formatter.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())); + deviationInputTextField.setText(FormattingUtils.formatPercentagePrice(preferences.getMaxPriceDistanceInPercent())); deviationInputTextField.textProperty().addListener(deviationListener); deviationInputTextField.focusedProperty().addListener(deviationFocusedListener); diff --git a/desktop/src/main/java/bisq/desktop/util/BsqAddressHelper.java b/desktop/src/main/java/bisq/desktop/util/BsqAddressHelper.java new file mode 100644 index 00000000000..bca6eece7cc --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/util/BsqAddressHelper.java @@ -0,0 +1,41 @@ +package bisq.desktop.util; + +import org.bitcoinj.core.Address; +import org.bitcoinj.core.AddressFormatException; +import org.bitcoinj.core.NetworkParameters; + +public class BsqAddressHelper { + + private static final String prefix = "B"; + + private final boolean useBsqAddressFormat; + private final NetworkParameters networkParams; + + public BsqAddressHelper(boolean useBsqAddressFormat, NetworkParameters networkParams) { + this.useBsqAddressFormat = useBsqAddressFormat; + this.networkParams = networkParams; + } + + /** + * Returns the base-58 encoded String representation of this + * object, including version and checksum bytes. + */ + public String getBsqAddressStringFromAddress(Address address) { + final String addressString = address.toString(); + if (useBsqAddressFormat) + return prefix + addressString; + else + return addressString; + } + + public Address getAddressFromBsqAddress(String encoded) { + if (useBsqAddressFormat) + encoded = encoded.substring(prefix.length(), encoded.length()); + + try { + return Address.fromBase58(networkParams, encoded); + } catch (AddressFormatException e) { + throw new RuntimeException(e); + } + } +} diff --git a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java new file mode 100644 index 00000000000..e4beb6cf145 --- /dev/null +++ b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java @@ -0,0 +1,221 @@ +package bisq.desktop.util; + +import bisq.core.locale.CurrencyUtil; +import bisq.core.locale.GlobalSettings; +import bisq.core.locale.Res; +import bisq.core.monetary.Altcoin; +import bisq.core.monetary.Price; +import bisq.core.monetary.Volume; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Monetary; +import org.bitcoinj.utils.Fiat; +import org.bitcoinj.utils.MonetaryFormat; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; + +import java.text.DateFormat; + +import java.math.BigDecimal; + +import java.util.Date; +import java.util.Optional; + +import lombok.extern.slf4j.Slf4j; + +import static bisq.core.util.ParsingUtils.parseToCoin; + +@Slf4j +public class DisplayUtils { + private static final int scale = 3; + private static final MonetaryFormat fiatVolumeFormat = new MonetaryFormat().shift(0).minDecimals(2).repeatOptionalDecimals(0, 0); + + public static String getDirectionWithCode(OfferPayload.Direction direction, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) + return (direction == OfferPayload.Direction.BUY) ? Res.get("shared.buyCurrency", Res.getBaseCurrencyCode()) : Res.get("shared.sellCurrency", Res.getBaseCurrencyCode()); + else + return (direction == OfferPayload.Direction.SELL) ? Res.get("shared.buyCurrency", currencyCode) : Res.get("shared.sellCurrency", currencyCode); + } + + public static String formatDateTime(Date date) { + return FormattingUtils.formatDateTime(date, true); + } + + public static String formatDateTimeSpan(Date dateFrom, Date dateTo) { + if (dateFrom != null && dateTo != null) { + DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, GlobalSettings.getLocale()); + DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, GlobalSettings.getLocale()); + return dateFormatter.format(dateFrom) + " " + timeFormatter.format(dateFrom) + FormattingUtils.RANGE_SEPARATOR + timeFormatter.format(dateTo); + } else { + return ""; + } + } + + public static String formatTime(Date date) { + if (date != null) { + DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, GlobalSettings.getLocale()); + return timeFormatter.format(date); + } else { + return ""; + } + } + + public static String formatDate(Date date) { + if (date != null) { + DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, GlobalSettings.getLocale()); + return dateFormatter.format(date); + } else { + return ""; + } + } + + public static String formatAccountAge(long durationMillis) { + durationMillis = Math.max(0, durationMillis); + String day = Res.get("time.day").toLowerCase(); + String days = Res.get("time.days"); + String format = "d\' " + days + "\'"; + return StringUtils.replaceOnce(DurationFormatUtils.formatDuration(durationMillis, format), "1 " + days, "1 " + day); + } + + public static String booleanToYesNo(boolean value) { + return value ? Res.get("shared.yes") : Res.get("shared.no"); + } + + public static String getDirectionBothSides(OfferPayload.Direction direction, String currencyCode) { + if (CurrencyUtil.isFiatCurrency(currencyCode)) { + currencyCode = Res.getBaseCurrencyCode(); + return direction == OfferPayload.Direction.BUY ? + Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) : + Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer")); + } else { + return direction == OfferPayload.Direction.SELL ? + Res.get("formatter.makerTaker", currencyCode, Res.get("shared.buyer"), currencyCode, Res.get("shared.seller")) : + Res.get("formatter.makerTaker", currencyCode, Res.get("shared.seller"), currencyCode, Res.get("shared.buyer")); + } + } + + public static String getFeeWithFiatAmount(Coin makerFeeAsCoin, Optional optionalFeeInFiat, CoinFormatter formatter) { + String fee = makerFeeAsCoin != null ? formatter.formatCoinWithCode(makerFeeAsCoin) : Res.get("shared.na"); + String feeInFiatAsString; + if (optionalFeeInFiat != null && optionalFeeInFiat.isPresent()) { + feeInFiatAsString = formatVolumeWithCode(optionalFeeInFiat.get()); + } else { + feeInFiatAsString = Res.get("shared.na"); + } + return Res.get("feeOptionWindow.fee", fee, feeInFiatAsString); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Volume + /////////////////////////////////////////////////////////////////////////////////////////// + + public static String formatVolume(Volume volume) { + return formatVolume(volume, fiatVolumeFormat, false); + } + + public static String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits) { + return formatVolume(offer, decimalAligned, maxNumberOfDigits, true); + } + + public static String formatVolume(Offer offer, Boolean decimalAligned, int maxNumberOfDigits, boolean showRange) { + String formattedVolume = offer.isRange() && showRange ? formatVolume(offer.getMinVolume()) + FormattingUtils.RANGE_SEPARATOR + formatVolume(offer.getVolume()) : formatVolume(offer.getVolume()); + + if (decimalAligned) { + formattedVolume = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedVolume, maxNumberOfDigits); + } + return formattedVolume; + } + + public static String formatVolumeWithCode(Volume volume) { + return formatVolume(volume, fiatVolumeFormat, true); + } + + private static String formatVolume(Volume volume, MonetaryFormat fiatVolumeFormat, boolean appendCurrencyCode) { + if (volume != null) { + Monetary monetary = volume.getMonetary(); + if (monetary instanceof Fiat) + return FormattingUtils.formatFiat((Fiat) monetary, fiatVolumeFormat, appendCurrencyCode); + else + return FormattingUtils.formatAltcoinVolume((Altcoin) monetary, appendCurrencyCode); + } else { + return ""; + } + } + + public static String formatVolumeLabel(String currencyCode) { + return formatVolumeLabel(currencyCode, ""); + } + + public static String formatVolumeLabel(String currencyCode, String postFix) { + return Res.get("formatter.formatVolumeLabel", + currencyCode, postFix); + } + + public static String formatPrice(Price price, Boolean decimalAligned, int maxPlaces) { + String formattedPrice = FormattingUtils.formatPrice(price); + + if (decimalAligned) { + formattedPrice = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedPrice, maxPlaces); + } + return formattedPrice; + } + + + public static String formatAmount(Offer offer, CoinFormatter coinFormatter) { + return offer.isRange() ? coinFormatter.formatCoin(offer.getMinAmount()) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount()) : coinFormatter.formatCoin(offer.getAmount()); + } + + public static String formatAmount(Offer offer, + int decimalPlaces, + boolean decimalAligned, + int maxPlaces, + CoinFormatter coinFormatter) { + String formattedAmount = offer.isRange() ? coinFormatter.formatCoin(offer.getMinAmount(), decimalPlaces) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount(), decimalPlaces) : coinFormatter.formatCoin(offer.getAmount(), decimalPlaces); + + if (decimalAligned) { + formattedAmount = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedAmount, maxPlaces); + } + return formattedAmount; + } + + /** + * Converts to a coin with max. 4 decimal places. Last place gets rounded. + * 0.01234 -> 0.0123 + * 0.01235 -> 0.0124 + * + * @param input + * @param coinFormatter + * @return + */ + public static Coin parseToCoinWith4Decimals(String input, CoinFormatter coinFormatter) { + try { + return Coin.valueOf(new BigDecimal(parseToCoin(ParsingUtils.cleanDoubleInput(input), coinFormatter).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) + log.warn("Exception at parseToCoinWith4Decimals: " + t.toString()); + return Coin.ZERO; + } + } + + public static boolean hasBtcValidDecimals(String input, CoinFormatter coinFormatter) { + return parseToCoin(input, coinFormatter).equals(parseToCoinWith4Decimals(input, coinFormatter)); + } + + /** + * Transform a coin with the properties defined in the format (used to reduce decimal places) + * + * @param coin The coin which should be transformed + * @param coinFormatter + * @return The transformed coin + */ + public static Coin reduceTo4Decimals(Coin coin, CoinFormatter coinFormatter) { + return parseToCoin(coinFormatter.formatCoin(coin), coinFormatter); + } +} diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index aa772f2c531..ea5cb2a9443 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -38,9 +38,10 @@ import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinUtil; +import bisq.core.util.FormattingUtils; import bisq.network.p2p.P2PService; @@ -680,13 +681,13 @@ public static void openMail(String to, String subject, String body) { } } - public static String getPercentageOfTradeAmount(Coin fee, Coin tradeAmount, BSFormatter formatter) { - return " (" + getPercentage(fee, tradeAmount, formatter) + + public static String getPercentageOfTradeAmount(Coin fee, Coin tradeAmount) { + return " (" + getPercentage(fee, tradeAmount) + " " + Res.get("guiUtil.ofTradeAmount") + ")"; } - public static String getPercentage(Coin part, Coin total, BSFormatter formatter) { - return formatter.formatToPercentWithSymbol((double) part.value / (double) total.value); + public static String getPercentage(Coin part, Coin total) { + return FormattingUtils.formatToPercentWithSymbol((double) part.value / (double) total.value); } public static T getParentOfType(Node node, Class t) { @@ -752,7 +753,7 @@ else if (!walletsSetup.isDownloadComplete()) log.warn("showNotReadyForTxBroadcastPopups called but no case matched. This should never happen if isReadyForTxBroadcast was called before."); } - public static void showWantToBurnBTCPopup(Coin miningFee, Coin amount, BSFormatter btcFormatter) { + public static void showWantToBurnBTCPopup(Coin miningFee, Coin amount, CoinFormatter btcFormatter) { new Popup<>().warning(Res.get("popup.warning.burnBTC", btcFormatter.formatCoinWithCode(miningFee), btcFormatter.formatCoinWithCode(amount))).show(); } @@ -856,7 +857,7 @@ public static void removeChildrenFromGridPaneRows(GridPane gridPane, int start, } public static void showBsqFeeInfoPopup(Coin fee, Coin miningFee, Coin btcForIssuance, int txSize, BsqFormatter bsqFormatter, - BSFormatter btcFormatter, String type, + CoinFormatter btcFormatter, String type, Runnable actionHandler) { String confirmationMessage; @@ -888,7 +889,7 @@ public static void showBsqFeeInfoPopup(Coin fee, Coin miningFee, Coin btcForIssu } public static void showBsqFeeInfoPopup(Coin fee, Coin miningFee, int txSize, BsqFormatter bsqFormatter, - BSFormatter btcFormatter, String type, + CoinFormatter btcFormatter, String type, Runnable actionHandler) { showBsqFeeInfoPopup(fee, miningFee, null, txSize, bsqFormatter, btcFormatter, type, actionHandler); } diff --git a/desktop/src/main/java/bisq/desktop/util/validation/BsqAddressValidator.java b/desktop/src/main/java/bisq/desktop/util/validation/BsqAddressValidator.java index f4dd1c45090..ce645b98151 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/BsqAddressValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/BsqAddressValidator.java @@ -17,19 +17,21 @@ package bisq.desktop.util.validation; +import bisq.desktop.util.BsqAddressHelper; + import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.InputValidator; import javax.inject.Inject; public final class BsqAddressValidator extends InputValidator { - private final BsqFormatter bsqFormatter; + private final BsqAddressHelper helper; @Inject - public BsqAddressValidator(BsqFormatter bsqFormatter) { - this.bsqFormatter = bsqFormatter; + public BsqAddressValidator(BsqAddressHelper addressHelper) { + this.helper = addressHelper; } @Override @@ -44,7 +46,7 @@ public ValidationResult validate(String input) { private ValidationResult validateBsqAddress(String input) { try { - bsqFormatter.getAddressFromBsqAddress(input); + helper.getAddressFromBsqAddress(input); return new ValidationResult(true); } catch (Throwable e) { return new ValidationResult(false, Res.get("validation.bsq.invalidFormat")); 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..9f4f6c93950 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/BsqValidator.java @@ -19,8 +19,9 @@ import bisq.core.btc.wallet.Restrictions; import bisq.core.locale.Res; -import bisq.core.util.BsqFormatter; -import bisq.core.util.CoinUtil; +import bisq.core.util.ParsingUtils; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinUtil; 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/BtcValidator.java b/desktop/src/main/java/bisq/desktop/util/validation/BtcValidator.java index d1b8d3d8173..f4353e1ef9e 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/BtcValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/BtcValidator.java @@ -19,11 +19,13 @@ import bisq.core.btc.wallet.Restrictions; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.coin.CoinFormatter; import org.bitcoinj.core.Coin; import javax.inject.Inject; +import javax.inject.Named; import java.math.BigDecimal; @@ -34,7 +36,7 @@ public class BtcValidator extends NumberValidator { - protected final BSFormatter formatter; + protected final CoinFormatter formatter; @Nullable @Setter @@ -50,7 +52,7 @@ public class BtcValidator extends NumberValidator { protected Coin maxTradeLimit; @Inject - public BtcValidator(BSFormatter formatter) { + public BtcValidator(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.formatter = formatter; } 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 04ecfe59f82..9a300af7700 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java +++ b/desktop/src/main/java/bisq/desktop/util/validation/SecurityDepositValidator.java @@ -20,17 +20,21 @@ import bisq.core.btc.wallet.Restrictions; import bisq.core.locale.Res; import bisq.core.payment.PaymentAccount; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; +import bisq.core.util.FormattingUtils; +import bisq.core.util.ParsingUtils; import javax.inject.Inject; +import javax.inject.Named; public class SecurityDepositValidator extends NumberValidator { - private final BSFormatter formatter; + private final CoinFormatter formatter; private PaymentAccount paymentAccount; @Inject - public SecurityDepositValidator(BSFormatter formatter) { + public SecurityDepositValidator(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { this.formatter = formatter; } @@ -58,11 +62,11 @@ public ValidationResult validate(String input) { private ValidationResult validateIfNotTooLowPercentageValue(String input) { try { - double percentage = formatter.parsePercentStringToDouble(input); + double percentage = ParsingUtils.parsePercentStringToDouble(input); double minPercentage = Restrictions.getMinBuyerSecurityDepositAsPercent(paymentAccount); if (percentage < minPercentage) return new ValidationResult(false, - Res.get("validation.inputTooSmall", formatter.formatToPercentWithSymbol(minPercentage))); + Res.get("validation.inputTooSmall", FormattingUtils.formatToPercentWithSymbol(minPercentage))); else return new ValidationResult(true); } catch (Throwable t) { @@ -72,11 +76,11 @@ private ValidationResult validateIfNotTooLowPercentageValue(String input) { private ValidationResult validateIfNotTooHighPercentageValue(String input) { try { - double percentage = formatter.parsePercentStringToDouble(input); + double percentage = ParsingUtils.parsePercentStringToDouble(input); double maxPercentage = Restrictions.getMaxBuyerSecurityDepositAsPercent(paymentAccount); if (percentage > maxPercentage) return new ValidationResult(false, - Res.get("validation.inputTooLarge", formatter.formatToPercentWithSymbol(maxPercentage))); + Res.get("validation.inputTooLarge", FormattingUtils.formatToPercentWithSymbol(maxPercentage))); else return new ValidationResult(true); } catch (Throwable t) { diff --git a/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java b/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java index 482ab242333..699f9348935 100644 --- a/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java +++ b/desktop/src/test/java/bisq/desktop/GuiceSetupTest.java @@ -38,8 +38,7 @@ import bisq.core.proto.persistable.CorePersistenceProtoResolver; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.network.p2p.network.BridgeAddressProvider; import bisq.network.p2p.seed.SeedNodeRepository; @@ -86,7 +85,6 @@ public void testGuiceSetup() { assertSingleton(Navigation.class); assertSingleton(InjectorViewFactory.class); assertSingleton(NotificationCenter.class); - assertSingleton(BSFormatter.class); assertSingleton(BsqFormatter.class); assertSingleton(TorNetworkSettingsWindow.class); assertSingleton(MarketPricePresentation.class); diff --git a/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java index 24a012b824f..2d2479bf261 100644 --- a/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java @@ -23,7 +23,10 @@ import bisq.core.locale.GlobalSettings; import bisq.core.provider.price.PriceFeedService; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; + +import org.bitcoinj.utils.MonetaryFormat; import javafx.beans.property.SimpleIntegerProperty; @@ -58,7 +61,7 @@ public void testMaxCharactersForBuyPriceWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null); assertEquals(0, model.maxPlacesForBuyPrice.intValue()); } @@ -77,7 +80,7 @@ public void testMaxCharactersForBuyPriceWithOfflinePriceFeedService() { when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty()); when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null); model.activate(); assertEquals(0, model.maxPlacesForBuyPrice.intValue()); } @@ -91,7 +94,7 @@ public void testMaxCharactersForFiatBuyPrice() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null); model.activate(); assertEquals(7, model.maxPlacesForBuyPrice.intValue()); offerBookListItems.addAll(make(btcBuyItem.but(with(OfferBookListItemMaker.price, 94016475L)))); @@ -107,7 +110,7 @@ public void testMaxCharactersForBuyVolumeWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null); assertEquals(0, model.maxPlacesForBuyVolume.intValue()); } @@ -120,7 +123,7 @@ public void testMaxCharactersForFiatBuyVolume() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null); model.activate(); assertEquals(4, model.maxPlacesForBuyVolume.intValue()); //0.01 offerBookListItems.addAll(make(btcBuyItem.but(with(OfferBookListItemMaker.amount, 100000000L)))); @@ -136,7 +139,7 @@ public void testMaxCharactersForSellPriceWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null); assertEquals(0, model.maxPlacesForSellPrice.intValue()); } @@ -155,7 +158,7 @@ public void testMaxCharactersForSellPriceWithOfflinePriceFeedService() { when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty()); when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null); model.activate(); assertEquals(0, model.maxPlacesForSellPrice.intValue()); } @@ -169,7 +172,7 @@ public void testMaxCharactersForFiatSellPrice() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null); model.activate(); assertEquals(7, model.maxPlacesForSellPrice.intValue()); // 10.0000 default price offerBookListItems.addAll(make(btcSellItem.but(with(OfferBookListItemMaker.price, 94016475L)))); @@ -185,7 +188,7 @@ public void testMaxCharactersForSellVolumeWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null); assertEquals(0, model.maxPlacesForSellVolume.intValue()); } @@ -198,7 +201,7 @@ public void testMaxCharactersForFiatSellVolume() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter()); + final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null); model.activate(); assertEquals(4, model.maxPlacesForSellVolume.intValue()); //0.01 offerBookListItems.addAll(make(btcSellItem.but(with(OfferBookListItemMaker.amount, 100000000L)))); diff --git a/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java index f32326bb8a5..614ee2afc9a 100644 --- a/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java @@ -23,11 +23,15 @@ import bisq.desktop.main.offer.offerbook.OfferBookListItemMaker; import bisq.core.provider.price.PriceFeedService; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; + +import org.bitcoinj.utils.MonetaryFormat; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import org.junit.Before; import org.junit.Test; import static bisq.desktop.main.offer.offerbook.OfferBookListItemMaker.btcBuyItem; @@ -41,6 +45,13 @@ public class SpreadViewModelTest { + private CoinFormatter coinFormatter; + + @Before + public void setup() { + coinFormatter = new ImmutableCoinFormatter(MonetaryFormat.BTC); + } + @Test public void testMaxCharactersForAmountWithNoOffers() { OfferBook offerBook = mock(OfferBook.class); @@ -48,7 +59,7 @@ public void testMaxCharactersForAmountWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - SpreadViewModel model = new SpreadViewModel(offerBook, null, new BSFormatter()); + SpreadViewModel model = new SpreadViewModel(offerBook, null, coinFormatter); assertEquals(0, model.maxPlacesForAmount.intValue()); } @@ -60,7 +71,7 @@ public void testMaxCharactersForAmount() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - SpreadViewModel model = new SpreadViewModel(offerBook, null, new BSFormatter()); + SpreadViewModel model = new SpreadViewModel(offerBook, null, coinFormatter); model.activate(); assertEquals(6, model.maxPlacesForAmount.intValue()); // 0.001 offerBookListItems.addAll(make(btcBuyItem.but(with(OfferBookListItemMaker.amount, 1403000000L)))); @@ -76,7 +87,7 @@ public void testFilterSpreadItemsForUniqueOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); - SpreadViewModel model = new SpreadViewModel(offerBook, priceFeedService, new BSFormatter()); + SpreadViewModel model = new SpreadViewModel(offerBook, priceFeedService, coinFormatter); model.activate(); assertEquals(1, model.spreadItems.get(0).numberOfOffers); diff --git a/desktop/src/test/java/bisq/desktop/main/market/trades/TradesChartsViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/market/trades/TradesChartsViewModelTest.java index 7e969c41006..d1403428116 100644 --- a/desktop/src/test/java/bisq/desktop/main/market/trades/TradesChartsViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/market/trades/TradesChartsViewModelTest.java @@ -27,7 +27,7 @@ import bisq.core.trade.statistics.TradeStatistics2; import bisq.core.trade.statistics.TradeStatisticsManager; import bisq.core.user.Preferences; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.common.crypto.KeyRing; import bisq.common.crypto.KeyStorage; @@ -111,7 +111,7 @@ public class TradesChartsViewModelTest { public void setup() throws IOException { tradeStatisticsManager = mock(TradeStatisticsManager.class); model = new TradesChartsViewModel(tradeStatisticsManager, mock(Preferences.class), mock(PriceFeedService.class), - mock(Navigation.class), mock(BSFormatter.class)); + mock(Navigation.class)); dir = File.createTempFile("temp_tests1", ""); //noinspection ResultOfMethodCallIgnored dir.delete(); diff --git a/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java index 6b4aa521165..cb1c51aa047 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java @@ -39,11 +39,13 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.core.util.validation.InputValidator; import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; import javafx.beans.property.SimpleIntegerProperty; @@ -67,16 +69,18 @@ public class CreateOfferViewModelTest { private CreateOfferViewModel model; + private CoinFormatter btcFormatter; + @Before public void setUp() { final CryptoCurrency btc = new CryptoCurrency("BTC", "bitcoin"); GlobalSettings.setDefaultTradeCurrency(btc); Res.setup(); - final BSFormatter bsFormatter = new BSFormatter(); - final BtcValidator btcValidator = new BtcValidator(bsFormatter); + final BtcValidator btcValidator = new BtcValidator(btcFormatter); final AltcoinValidator altcoinValidator = new AltcoinValidator(); final FiatPriceValidator fiatPriceValidator = new FiatPriceValidator(); + btcFormatter = new ImmutableCoinFormatter(MonetaryFormat.BTC); FeeService feeService = mock(FeeService.class); AddressEntry addressEntry = mock(AddressEntry.class); @@ -104,11 +108,11 @@ public void setUp() { when(bsqFormatter.formatCoin(any())).thenReturn("0"); when(bsqWalletService.getAvailableConfirmedBalance()).thenReturn(Coin.ZERO); - CreateOfferDataModel dataModel = new CreateOfferDataModel(null, btcWalletService, bsqWalletService, empty, user, null, null, priceFeedService, null, accountAgeWitnessService, feeService, txFeeEstimationService, null, bsFormatter, mock(MakerFeeProvider.class)); + CreateOfferDataModel dataModel = new CreateOfferDataModel(null, btcWalletService, bsqWalletService, empty, user, null, null, priceFeedService, null, accountAgeWitnessService, feeService, txFeeEstimationService, null, btcFormatter, mock(MakerFeeProvider.class)); dataModel.initWithData(OfferPayload.Direction.BUY, new CryptoCurrency("BTC", "bitcoin")); dataModel.activate(); - model = new CreateOfferViewModel(dataModel, null, fiatPriceValidator, altcoinValidator, btcValidator, null, securityDepositValidator, null, null, priceFeedService, null, preferences, bsFormatter, bsqFormatter); + model = new CreateOfferViewModel(dataModel, null, fiatPriceValidator, altcoinValidator, btcValidator, null, securityDepositValidator, null, null, priceFeedService, null, preferences, btcFormatter, bsqFormatter); model.activate(); } diff --git a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java index 272d241c468..df029382fa2 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java @@ -41,7 +41,10 @@ import bisq.core.payment.payload.SpecificBanksAccountPayload; import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; + +import org.bitcoinj.utils.MonetaryFormat; import javafx.beans.property.SimpleIntegerProperty; @@ -79,6 +82,8 @@ public class OfferBookViewModelTest { private static final Logger log = LoggerFactory.getLogger(OfferBookViewModelTest.class); + private final CoinFormatter btcFormatter = new ImmutableCoinFormatter(MonetaryFormat.BTC); + @Before public void setUp() { GlobalSettings.setDefaultTradeCurrency(usd); @@ -225,7 +230,7 @@ public void testMaxCharactersForAmountWithNoOffes() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); assertEquals(0, model.maxPlacesForAmount.intValue()); } @@ -239,7 +244,7 @@ public void testMaxCharactersForAmount() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(6, model.maxPlacesForAmount.intValue()); @@ -257,7 +262,7 @@ public void testMaxCharactersForAmountRange() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(15, model.maxPlacesForAmount.intValue()); @@ -276,7 +281,7 @@ public void testMaxCharactersForVolumeWithNoOffes() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); assertEquals(0, model.maxPlacesForVolume.intValue()); } @@ -290,7 +295,7 @@ public void testMaxCharactersForVolume() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(8, model.maxPlacesForVolume.intValue()); @@ -308,7 +313,7 @@ public void testMaxCharactersForVolumeRange() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(15, model.maxPlacesForVolume.intValue()); @@ -327,7 +332,7 @@ public void testMaxCharactersForPriceWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); assertEquals(0, model.maxPlacesForPrice.intValue()); } @@ -341,7 +346,7 @@ public void testMaxCharactersForPrice() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(7, model.maxPlacesForPrice.intValue()); @@ -359,7 +364,7 @@ public void testMaxCharactersForPriceDistanceWithNoOffers() { when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems); final OfferBookViewModel model = new OfferBookViewModel(null, null, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); assertEquals(0, model.maxPlacesForMarketPriceMargin.intValue()); } @@ -387,7 +392,7 @@ public void testMaxCharactersForPriceDistance() { offerBookListItems.addAll(item1, item2); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, priceFeedService, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); model.activate(); assertEquals(8, model.maxPlacesForMarketPriceMargin.intValue()); //" (1.97%)" @@ -408,7 +413,7 @@ public void testGetPrice() { when(priceFeedService.getMarketPrice(anyString())).thenReturn(new MarketPrice("USD", 12684.0450, Instant.now().getEpochSecond(), true)); final OfferBookViewModel model = new OfferBookViewModel(null, openOfferManager, offerBook, empty, null, null, - null, null, null, null, new BSFormatter()); + null, null, null, null, btcFormatter); final OfferBookListItem item = make(btcBuyItem.but( with(useMarketBasedPrice, true), diff --git a/desktop/src/test/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModelTest.java b/desktop/src/test/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModelTest.java index ee0dc5a2e97..dbd0591b538 100644 --- a/desktop/src/test/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModelTest.java @@ -20,8 +20,7 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.user.Preferences; import bisq.core.user.User; -import bisq.core.util.BSFormatter; -import bisq.core.util.BsqFormatter; +import bisq.core.util.coin.BsqFormatter; import bisq.core.util.validation.InputValidator; import org.bitcoinj.core.Coin; @@ -62,8 +61,6 @@ public void setUp() { GlobalSettings.setDefaultTradeCurrency(btc); Res.setup(); - final BSFormatter bsFormatter = new BSFormatter(); - FeeService feeService = mock(FeeService.class); AddressEntry addressEntry = mock(AddressEntry.class); BtcWalletService btcWalletService = mock(BtcWalletService.class); diff --git a/desktop/src/test/java/bisq/desktop/util/BSFormatterTest.java b/desktop/src/test/java/bisq/desktop/util/BSFormatterTest.java deleted file mode 100644 index 3c319ea62e1..00000000000 --- a/desktop/src/test/java/bisq/desktop/util/BSFormatterTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.desktop.util; - -import bisq.core.locale.Res; -import bisq.core.monetary.Volume; -import bisq.core.offer.Offer; -import bisq.core.offer.OfferPayload; -import bisq.core.util.BSFormatter; - -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.CoinMaker; - -import java.util.Locale; -import java.util.concurrent.TimeUnit; - -import org.junit.Before; -import org.junit.Test; - -import static bisq.desktop.maker.OfferMaker.btcUsdOffer; -import static bisq.desktop.maker.PriceMaker.priceString; -import static bisq.desktop.maker.PriceMaker.usdPrice; -import static bisq.desktop.maker.VolumeMaker.usdVolume; -import static bisq.desktop.maker.VolumeMaker.volumeString; -import static com.natpryce.makeiteasy.MakeItEasy.a; -import static com.natpryce.makeiteasy.MakeItEasy.make; -import static com.natpryce.makeiteasy.MakeItEasy.with; -import static org.bitcoinj.core.CoinMaker.oneBitcoin; -import static org.bitcoinj.core.CoinMaker.satoshis; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class BSFormatterTest { - - private BSFormatter formatter; - - @Before - public void setUp() { - Locale.setDefault(new Locale("en", "US")); - formatter = new BSFormatter(); - Res.setBaseCurrencyCode("BTC"); - Res.setBaseCurrencyName("Bitcoin"); - } - - @Test - public void testIsValid() { - assertEquals("0 days", formatter.formatAccountAge(TimeUnit.HOURS.toMillis(23))); - assertEquals("0 days", formatter.formatAccountAge(0)); - assertEquals("0 days", formatter.formatAccountAge(-1)); - assertEquals("1 day", formatter.formatAccountAge(TimeUnit.DAYS.toMillis(1))); - assertEquals("2 days", formatter.formatAccountAge(TimeUnit.DAYS.toMillis(2))); - assertEquals("30 days", formatter.formatAccountAge(TimeUnit.DAYS.toMillis(30))); - assertEquals("60 days", formatter.formatAccountAge(TimeUnit.DAYS.toMillis(60))); - } - - @Test - public void testFormatDurationAsWords() { - long oneDay = TimeUnit.DAYS.toMillis(1); - long oneHour = TimeUnit.HOURS.toMillis(1); - long oneMinute = TimeUnit.MINUTES.toMillis(1); - long oneSecond = TimeUnit.SECONDS.toMillis(1); - - assertEquals("1 hour, 0 minutes", formatter.formatDurationAsWords(oneHour)); - assertEquals("1 day, 0 hours, 0 minutes", formatter.formatDurationAsWords(oneDay)); - assertEquals("2 days, 0 hours, 1 minute", formatter.formatDurationAsWords(oneDay * 2 + oneMinute)); - assertEquals("2 days, 0 hours, 2 minutes", formatter.formatDurationAsWords(oneDay * 2 + oneMinute * 2)); - assertEquals("1 hour, 0 minutes, 0 seconds", formatter.formatDurationAsWords(oneHour, true, true)); - assertEquals("1 hour, 0 minutes, 1 second", formatter.formatDurationAsWords(oneHour + oneSecond, true, true)); - assertEquals("1 hour, 0 minutes, 2 seconds", formatter.formatDurationAsWords(oneHour + oneSecond * 2, true, true)); - assertEquals("2 days, 21 hours, 28 minutes", formatter.formatDurationAsWords(oneDay * 2 + oneHour * 21 + oneMinute * 28)); - assertEquals("110 days", formatter.formatDurationAsWords(oneDay * 110, false, false)); - assertEquals("10 days, 10 hours, 10 minutes, 10 seconds", formatter.formatDurationAsWords(oneDay * 10 + oneHour * 10 + oneMinute * 10 + oneSecond * 10, true, false)); - assertEquals("1 hour, 2 seconds", formatter.formatDurationAsWords(oneHour + oneSecond * 2, true, false)); - assertEquals("1 hour", formatter.formatDurationAsWords(oneHour + oneSecond * 2, false, false)); - assertEquals("0 hours, 0 minutes, 1 second", formatter.formatDurationAsWords(oneSecond, true, true)); - assertEquals("1 second", formatter.formatDurationAsWords(oneSecond, true, false)); - assertEquals("0 hours", formatter.formatDurationAsWords(oneSecond, false, false)); - assertEquals("", formatter.formatDurationAsWords(0)); - assertTrue(formatter.formatDurationAsWords(0).isEmpty()); - } - - @Test - public void testFormatPrice() { - assertEquals("100.0000", formatter.formatPrice(make(usdPrice))); - assertEquals("7098.4700", formatter.formatPrice(make(usdPrice.but(with(priceString, "7098.4700"))))); - } - - @Test - public void testFormatCoin() { - assertEquals("1.00", formatter.formatCoin(oneBitcoin)); - assertEquals("1.0000", formatter.formatCoin(oneBitcoin, 4)); - assertEquals("1.00", formatter.formatCoin(oneBitcoin, 5)); - assertEquals("0.000001", formatter.formatCoin(make(a(CoinMaker.Coin).but(with(satoshis, 100L))))); - assertEquals("0.00000001", formatter.formatCoin(make(a(CoinMaker.Coin).but(with(satoshis, 1L))))); - } - - @Test - public void testFormatVolume() { - assertEquals("1.00", formatter.formatVolume(make(btcUsdOffer), true, 4)); - assertEquals("100.00", formatter.formatVolume(make(usdVolume))); - assertEquals("1774.62", formatter.formatVolume(make(usdVolume.but(with(volumeString, "1774.62"))))); - } - - @Test - public void testFormatSameVolume() { - Offer offer = mock(Offer.class); - Volume btc = Volume.parse("0.10", "BTC"); - when(offer.getMinVolume()).thenReturn(btc); - when(offer.getVolume()).thenReturn(btc); - - assertEquals("0.10000000", formatter.formatVolume(offer.getVolume())); - } - - @Test - public void testFormatDifferentVolume() { - Offer offer = mock(Offer.class); - Volume btcMin = Volume.parse("0.10", "BTC"); - Volume btcMax = Volume.parse("0.25", "BTC"); - when(offer.isRange()).thenReturn(true); - when(offer.getMinVolume()).thenReturn(btcMin); - when(offer.getVolume()).thenReturn(btcMax); - - assertEquals("0.10000000 - 0.25000000", formatter.formatVolume(offer, false, 0)); - } - - @Test - public void testFormatNullVolume() { - Offer offer = mock(Offer.class); - when(offer.getMinVolume()).thenReturn(null); - when(offer.getVolume()).thenReturn(null); - - assertEquals("", formatter.formatVolume(offer.getVolume())); - } - - @Test - public void testFormatSameAmount() { - Offer offer = mock(Offer.class); - when(offer.getMinAmount()).thenReturn(Coin.valueOf(10000000)); - when(offer.getAmount()).thenReturn(Coin.valueOf(10000000)); - - assertEquals("0.10", formatter.formatAmount(offer)); - } - - @Test - public void testFormatDifferentAmount() { - OfferPayload offerPayload = mock(OfferPayload.class); - Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(20000000L); - - assertEquals("0.10 - 0.20", formatter.formatAmount(offer)); - } - - @Test - public void testFormatAmountWithAlignmenWithDecimals() { - OfferPayload offerPayload = mock(OfferPayload.class); - Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(20000000L); - - assertEquals("0.1000 - 0.2000", formatter.formatAmount(offer, 4, true, 15)); - } - - @Test - public void testFormatAmountWithAlignmenWithDecimalsNoRange() { - OfferPayload offerPayload = mock(OfferPayload.class); - Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(10000000L); - - assertEquals("0.1000", formatter.formatAmount(offer, 4, true, 15)); - } - - @Test - public void testFormatNullAmount() { - Offer offer = mock(Offer.class); - when(offer.getMinAmount()).thenReturn(null); - when(offer.getAmount()).thenReturn(null); - - assertEquals("", formatter.formatAmount(offer)); - } -} diff --git a/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java b/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java new file mode 100644 index 00000000000..16fd956a7ee --- /dev/null +++ b/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java @@ -0,0 +1,134 @@ +package bisq.desktop.util; + +import bisq.core.locale.Res; +import bisq.core.monetary.Volume; +import bisq.core.offer.Offer; +import bisq.core.offer.OfferPayload; +import bisq.core.util.coin.CoinFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; + +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; + +import static bisq.desktop.maker.OfferMaker.btcUsdOffer; +import static bisq.desktop.maker.VolumeMaker.usdVolume; +import static bisq.desktop.maker.VolumeMaker.volumeString; +import static com.natpryce.makeiteasy.MakeItEasy.make; +import static com.natpryce.makeiteasy.MakeItEasy.with; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DisplayUtilsTest { + private final CoinFormatter formatter = new ImmutableCoinFormatter(MonetaryFormat.BTC); + + @Before + public void setUp() { + Locale.setDefault(new Locale("en", "US")); + Res.setBaseCurrencyCode("BTC"); + Res.setBaseCurrencyName("Bitcoin"); + } + + @Test + public void testFormatAccountAge() { + assertEquals("0 days", DisplayUtils.formatAccountAge(TimeUnit.HOURS.toMillis(23))); + assertEquals("0 days", DisplayUtils.formatAccountAge(0)); + assertEquals("0 days", DisplayUtils.formatAccountAge(-1)); + assertEquals("1 day", DisplayUtils.formatAccountAge(TimeUnit.DAYS.toMillis(1))); + assertEquals("2 days", DisplayUtils.formatAccountAge(TimeUnit.DAYS.toMillis(2))); + assertEquals("30 days", DisplayUtils.formatAccountAge(TimeUnit.DAYS.toMillis(30))); + assertEquals("60 days", DisplayUtils.formatAccountAge(TimeUnit.DAYS.toMillis(60))); + } + + @Test + public void testFormatVolume() { + assertEquals("1.00", DisplayUtils.formatVolume(make(btcUsdOffer), true, 4)); + assertEquals("100.00", DisplayUtils.formatVolume(make(usdVolume))); + assertEquals("1774.62", DisplayUtils.formatVolume(make(usdVolume.but(with(volumeString, "1774.62"))))); + } + + @Test + public void testFormatSameVolume() { + Offer offer = mock(Offer.class); + Volume btc = Volume.parse("0.10", "BTC"); + when(offer.getMinVolume()).thenReturn(btc); + when(offer.getVolume()).thenReturn(btc); + + assertEquals("0.10000000", DisplayUtils.formatVolume(offer.getVolume())); + } + + @Test + public void testFormatDifferentVolume() { + Offer offer = mock(Offer.class); + Volume btcMin = Volume.parse("0.10", "BTC"); + Volume btcMax = Volume.parse("0.25", "BTC"); + when(offer.isRange()).thenReturn(true); + when(offer.getMinVolume()).thenReturn(btcMin); + when(offer.getVolume()).thenReturn(btcMax); + + assertEquals("0.10000000 - 0.25000000", DisplayUtils.formatVolume(offer, false, 0)); + } + + @Test + public void testFormatNullVolume() { + Offer offer = mock(Offer.class); + when(offer.getMinVolume()).thenReturn(null); + when(offer.getVolume()).thenReturn(null); + + assertEquals("", DisplayUtils.formatVolume(offer.getVolume())); + } + + @Test + public void testFormatSameAmount() { + Offer offer = mock(Offer.class); + when(offer.getMinAmount()).thenReturn(Coin.valueOf(10000000)); + when(offer.getAmount()).thenReturn(Coin.valueOf(10000000)); + + assertEquals("0.10", DisplayUtils.formatAmount(offer, formatter)); + } + + @Test + public void testFormatDifferentAmount() { + OfferPayload offerPayload = mock(OfferPayload.class); + Offer offer = new Offer(offerPayload); + when(offerPayload.getMinAmount()).thenReturn(10000000L); + when(offerPayload.getAmount()).thenReturn(20000000L); + + assertEquals("0.10 - 0.20", DisplayUtils.formatAmount(offer, formatter)); + } + + @Test + public void testFormatAmountWithAlignmenWithDecimals() { + OfferPayload offerPayload = mock(OfferPayload.class); + Offer offer = new Offer(offerPayload); + when(offerPayload.getMinAmount()).thenReturn(10000000L); + when(offerPayload.getAmount()).thenReturn(20000000L); + + assertEquals("0.1000 - 0.2000", DisplayUtils.formatAmount(offer, 4, true, 15, formatter)); + } + + @Test + public void testFormatAmountWithAlignmenWithDecimalsNoRange() { + OfferPayload offerPayload = mock(OfferPayload.class); + Offer offer = new Offer(offerPayload); + when(offerPayload.getMinAmount()).thenReturn(10000000L); + when(offerPayload.getAmount()).thenReturn(10000000L); + + assertEquals("0.1000", DisplayUtils.formatAmount(offer, 4, true, 15, formatter)); + } + + @Test + public void testFormatNullAmount() { + Offer offer = mock(Offer.class); + when(offer.getMinAmount()).thenReturn(null); + when(offer.getAmount()).thenReturn(null); + + assertEquals("", DisplayUtils.formatAmount(offer, formatter)); + } +} diff --git a/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java b/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java index 067d6b3a14a..64cd5133392 100644 --- a/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java +++ b/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java @@ -21,9 +21,10 @@ import bisq.core.btc.BaseCurrencyNetwork; import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.util.BSFormatter; +import bisq.core.util.coin.ImmutableCoinFormatter; import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.MonetaryFormat; import org.junit.Before; import org.junit.Test; @@ -44,7 +45,7 @@ public void setup() { @Test public void testIsValid() { - BtcValidator validator = new BtcValidator(new BSFormatter()); + BtcValidator validator = new BtcValidator(new ImmutableCoinFormatter(MonetaryFormat.BTC)); assertTrue(validator.validate("1").isValid); assertTrue(validator.validate("0,1").isValid);