diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 0a2b54913a..e2ced9613a 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -31,9 +31,7 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_keys_file.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; -import 'package:ledger_bitcoin/ledger_bitcoin.dart'; import 'package:ledger_bitcoin/psbt.dart'; -import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:mobx/mobx.dart'; import 'package:ur/cbor_lite.dart'; import 'package:ur/ur.dart'; diff --git a/cw_bitcoin/lib/electrum_balance.dart b/cw_bitcoin/lib/electrum_balance.dart index aeb06f1f07..c129f245bd 100644 --- a/cw_bitcoin/lib/electrum_balance.dart +++ b/cw_bitcoin/lib/electrum_balance.dart @@ -1,5 +1,5 @@ import 'dart:convert'; -import 'package:cw_bitcoin/bitcoin_amount_format.dart'; + import 'package:cw_core/balance.dart'; class ElectrumBalance extends Balance { @@ -9,17 +9,11 @@ class ElectrumBalance extends Balance { required this.frozen, this.secondConfirmed = 0, this.secondUnconfirmed = 0, - }) : super( - confirmed, - unconfirmed, - secondAvailable: secondConfirmed, - secondAdditional: secondUnconfirmed, - ); + }) : super(confirmed, unconfirmed, + secondAvailable: secondConfirmed, secondAdditional: secondUnconfirmed, frozen: frozen); static ElectrumBalance? fromJSON(String? jsonSource) { - if (jsonSource == null) { - return null; - } + if (jsonSource == null) return null; final decoded = json.decode(jsonSource) as Map; @@ -34,31 +28,14 @@ class ElectrumBalance extends Balance { int confirmed; int unconfirmed; + @override final int frozen; + int secondConfirmed = 0; int secondUnconfirmed = 0; @override - String get formattedAvailableBalance => bitcoinAmountToString(amount: ((confirmed + unconfirmed) - frozen) ); - - @override - String get formattedAdditionalBalance => bitcoinAmountToString(amount: unconfirmed); - - @override - String get formattedUnAvailableBalance { - final frozenFormatted = bitcoinAmountToString(amount: frozen); - return frozenFormatted == '0.0' ? '' : frozenFormatted; - } - - @override - String get formattedSecondAvailableBalance => bitcoinAmountToString(amount: secondConfirmed); - - @override - String get formattedSecondAdditionalBalance => bitcoinAmountToString(amount: secondUnconfirmed); - - @override - String get formattedFullAvailableBalance => - bitcoinAmountToString(amount: (confirmed + unconfirmed) + secondConfirmed - frozen); + int get fullAvailableBalance => (confirmed + unconfirmed) + secondConfirmed - frozen; String toJSON() => json.encode({ 'confirmed': confirmed, diff --git a/cw_bitcoin/lib/electrum_transaction_info.dart b/cw_bitcoin/lib/electrum_transaction_info.dart index 407e405e10..12bfa8a6b3 100644 --- a/cw_bitcoin/lib/electrum_transaction_info.dart +++ b/cw_bitcoin/lib/electrum_transaction_info.dart @@ -225,11 +225,11 @@ class ElectrumTransactionInfo extends TransactionInfo { @override String amountFormatted() => - '${formatAmount(bitcoinAmountToString(amount: amount))} ${walletTypeToCryptoCurrency(type).title}'; + '${walletTypeToCryptoCurrency(type).formatAmount(BigInt.from(amount))} ${walletTypeToCryptoCurrency(type).title}'; @override String? feeFormatted() => fee != null - ? '${formatAmount(bitcoinAmountToString(amount: fee!))} ${walletTypeToCryptoCurrency(type).title}' + ? '${walletTypeToCryptoCurrency(type).formatAmount(BigInt.from(fee!))} ${walletTypeToCryptoCurrency(type).title}' : ''; @override diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index a285ff9794..7e008ed6c6 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -4,6 +4,13 @@ import 'dart:io'; import 'dart:isolate'; import 'package:bitcoin_base/bitcoin_base.dart'; +import 'package:cw_core/hardware/hardware_wallet_service.dart'; +import 'package:cw_core/root_dir.dart'; +import 'package:cw_core/utils/proxy_wrapper.dart'; +import 'package:cw_core/utils/print_verbose.dart'; +import 'package:cw_bitcoin/bitcoin_wallet.dart'; +import 'package:cw_bitcoin/litecoin_wallet.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:blockchain_utils/blockchain_utils.dart'; import 'package:collection/collection.dart'; import 'package:cw_bitcoin/address_from_output.dart'; @@ -11,7 +18,6 @@ import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart'; import 'package:cw_bitcoin/bitcoin_transaction_priority.dart'; import 'package:cw_bitcoin/bitcoin_unspent.dart'; -import 'package:cw_bitcoin/bitcoin_wallet.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; import 'package:cw_bitcoin/electrum.dart' as electrum; import 'package:cw_bitcoin/electrum_balance.dart'; @@ -20,25 +26,20 @@ import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/exceptions.dart'; -import 'package:cw_bitcoin/litecoin_wallet.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/utils.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/encryption_file_utils.dart'; import 'package:cw_core/get_height_by_date.dart'; -import 'package:cw_core/hardware/hardware_wallet_service.dart'; import 'package:cw_core/node.dart'; import 'package:cw_core/output_info.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/root_dir.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coin_type.dart'; import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/utils/print_verbose.dart'; -import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/utils/socket_health_logger.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; @@ -49,7 +50,6 @@ import 'package:hex/hex.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:rxdart/subjects.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:sp_scanner/sp_scanner.dart'; part 'electrum_wallet.g.dart'; diff --git a/cw_core/lib/balance.dart b/cw_core/lib/balance.dart index 7350c80f18..6394855370 100644 --- a/cw_core/lib/balance.dart +++ b/cw_core/lib/balance.dart @@ -1,17 +1,17 @@ +/// Balance Data class with all amounts in the lowest possible currency (e.g. satoshis or wei) abstract class Balance { - const Balance(this.available, this.additional, {this.secondAvailable, this.secondAdditional}); + const Balance(this.available, this.additional, {this.secondAvailable, this.secondAdditional, this.frozen}); final int available; - final int additional; final int? secondAvailable; final int? secondAdditional; - String get formattedAvailableBalance; - String get formattedAdditionalBalance; + final int? frozen; + + int get fullAvailableBalance => available; + + @deprecated String get formattedUnAvailableBalance => ''; - String get formattedSecondAvailableBalance => ''; - String get formattedSecondAdditionalBalance => ''; - String get formattedFullAvailableBalance => formattedAvailableBalance; } diff --git a/cw_core/lib/crypto_currency.dart b/cw_core/lib/crypto_currency.dart index d3f9faf221..f0b86ac7df 100644 --- a/cw_core/lib/crypto_currency.dart +++ b/cw_core/lib/crypto_currency.dart @@ -1,10 +1,9 @@ import 'package:cw_core/currency.dart'; import 'package:cw_core/enumerable_item.dart'; import 'package:collection/collection.dart'; +import 'package:cw_core/format_fixed.dart'; import 'package:cw_core/parse_fixed.dart'; -import 'format_fixed.dart'; - class CryptoCurrency extends EnumerableItem with Serializable implements Currency { const CryptoCurrency({ String title = '', @@ -391,19 +390,18 @@ class CryptoCurrency extends EnumerableItem with Serializable implemen int? decimals, bool? enabled, bool? isPotentialScam, - }) { - return CryptoCurrency( - title: title ?? this.title, - raw: raw ?? this.raw, - name: name ?? this.name, - fullName: fullName ?? this.fullName, - iconPath: iconPath ?? this.iconPath, - tag: tag ?? this.tag, - decimals: decimals ?? this.decimals, - enabled: enabled ?? this.enabled, - isPotentialScam: isPotentialScam ?? this.isPotentialScam, - ); - } + }) => + CryptoCurrency( + title: title ?? this.title, + raw: raw ?? this.raw, + name: name ?? this.name, + fullName: fullName ?? this.fullName, + iconPath: iconPath ?? this.iconPath, + tag: tag ?? this.tag, + decimals: decimals ?? this.decimals, + enabled: enabled ?? this.enabled, + isPotentialScam: isPotentialScam ?? this.isPotentialScam, + ); @override String toString() => title; diff --git a/cw_core/lib/monero_balance.dart b/cw_core/lib/monero_balance.dart index 34f51faf97..9c14a7d4f6 100644 --- a/cw_core/lib/monero_balance.dart +++ b/cw_core/lib/monero_balance.dart @@ -3,25 +3,15 @@ import 'package:cw_core/monero_amount_format.dart'; class MoneroBalance extends Balance { MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0}) - : formattedUnconfirmedBalance = moneroAmountToString(amount: fullBalance - unlockedBalance), - formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance), - formattedFrozenBalance = moneroAmountToString(amount: frozenBalance), - super(unlockedBalance, fullBalance); + : formattedFrozenBalance = moneroAmountToString(amount: frozenBalance), + super(unlockedBalance, fullBalance, frozen: frozenBalance); final int fullBalance; final int unlockedBalance; final int frozenBalance; - final String formattedUnconfirmedBalance; - final String formattedUnlockedBalance; final String formattedFrozenBalance; @override String get formattedUnAvailableBalance => formattedFrozenBalance == '0.0' ? '' : formattedFrozenBalance; - - @override - String get formattedAvailableBalance => formattedUnlockedBalance; - - @override - String get formattedAdditionalBalance => formattedUnconfirmedBalance; } diff --git a/cw_core/lib/wownero_balance.dart b/cw_core/lib/wownero_balance.dart index 916fa90bc6..c309226b9c 100644 --- a/cw_core/lib/wownero_balance.dart +++ b/cw_core/lib/wownero_balance.dart @@ -3,26 +3,15 @@ import 'package:cw_core/wownero_amount_format.dart'; class WowneroBalance extends Balance { WowneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0}) - : formattedUnconfirmedBalance = wowneroAmountToString(amount: fullBalance - unlockedBalance), - formattedUnlockedBalance = wowneroAmountToString(amount: unlockedBalance), - formattedFrozenBalance = - wowneroAmountToString(amount: frozenBalance), - super(unlockedBalance, fullBalance); + : formattedFrozenBalance = wowneroAmountToString(amount: frozenBalance), + super(unlockedBalance, fullBalance, frozen: frozenBalance); final int fullBalance; final int unlockedBalance; final int frozenBalance; - final String formattedUnconfirmedBalance; - final String formattedUnlockedBalance; final String formattedFrozenBalance; @override String get formattedUnAvailableBalance => formattedFrozenBalance == '0.0' ? '' : formattedFrozenBalance; - - @override - String get formattedAvailableBalance => formattedUnlockedBalance; - - @override - String get formattedAdditionalBalance => formattedUnconfirmedBalance; -} \ No newline at end of file +} diff --git a/cw_evm/lib/evm_chain_transaction_info.dart b/cw_evm/lib/evm_chain_transaction_info.dart index 781dd57388..ac9227f17a 100644 --- a/cw_evm/lib/evm_chain_transaction_info.dart +++ b/cw_evm/lib/evm_chain_transaction_info.dart @@ -1,8 +1,6 @@ // ignore_for_file: overridden_fields, annotate_overrides - -import 'dart:math'; - import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/format_fixed.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; @@ -47,10 +45,8 @@ abstract class EVMChainTransactionInfo extends TransactionInfo { String get feeCurrency; @override - String amountFormatted() { - final amount = formatAmount((ethAmount / BigInt.from(10).pow(exponent)).toString()); - return '${amount.substring(0, min(10, amount.length))} $tokenSymbol'; - } + String amountFormatted() => + '${formatFixed(ethAmount, exponent, fractionalDigits: 10)} $tokenSymbol'; @override String fiatAmount() => _fiatAmount ?? ''; @@ -59,10 +55,7 @@ abstract class EVMChainTransactionInfo extends TransactionInfo { void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); @override - String feeFormatted() { - final amount = (ethFee / BigInt.from(10).pow(18)).toString(); - return '${amount.substring(0, min(18, amount.length))} $feeCurrency'; - } + String feeFormatted() => '${formatFixed(ethFee, 18)} $feeCurrency'; Map toJson() => { 'id': id, diff --git a/cw_evm/lib/evm_erc20_balance.dart b/cw_evm/lib/evm_erc20_balance.dart index a29b741885..369f950d9a 100644 --- a/cw_evm/lib/evm_erc20_balance.dart +++ b/cw_evm/lib/evm_erc20_balance.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:cw_core/format_fixed.dart'; import 'package:cw_core/balance.dart'; @@ -10,12 +9,6 @@ class EVMChainERC20Balance extends Balance { final BigInt balance; final int exponent; - @override - String get formattedAdditionalBalance => formatFixed(balance, exponent, fractionalDigits: 12); - - @override - String get formattedAvailableBalance => formatFixed(balance, exponent, fractionalDigits: 12); - String toJSON() => json.encode({ 'balanceInWei': balance.toString(), 'exponent': exponent, diff --git a/cw_monero/lib/monero_transaction_info.dart b/cw_monero/lib/monero_transaction_info.dart index 0ac48dcba9..b7ddd0ca69 100644 --- a/cw_monero/lib/monero_transaction_info.dart +++ b/cw_monero/lib/monero_transaction_info.dart @@ -1,13 +1,12 @@ -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/monero_amount_format.dart'; -import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/format_amount.dart'; +import 'package:cw_core/transaction_direction.dart'; +import 'package:cw_core/transaction_info.dart'; class MoneroTransactionInfo extends TransactionInfo { - MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date, - this.isPending, this.amount, this.accountIndex, this.addressIndex, this.fee, - this.confirmations) : - id = "${txHash}_${amount}_${accountIndex}_${addressIndex}"; + MoneroTransactionInfo(this.txHash, this.height, this.direction, this.date, this.isPending, + this.amount, this.accountIndex, this.addressIndex, this.fee, this.confirmations) + : id = "${txHash}_${amount}_${accountIndex}_${addressIndex}"; final String id; final String txHash; @@ -25,8 +24,7 @@ class MoneroTransactionInfo extends TransactionInfo { String? _fiatAmount; @override - String amountFormatted() => - '${formatAmount(moneroAmountToString(amount: amount))} XMR'; + String amountFormatted() => '${CryptoCurrency.xmr.formatAmount(BigInt.from(amount))} XMR'; @override String fiatAmount() => _fiatAmount ?? ''; @@ -35,6 +33,5 @@ class MoneroTransactionInfo extends TransactionInfo { void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); @override - String feeFormatted() => - '${formatAmount(moneroAmountToString(amount: fee))} XMR'; + String feeFormatted() => '${CryptoCurrency.xmr.formatAmount(BigInt.from(fee))} XMR'; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 9f5986e267..81771193b1 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -3,6 +3,7 @@ import 'dart:ffi'; import 'dart:io'; import 'dart:isolate'; +import 'package:cw_core/format_fixed.dart'; import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/transaction_priority.dart'; diff --git a/cw_tron/lib/tron_balance.dart b/cw_tron/lib/tron_balance.dart index 5b2ba3fa7c..001478bfc2 100644 --- a/cw_tron/lib/tron_balance.dart +++ b/cw_tron/lib/tron_balance.dart @@ -1,22 +1,13 @@ import 'dart:convert'; import 'package:cw_core/balance.dart'; -import 'package:on_chain/on_chain.dart'; class TronBalance extends Balance { TronBalance(this.balance) : super(balance.toInt(), balance.toInt()); final BigInt balance; - @override - String get formattedAdditionalBalance => TronHelper.fromSun(balance); - - @override - String get formattedAvailableBalance => TronHelper.fromSun(balance); - - String toJSON() => json.encode({ - 'balance': balance.toString(), - }); + String toJSON() => json.encode({ 'balance': balance.toString() }); static TronBalance? fromJSON(String? jsonSource) { if (jsonSource == null) { diff --git a/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart b/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart index bf6dc1fd92..04f2663ab0 100644 --- a/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart +++ b/lib/cake_pay/src/cards/cake_pay_buy_card_page.dart @@ -617,13 +617,19 @@ class CakePayBuyCardPage extends BasePage { expirationTime: cakePayBuyCardViewModel.formattedRemainingTime, walletType: _sendViewModel.walletType, titleIconPath: _sendViewModel.selectedCryptoCurrency.iconPath, - currency: _sendViewModel.selectedCryptoCurrency, + currencyTitle: _sendViewModel.amountParsingProxy + .getCryptoSymbol(_sendViewModel.selectedCryptoCurrency), amount: S.of(bottomSheetContext).send_amount, - amountValue: _sendViewModel.pendingTransaction!.amountFormatted, + amountValue: _sendViewModel.amountParsingProxy.getCryptoOutputAmount( + _sendViewModel.pendingTransaction!.amountFormatted, + _sendViewModel.selectedCryptoCurrency), quantity: 'QTY: ${cakePayBuyCardViewModel.quantity}', fiatAmountValue: _sendViewModel.pendingTransactionFiatAmountFormatted, fee: S.of(bottomSheetContext).send_fee, - feeValue: _sendViewModel.pendingTransaction!.feeFormatted, + feeValue: "${_sendViewModel.amountParsingProxy.getCryptoOutputAmount( + _sendViewModel.pendingTransaction!.feeFormattedValue, + _sendViewModel.selectedCryptoCurrency)} ${_sendViewModel.amountParsingProxy + .getCryptoSymbol(_sendViewModel.wallet.currency)}", feeFiatAmount: _sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: displayingOutputs, footerType: FooterType.slideActionButton, diff --git a/lib/core/amount.dart b/lib/core/amount.dart deleted file mode 100644 index 3d64f1d669..0000000000 --- a/lib/core/amount.dart +++ /dev/null @@ -1,37 +0,0 @@ -// abstract class Amount { -// Amount(this.value); - -// int value; - -// int minorDigits; - -// String code; - -// String formatted(); -// } - -// class MoneroAmount extends Amount { -// MoneroAmount(int value) : super(value) { -// minorDigits = 12; -// code = 'XMR'; -// } - -// // const moneroAmountLength = 12; -// // const moneroAmountDivider = 1000000000000; -// // final moneroAmountFormat = NumberFormat() -// // ..maximumFractionDigits = moneroAmountLength -// // ..minimumFractionDigits = 1; - -// // String moneroAmountToString({int amount}) => -// // moneroAmountFormat.format(cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider)); - -// // double moneroAmountToDouble({int amount}) => cryptoAmountToDouble(amount: amount, divider: moneroAmountDivider); - -// // int moneroParseAmount({String amount}) => moneroAmountFormat.parse(amount).toInt(); - -// @override -// String formatted() { -// // TODO: implement formatted -// throw UnimplementedError(); -// } -// } diff --git a/lib/core/amount_parsing_proxy.dart b/lib/core/amount_parsing_proxy.dart new file mode 100644 index 0000000000..890a47196d --- /dev/null +++ b/lib/core/amount_parsing_proxy.dart @@ -0,0 +1,63 @@ +import 'package:cake_wallet/entities/bitcoin_amount_display_mode.dart'; +import 'package:cw_core/crypto_currency.dart'; + +class AmountParsingProxy { + final BitcoinAmountDisplayMode displayMode; + + const AmountParsingProxy(this.displayMode); + + /// [getCryptoInputAmount] turns the input [amount] into the canonical representation of [cryptoCurrency] + String getCryptoInputAmount(String amount, CryptoCurrency cryptoCurrency) { + if (useSatoshi(cryptoCurrency) && amount.isNotEmpty) { + return cryptoCurrency.formatAmount(BigInt.parse(amount)); + } + + return amount; + } + + /// [getCryptoOutputAmount] turns the input [amount] into the preferred representation of [cryptoCurrency] + String getCryptoOutputAmount(String amount, CryptoCurrency cryptoCurrency) { + if (useSatoshi(cryptoCurrency) && amount.isNotEmpty) { + return cryptoCurrency.parseAmount(amount).toString(); + } + + return amount; + } + + /// [getCryptoStringRepresentation] turns the input [amount] into the preferred representation of [cryptoCurrency] + String getCryptoString(int amount, CryptoCurrency cryptoCurrency) { + if (useSatoshi(cryptoCurrency)) { + return "$amount"; + } + + return cryptoCurrency.formatAmount(BigInt.from(amount)); + } + + /// [getCryptoStringFromDouble] turns the input [amount] into the preferred representation of [cryptoCurrency] and + String getCryptoStringFromDouble(double amount, CryptoCurrency cryptoCurrency) { + if (useSatoshi(cryptoCurrency)) { + return "$amount"; + } + + return cryptoCurrency.formatAmount(BigInt.from(amount)); + } + + /// [parseCryptoString] turns the input [string] into a `BigInt` presentation of the [cryptoCurrency] + BigInt parseCryptoString(String amount, CryptoCurrency cryptoCurrency) { + if (useSatoshi(cryptoCurrency)) { + return BigInt.parse(amount); + } + + return cryptoCurrency.parseAmount(amount); + } + + /// [getCryptoSymbol] returns the correct Symbol related to the presentation + String getCryptoSymbol(CryptoCurrency cryptoCurrency) => + useSatoshi(cryptoCurrency) ? "SATS" : cryptoCurrency.title; + + bool useSatoshi(CryptoCurrency cryptoCurrency) => + ([CryptoCurrency.btc, CryptoCurrency.btcln].contains(cryptoCurrency) && + displayMode == BitcoinAmountDisplayMode.satoshi) || + (CryptoCurrency.btcln == cryptoCurrency && + displayMode == BitcoinAmountDisplayMode.satoshiForLightning); +} diff --git a/lib/di.dart b/lib/di.dart index 276a470ea2..473a800a06 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -377,7 +377,7 @@ Future setup({ nodeListStore: getIt.get(), themeStore: getIt.get())); getIt.registerSingleton( - TradesStore(tradesSource: _tradesSource, settingsStore: getIt.get())); + TradesStore(tradesSource: _tradesSource, appStore: getIt.get())); getIt.registerSingleton( OrdersStore(ordersSource: _ordersSource, settingsStore: getIt.get())); getIt.registerFactory(() => @@ -547,7 +547,6 @@ Future setup({ _tradesSource, getIt.get(), getIt.get(), - getIt.get().settingsStore, getIt.get(), getIt.get(), getIt.get(), @@ -823,7 +822,7 @@ Future setup({ getIt.registerFactory(() => SendTemplateViewModel( getIt.get().wallet!, - getIt.get().settingsStore, + getIt.get(), getIt.get(), getIt.get())); @@ -975,7 +974,7 @@ Future setup({ getIt.get(param1: account))); getIt.registerFactory(() => - DisplaySettingsViewModel(getIt.get(), getIt.get())); + DisplaySettingsViewModel(getIt.get(), getIt.get())); getIt.registerFactory(() => SilentPaymentsSettingsViewModel(getIt.get(), getIt.get().wallet!)); @@ -1300,7 +1299,7 @@ Future setup({ transactionInfo: transactionInfo, transactionDescriptionBox: _transactionDescriptionBox, wallet: wallet, - settingsStore: getIt.get(), + appStore: getIt.get(), sendViewModel: getIt.get(), canReplaceByFee: canReplaceByFee, ); @@ -1441,7 +1440,7 @@ Future setup({ wallet: wallet!, unspentCoinsInfo: _unspentCoinsInfoSource, fiatConversationStore: getIt.get(), - settingsStore: getIt.get(), + appStore: getIt.get(), coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.any, ); }); diff --git a/lib/entities/bitcoin_amount_display_mode.dart b/lib/entities/bitcoin_amount_display_mode.dart new file mode 100644 index 0000000000..ea15dcfd82 --- /dev/null +++ b/lib/entities/bitcoin_amount_display_mode.dart @@ -0,0 +1,32 @@ +import 'package:cw_core/enumerable_item.dart'; + +class BitcoinAmountDisplayMode extends EnumerableItem with Serializable { + const BitcoinAmountDisplayMode({required String title, required int raw}) + : super(title: title, raw: raw); + + static const all = [ + BitcoinAmountDisplayMode.satoshiForLightning, + BitcoinAmountDisplayMode.bitcoin, + BitcoinAmountDisplayMode.satoshi, + ]; + static const satoshiForLightning = + BitcoinAmountDisplayMode(raw: 0, title: 'Lightning in Satoshi'); + static const bitcoin = BitcoinAmountDisplayMode(raw: 1, title: 'Bitcoin'); + static const satoshi = BitcoinAmountDisplayMode(raw: 2, title: 'Satoshi'); + + static BitcoinAmountDisplayMode deserialize({required int raw}) { + switch (raw) { + case 0: + return satoshiForLightning; + case 1: + return bitcoin; + case 2: + return satoshi; + default: + throw Exception('Unexpected token: $raw for BalanceDisplayMode deserialize'); + } + } + + @override + String toString() => title; +} diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart index a9acc2a6bf..382615328e 100644 --- a/lib/entities/preferences_key.dart +++ b/lib/entities/preferences_key.dart @@ -24,6 +24,7 @@ class PreferencesKey { static const currentWowneroNodeIdKey = 'current_node_id_wow'; static const currentTransactionPriorityKeyLegacy = 'current_fee_priority'; static const currentBalanceDisplayModeKey = 'current_balance_display_mode'; + static const displayAmountsInSatoshi = 'display_amounts_in_satoshi'; static const shouldSaveRecipientAddressKey = 'save_recipient_address'; static const isAppSecureKey = 'is_app_secure'; static const disableTradeOption = 'disable_buy'; diff --git a/lib/src/screens/buy/buy_sell_page.dart b/lib/src/screens/buy/buy_sell_page.dart index 53c8cdec95..b74192795f 100644 --- a/lib/src/screens/buy/buy_sell_page.dart +++ b/lib/src/screens/buy/buy_sell_page.dart @@ -453,6 +453,7 @@ class BuySellPage extends BasePage { fillColor: buySellViewModel.isBuyAction ? Theme.of(context).colorScheme.surfaceContainerLow : Theme.of(context).colorScheme.surfaceContainer, + useSatoshis: buySellViewModel.useSatoshi, ), ); diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index 85ffbcbe47..949c662745 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -155,8 +155,8 @@ class TransactionsPage extends StatelessWidget { ), currency: "BTC", state: item.status, - amount: bitcoin! - .formatterBitcoinAmountToString(amount: session.amount.toInt()), + amount: dashboardViewModel.appStore.amountParsingProxy + .getCryptoString(session.amount.toInt(), CryptoCurrency.btc), createdAt: DateFormat('HH:mm').format(session.inProgressSince!), isSending: session.isSenderSession, ); @@ -173,18 +173,22 @@ class TransactionsPage extends StatelessWidget { return tradeFrom != null && tradeTo != null ? Observer( builder: (_) => TradeRow( - key: item.key, - onTap: () => Navigator.of(context) - .pushNamed(Routes.tradeDetails, arguments: trade), - swapState: trade.state, - provider: trade.provider, - from: tradeFrom, - to: tradeTo, - createdAtFormattedDate: trade.createdAt != null - ? DateFormat('HH:mm').format(trade.createdAt!) - : null, - formattedAmount: item.tradeFormattedAmount, - formattedReceiveAmount: item.tradeFormattedReceiveAmount), + key: item.key, + onTap: () => Navigator.of(context) + .pushNamed(Routes.tradeDetails, arguments: trade), + swapState: trade.state, + provider: trade.provider, + title: "$tradeFrom → $tradeTo", + fromSymbol: dashboardViewModel.appStore.amountParsingProxy + .getCryptoSymbol(tradeFrom), + toSymbol: dashboardViewModel.appStore.amountParsingProxy + .getCryptoSymbol(tradeTo), + createdAtFormattedDate: trade.createdAt != null + ? DateFormat("HH:mm").format(trade.createdAt!) + : null, + formattedAmount: item.tradeFormattedAmount, + formattedReceiveAmount: item.tradeFormattedReceiveAmount, + ), ) : Container(); } diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index e50cb97186..05e3749179 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -1,15 +1,15 @@ -import 'package:cake_wallet/exchange/trade_state.dart'; -import 'package:cake_wallet/palette.dart'; -import 'package:cake_wallet/utils/image_utill.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/exchange/exchange_provider_description.dart'; -import 'package:cw_core/crypto_currency.dart'; +import "package:cake_wallet/exchange/trade_state.dart"; +import "package:cake_wallet/palette.dart"; +import "package:cake_wallet/utils/image_utill.dart"; +import "package:flutter/material.dart"; +import "package:cake_wallet/exchange/exchange_provider_description.dart"; class TradeRow extends StatelessWidget { TradeRow({ required this.provider, - required this.from, - required this.to, + required this.title, + required this.fromSymbol, + required this.toSymbol, required this.createdAtFormattedDate, this.onTap, this.formattedAmount, @@ -20,8 +20,9 @@ class TradeRow extends StatelessWidget { final VoidCallback? onTap; final ExchangeProviderDescription provider; - final CryptoCurrency from; - final CryptoCurrency to; + final String fromSymbol; + final String toSymbol; + final String title; final String? createdAtFormattedDate; final String? formattedAmount; final String? formattedReceiveAmount; @@ -29,9 +30,6 @@ class TradeRow extends StatelessWidget { @override Widget build(BuildContext context) { - final amountCrypto = from.toString(); - final receiveAmountCrypto = to.toString(); - return InkWell( onTap: onTap, child: Container( @@ -72,7 +70,7 @@ class TradeRow extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - '${from.toString()} → ${to.toString()}', + title, style: Theme.of(context).textTheme.bodyLarge?.copyWith( fontSize: 16, fontWeight: FontWeight.w600, @@ -80,7 +78,7 @@ class TradeRow extends StatelessWidget { ), formattedAmount != null ? Text( - formattedAmount! + ' ' + amountCrypto, + "$formattedAmount $fromSymbol", style: Theme.of(context).textTheme.bodyLarge?.copyWith( fontSize: 16, fontWeight: FontWeight.w500, @@ -105,7 +103,7 @@ class TradeRow extends StatelessWidget { : Container(), formattedReceiveAmount != null ? Text( - formattedReceiveAmount! + ' ' + receiveAmountCrypto, + "$formattedReceiveAmount $toSymbol", style: Theme.of(context).textTheme.bodyMedium?.copyWith( fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurfaceVariant, diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 32a1b4eeb8..4e9403bd35 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -734,6 +734,7 @@ class ExchangePage extends BasePage { exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency); }, + useSatoshis: exchangeViewModel.useSatoshiDeposit, ), ); @@ -781,6 +782,7 @@ class ExchangePage extends BasePage { exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency); }, + useSatoshis: exchangeViewModel.useSatoshisReceive, ), ); diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index 15426b668b..038bb37c83 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -47,6 +47,7 @@ class ExchangeCard extends StatefulWidget { this.onPushPasteButton, this.onPushAddressBookButton, this.onDispose, + this.useSatoshis = false, required this.cardInstanceName, }) : super(key: key); @@ -82,6 +83,7 @@ class ExchangeCard extends StatefulWidget { final Function()? onDispose; final String cardInstanceName; final Color fillColor; + final bool useSatoshis; @override ExchangeCardState createState() => ExchangeCardState(); @@ -224,8 +226,8 @@ class ExchangeCardState extends State> { currencyAmountTextFieldWidgetKey: ValueKey('${_cardInstanceName}_currency_amount_textfield_widget_key'), imageArrow: widget.imageArrow, - selectedCurrency: _selectedCurrency.toString(), - selectedCurrencyDecimals: _selectedCurrency.decimals, + selectedCurrency: widget.useSatoshis ? "SATS" : "$_selectedCurrency", + selectedCurrencyDecimals: widget.useSatoshis ? 0 : _selectedCurrency.decimals, amountFocusNode: widget.amountFocusNode, amountController: amountController, onTapPicker: () => _presentPicker(context), diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 7a1587d845..38ecc21e58 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -280,42 +280,42 @@ class ExchangeTradeState extends State { context: context, isDismissible: false, isScrollControlled: true, - builder: (BuildContext bottomSheetContext) { + builder: (bottomSheetContext) { + final sendVM = widget.exchangeTradeViewModel.sendViewModel; + return ConfirmSendingBottomSheet( key: ValueKey('exchange_trade_page_confirm_sending_bottom_sheet_key'), footerType: FooterType.slideActionButton, - isSlideActionEnabled: widget.exchangeTradeViewModel.sendViewModel.isReadyForSend, - walletType: widget.exchangeTradeViewModel.sendViewModel.walletType, + isSlideActionEnabled: sendVM.isReadyForSend, + walletType: sendVM.walletType, titleText: S.of(bottomSheetContext).confirm_transaction, - titleIconPath: - widget.exchangeTradeViewModel.sendViewModel.selectedCryptoCurrency.iconPath, - currency: widget.exchangeTradeViewModel.sendViewModel.selectedCryptoCurrency, + titleIconPath: sendVM.selectedCryptoCurrency.iconPath, + currencyTitle: + sendVM.amountParsingProxy.getCryptoSymbol(sendVM.selectedCryptoCurrency), amount: S.of(bottomSheetContext).send_amount, - amountValue: amountValue, - fiatAmountValue: widget - .exchangeTradeViewModel.sendViewModel.pendingTransactionFiatAmountFormatted, - fee: - isEVMCompatibleChain(widget.exchangeTradeViewModel.sendViewModel.walletType) - ? S.of(bottomSheetContext).send_estimated_fee - : S.of(bottomSheetContext).send_fee, - feeValue: widget - .exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeFormatted, - feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel - .pendingTransactionFeeFiatAmountFormatted, - outputs: widget.exchangeTradeViewModel.sendViewModel.outputs, + amountValue: sendVM.amountParsingProxy + .getCryptoOutputAmount(amountValue, sendVM.selectedCryptoCurrency), + fiatAmountValue: sendVM.pendingTransactionFiatAmountFormatted, + fee: isEVMCompatibleChain(sendVM.walletType) + ? S.of(bottomSheetContext).send_estimated_fee + : S.of(bottomSheetContext).send_fee, + feeValue: "${sendVM.amountParsingProxy.getCryptoOutputAmount( + sendVM.pendingTransaction!.feeFormattedValue, + sendVM.selectedCryptoCurrency)} ${sendVM.amountParsingProxy + .getCryptoSymbol(sendVM.wallet.currency)}", + feeFiatAmount: sendVM.pendingTransactionFeeFiatAmountFormatted, + outputs: sendVM.outputs, onSlideActionComplete: () async { - if (bottomSheetContext.mounted) { - Navigator.of(bottomSheetContext).pop(true); - } - widget.exchangeTradeViewModel.sendViewModel.commitTransaction(context); + if (bottomSheetContext.mounted) Navigator.of(bottomSheetContext).pop(true); + + sendVM.commitTransaction(context); widget.exchangeTradeViewModel.registerSwapsXyzTransaction(); }, ); }, ); - if (result == null) widget.exchangeTradeViewModel.sendViewModel.dismissTransaction(); - + if (result == null) widget.exchangeTradeViewModel.sendViewModel.dismissTransaction(); } }); } diff --git a/lib/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart b/lib/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart index 85be26c924..347498ca7c 100644 --- a/lib/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart +++ b/lib/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart @@ -217,7 +217,7 @@ class FeeSelectionWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - '${output.estimatedFee} ${feesViewModel.currency}', + '${output.estimatedFee} ${feesViewModel.amountParsingProxy.getCryptoSymbol(feesViewModel.currency)}', style: Theme.of(context).textTheme.bodySmall?.copyWith( fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface, diff --git a/lib/src/screens/integrations/deuro/savings_page.dart b/lib/src/screens/integrations/deuro/savings_page.dart index 57192f2a96..f7a390d367 100644 --- a/lib/src/screens/integrations/deuro/savings_page.dart +++ b/lib/src/screens/integrations/deuro/savings_page.dart @@ -178,7 +178,7 @@ class DEuroSavingsPage extends BasePage { titleText: title, walletType: WalletType.ethereum, titleIconPath: CryptoCurrency.deuro.iconPath, - currency: CryptoCurrency.deuro, + currencyTitle: CryptoCurrency.deuro.title, amount: S.of(bottomSheetContext).send_amount, amountValue: _dEuroViewModel.actionType == DEuroActionType.reinvest ? _dEuroViewModel.accruedInterestFormated @@ -213,7 +213,7 @@ class DEuroSavingsPage extends BasePage { titleText: S.of(bottomSheetContext).approve_tokens, walletType: WalletType.ethereum, titleIconPath: CryptoCurrency.deuro.iconPath, - currency: CryptoCurrency.deuro, + currencyTitle: CryptoCurrency.deuro.title, amount: S.of(bottomSheetContext).send_amount, amountValue: tx.amountFormatted, fiatAmountValue: "", diff --git a/lib/src/screens/receive/widgets/currency_input_field.dart b/lib/src/screens/receive/widgets/currency_input_field.dart index 2a061c4d02..a5b0800e28 100644 --- a/lib/src/screens/receive/widgets/currency_input_field.dart +++ b/lib/src/screens/receive/widgets/currency_input_field.dart @@ -184,7 +184,7 @@ class CurrencyAmountTextField extends StatelessWidget { inputFormatters: [ FilteringTextInputFormatter.deny(RegExp('[\\-|\\ ]')), ], - hintText: hintText ?? '0.0000', + hintText: hintText ?? (selectedCurrencyDecimals == 0 ? '0' : '0.0000'), fillColor: fillColor, textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith( fontSize: 16, @@ -198,8 +198,13 @@ class CurrencyAmountTextField extends StatelessWidget { ), validator: isAmountEditable ? currencyValueValidator : null, onChanged: (value) { - final sanitized = + var sanitized = value.replaceAll(',', '.').withMaxDecimals(selectedCurrencyDecimals); + + if (selectedCurrencyDecimals == 0) { + sanitized = sanitized.replaceAll('.', ''); + } + if (sanitized != amountController.text) { // Update text while preserving a sane cursor position to avoid auto-selection amountController.value = amountController.value.copyWith( diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index 6a40850b64..7d38c973a6 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -204,7 +204,7 @@ class QRWidget extends StatelessWidget { borderWidth: 0.0, selectedCurrency: _currencyName, selectedCurrencyDecimals: - addressListViewModel.selectedCurrency.decimals, + addressListViewModel.selectedCurrencyDecimals, amountFocusNode: amountTextFieldFocusNode, amountController: amountController, padding: EdgeInsets.only(top: 20, left: _width / 4), @@ -283,6 +283,7 @@ class QRWidget extends StatelessWidget { String get _currencyName { if (addressListViewModel.selectedCurrency is CryptoCurrency) { + if (addressListViewModel.useSatoshi) return "SATS"; return (addressListViewModel.selectedCurrency as CryptoCurrency).title.toUpperCase(); } return addressListViewModel.selectedCurrency.name.toUpperCase(); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index f5b151482b..10c7cf47e7 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -570,14 +570,20 @@ class SendPage extends BasePage { isSlideActionEnabled: sendViewModel.isReadyForSend, walletType: sendViewModel.walletType, titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath, - currency: sendViewModel.selectedCryptoCurrency, + currencyTitle: sendViewModel.amountParsingProxy + .getCryptoSymbol(sendViewModel.selectedCryptoCurrency), amount: S.of(bottomSheetContext).send_amount, - amountValue: sendViewModel.pendingTransaction!.amountFormatted, + amountValue: sendViewModel.amountParsingProxy.getCryptoOutputAmount( + sendViewModel.pendingTransaction!.amountFormatted, + sendViewModel.selectedCryptoCurrency), fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted, fee: isEVMCompatibleChain(sendViewModel.walletType) ? S.of(bottomSheetContext).send_estimated_fee : S.of(bottomSheetContext).send_fee, - feeValue: sendViewModel.pendingTransaction!.feeFormatted, + feeValue: "${sendViewModel.amountParsingProxy.getCryptoOutputAmount( + sendViewModel.pendingTransaction!.feeFormattedValue, + sendViewModel.selectedCryptoCurrency)} ${sendViewModel.amountParsingProxy + .getCryptoSymbol(sendViewModel.wallet.currency)}", feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted, outputs: sendViewModel.outputs, onSlideActionComplete: () async { diff --git a/lib/src/screens/send/widgets/send_card.dart b/lib/src/screens/send/widgets/send_card.dart index 007b90054c..2ba38f5554 100644 --- a/lib/src/screens/send/widgets/send_card.dart +++ b/lib/src/screens/send/widgets/send_card.dart @@ -508,8 +508,8 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin Padding( padding: EdgeInsets.only(top: 14), @@ -790,8 +786,12 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin with AutomaticKeepAliveClientMixin output.fiatAmount, (String amount) { @@ -835,8 +836,11 @@ class SendCardState extends State with AutomaticKeepAliveClientMixin mode.title, isGridView: false, ), + if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting) + SettingsPickerCell( + title: "Bitcoin Amount Display", // ToDo (Konsti) localize + items: BitcoinAmountDisplayMode.all, + selectedItem: _displaySettingsViewModel.displayAmountsInSatoshi, + onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi, + displayItem: (mode) => mode.title, + isGridView: false, + ), //if (!isHaven) it does not work correctly if (!_displaySettingsViewModel.disabledFiatApiMode) SettingsPickerCell( diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart index 66866bf2ae..e4ac599f72 100644 --- a/lib/src/screens/transaction_details/rbf_details_page.dart +++ b/lib/src/screens/transaction_details/rbf_details_page.dart @@ -194,7 +194,8 @@ class RBFDetailsPage extends BasePage { walletType: transactionDetailsViewModel.sendViewModel.walletType, titleIconPath: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency.iconPath, - currency: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency, + currencyTitle: + transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency.title, amount: S.of(bottomSheetContext).send_amount, amountValue: transactionDetailsViewModel.sendViewModel.pendingTransaction!.amountFormatted, diff --git a/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart b/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart index 1f9b09d523..6e6f593902 100644 --- a/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart +++ b/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart @@ -5,7 +5,6 @@ import 'package:cake_wallet/utils/address_formatter.dart'; import 'package:cake_wallet/utils/image_utill.dart'; import 'package:cake_wallet/view_model/cake_pay/cake_pay_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/send/output.dart'; -import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/pending_transaction.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -23,7 +22,7 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet { VoidCallback? onSlideActionComplete, bool isSlideActionEnabled = true, String? accessibleNavigationModeSlideActionButtonText, - required this.currency, + required this.currencyTitle, this.paymentId, this.paymentIdValue, this.expirationTime, @@ -54,7 +53,7 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet { accessibleNavigationModeSlideActionButtonText, key: key); - final CryptoCurrency currency; + final String currencyTitle; final String? paymentId; final String? paymentIdValue; final String? expirationTime; @@ -127,7 +126,7 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet { ), StandardTile( itemTitle: amount, - itemValue: '$amountValue ${currency.title}', + itemValue: '$amountValue $currencyTitle', itemTitleTextStyle: itemTitleTextStyle, itemSubTitle: fiatAmountValue, itemSubTitleTextStyle: itemSubTitleTextStyle, @@ -159,7 +158,7 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet { final batchContactTitle = '${index + 1}/${outputs.length} - ${contactName.isEmpty ? 'Address' : contactName}'; final _address = item.isParsedAddress ? item.extractedAddress : item.address; - final _amount = item.cryptoAmount.replaceAll(',', '.') + ' ${currency.title}'; + final _amount = '${item.cryptoAmount.replaceAll(',', '.')} $currencyTitle'; return isBatchSending || (contactName.isNotEmpty && !isCakePayName) ? ExpansionAddressTile( contactType: isOpenCryptoPay ? 'Open CryptoPay' : S.of(context).contact, @@ -194,7 +193,7 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet { contactType: 'Change', name: S.of(context).send_change_to_you, address: change!.address, - amount: change!.amount + ' ${currency.title}', + amount: '${change!.amount} $currencyTitle', isBatchSending: true, walletType: walletType, itemTitleTextStyle: itemTitleTextStyle, diff --git a/lib/store/app_store.dart b/lib/store/app_store.dart index c3e7cc4562..2de3e8f24c 100644 --- a/lib/store/app_store.dart +++ b/lib/store/app_store.dart @@ -1,4 +1,5 @@ +import 'package:cake_wallet/core/amount_parsing_proxy.dart'; import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; @@ -22,12 +23,18 @@ part 'app_store.g.dart'; class AppStore = AppStoreBase with _$AppStore; abstract class AppStoreBase with Store { - AppStoreBase( - {required this.authenticationStore, - required this.walletList, - required this.settingsStore, - required this.nodeListStore, - required this.themeStore}); + AppStoreBase({ + required this.authenticationStore, + required this.walletList, + required this.settingsStore, + required this.nodeListStore, + required this.themeStore, + }) : _amountParsingProxy = AmountParsingProxy(settingsStore.displayAmountsInSatoshi) { + reaction( + (_) => settingsStore.displayAmountsInSatoshi, + (value) => _amountParsingProxy = AmountParsingProxy(value), + ); + } AuthenticationStore authenticationStore; @@ -42,6 +49,9 @@ abstract class AppStoreBase with Store { ThemeStore themeStore; + AmountParsingProxy _amountParsingProxy; + AmountParsingProxy get amountParsingProxy => _amountParsingProxy; + @action Future changeCurrentWallet( WalletBase, TransactionInfo> wallet) async { diff --git a/lib/store/dashboard/trades_store.dart b/lib/store/dashboard/trades_store.dart index d0a4592e33..b32ae1f885 100644 --- a/lib/store/dashboard/trades_store.dart +++ b/lib/store/dashboard/trades_store.dart @@ -1,17 +1,17 @@ import 'dart:async'; import 'package:cake_wallet/exchange/trade.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/store/settings_store.dart'; part 'trades_store.g.dart'; class TradesStore = TradesStoreBase with _$TradesStore; abstract class TradesStoreBase with Store { - TradesStoreBase({required this.tradesSource, required this.settingsStore}) + TradesStoreBase({required this.tradesSource, required this.appStore}) : trades = [] { _onTradesChanged = tradesSource.watch().listen((_) async => await updateTradeList()); updateTradeList(); @@ -19,7 +19,7 @@ abstract class TradesStoreBase with Store { Box tradesSource; StreamSubscription? _onTradesChanged; - SettingsStore settingsStore; + AppStore appStore; @observable List trades; @@ -34,7 +34,7 @@ abstract class TradesStoreBase with Store { Future updateTradeList() async => trades = tradesSource.values .map((trade) => TradeListItem( trade: trade, - settingsStore: settingsStore, + appStore: appStore, key: ValueKey('trade_list_item_${trade.id}_key'), )) .toList(); diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 42809cc3e9..85876e5f60 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -12,6 +12,7 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/entities/action_list_display_mode.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/balance_display_mode.dart'; +import 'package:cake_wallet/entities/bitcoin_amount_display_mode.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; import 'package:cake_wallet/entities/country.dart'; import 'package:cake_wallet/entities/default_settings_migration.dart'; @@ -90,6 +91,7 @@ abstract class SettingsStoreBase with Store { required this.deviceName, required Map nodes, required Map powNodes, + required this.displayAmountsInSatoshi, required this.shouldShowYatPopup, required this.shouldShowDEuroDisclaimer, required this.shouldShowRepWarning, @@ -427,6 +429,11 @@ abstract class SettingsStoreBase with Store { (BalanceDisplayMode mode) => sharedPreferences.setInt( PreferencesKey.currentBalanceDisplayModeKey, mode.serialize())); + reaction( + (_) => displayAmountsInSatoshi, + (BitcoinAmountDisplayMode displayAmountsInSatoshi) => sharedPreferences.setInt( + PreferencesKey.displayAmountsInSatoshi, displayAmountsInSatoshi.raw)); + reaction((_) => currentSyncMode, (SyncMode syncMode) { sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode.type.index); FlutterDaemon().startBackgroundSync(syncMode.frequency.inMinutes); @@ -720,6 +727,9 @@ abstract class SettingsStoreBase with Store { @observable BalanceDisplayMode balanceDisplayMode; + @observable + BitcoinAmountDisplayMode displayAmountsInSatoshi; + @observable FiatApiMode fiatApiMode; @@ -1044,6 +1054,8 @@ abstract class SettingsStoreBase with Store { final currentBalanceDisplayMode = BalanceDisplayMode.deserialize( raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!); + final displayAmountsInSatoshi = BitcoinAmountDisplayMode.deserialize( + raw: sharedPreferences.getInt(PreferencesKey.displayAmountsInSatoshi) ?? 0); // FIX-ME: Check for which default value we should have here final shouldSaveRecipientAddress = sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false; @@ -1392,6 +1404,7 @@ abstract class SettingsStoreBase with Store { powNodes: powNodes, appVersion: packageInfo.version, deviceName: deviceName, + displayAmountsInSatoshi: displayAmountsInSatoshi, isBitcoinBuyEnabled: isBitcoinBuyEnabled, initialFiatCurrency: currentFiatCurrency, initialCakePayCountry: currentCakePayCountry, diff --git a/lib/view_model/buy/buy_sell_view_model.dart b/lib/view_model/buy/buy_sell_view_model.dart index 76e6e9edf2..0f2554ebc9 100644 --- a/lib/view_model/buy/buy_sell_view_model.dart +++ b/lib/view_model/buy/buy_sell_view_model.dart @@ -79,11 +79,13 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S } double get amount { - final formattedFiatAmount = double.tryParse(fiatAmount) ?? 200.0; - final formattedCryptoAmount = - double.tryParse(cryptoAmount) ?? (cryptoCurrency == CryptoCurrency.btc ? 0.001 : 1); + final formattedFiatAmount = double.tryParse(fiatAmount); + var formattedCryptoAmount = double.tryParse( + _appStore.amountParsingProxy.getCryptoInputAmount(cryptoAmount, cryptoCurrency)); - return isBuyAction ? formattedFiatAmount : formattedCryptoAmount; + return isBuyAction + ? formattedFiatAmount ?? 200.0 + : formattedCryptoAmount ?? (cryptoCurrency == CryptoCurrency.btc ? 0.001 : 1); } final AppStore _appStore; @@ -164,6 +166,9 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S ? (buySellQuotState as BuySellQuotFailed).errorMessage : null; + @computed + bool get useSatoshi => _appStore.amountParsingProxy.useSatoshi(cryptoCurrency); + @action void reset() { cryptoCurrency = wallet.currency; @@ -215,11 +220,13 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S } if (bestRateQuote != null) { + final amount = enteredAmount / bestRateQuote!.rate; + _cryptoNumberFormat.maximumFractionDigits = cryptoCurrency.decimals; - cryptoAmount = _cryptoNumberFormat - .format(enteredAmount / bestRateQuote!.rate) - .toString() - .replaceAll(RegExp('\\,'), ''); + cryptoAmount = _appStore.amountParsingProxy.getCryptoOutputAmount( + _cryptoNumberFormat.format(amount).replaceAll(RegExp('\\,'), ''), + cryptoCurrency, + ); } else { await calculateBestRate(); } @@ -227,7 +234,7 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S @action Future changeCryptoAmount({required String amount}) async { - cryptoAmount = amount; + cryptoAmount = _appStore.amountParsingProxy.getCryptoInputAmount(amount, cryptoCurrency); if (amount.isEmpty) { fiatAmount = ''; @@ -355,12 +362,11 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S Future _getAvailablePaymentTypes() async { paymentMethodState = PaymentMethodLoading(); selectedPaymentMethod = null; - final result = await Future.wait(providerList.map((element) => element - .getAvailablePaymentTypes(fiatCurrency.title, cryptoCurrency, isBuyAction) - .timeout( - Duration(seconds: 10), - onTimeout: () => [], - ))); + final result = await Future.wait(providerList.map((element) => + element.getAvailablePaymentTypes(fiatCurrency.title, cryptoCurrency, isBuyAction).timeout( + Duration(seconds: 10), + onTimeout: () => [], + ))); final List tempPaymentMethods = []; @@ -395,11 +401,11 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S final List validProviders = providerList.where((provider) { if (isBuyAction) { - return provider.supportedCryptoList.any((pair) => - pair.from == cryptoCurrency && pair.to == fiatCurrency); + return provider.supportedCryptoList + .any((pair) => pair.from == cryptoCurrency && pair.to == fiatCurrency); } else { - return provider.supportedFiatList.any((pair) => - pair.from == fiatCurrency && pair.to == cryptoCurrency); + return provider.supportedFiatList + .any((pair) => pair.from == fiatCurrency && pair.to == cryptoCurrency); } }).toList(); @@ -445,10 +451,11 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S return true; }).toList(); - final List successRateQuotes = validQuotes.where((element) => - element.provider is OnRamperBuyProvider && - element.recommendations.contains(ProviderRecommendation.successRate) - ).toList(); + final List successRateQuotes = validQuotes + .where((element) => + element.provider is OnRamperBuyProvider && + element.recommendations.contains(ProviderRecommendation.successRate)) + .toList(); for (final quote in successRateQuotes) { if (!uniqueProviderQuotes.contains(quote)) { @@ -495,7 +502,8 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S if (e.toString().contains("403")) { buySellQuotState = BuySellQuotFailed(errorMessage: "Using Tor is not supported"); } else { - buySellQuotState = BuySellQuotFailed(errorMessage: "Something went wrong please try again later"); + buySellQuotState = + BuySellQuotFailed(errorMessage: "Something went wrong please try again later"); } } } diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 552d318e4a..91a7655471 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -202,11 +202,11 @@ abstract class BalanceViewModelBase with Store { String additionalBalance(CryptoCurrency cryptoCurrency) { final balance = _currencyBalance(cryptoCurrency); - if (displayMode == BalanceDisplayMode.hiddenBalance) { + if (displayMode == BalanceDisplayMode.hiddenBalance || balance.additional == 0) { return '0.0'; } - return balance.formattedAdditionalBalance; + return cryptoCurrency.formatAmount(BigInt.from(balance.additional)); } @computed @@ -237,51 +237,44 @@ abstract class BalanceViewModelBase with Store { // throw Exception('Price is null for: $key'); // } - final additionalFiatBalance = isFiatDisabled + final availableFiatBalance = isFiatDisabled ? '' - : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedAdditionalBalance)); + : '$fiatCurrency ${_getFiatBalance(price: price, cryptoAmount: key.formatAmount(BigInt.from(value.available)))}'; - final availableFiatBalance = isFiatDisabled + final additionalFiatBalance = isFiatDisabled ? '' - : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedAvailableBalance)); + : '$fiatCurrency ${_getFiatBalance(price: price, cryptoAmount: key.formatAmount(BigInt.from(value.additional)))}'; final frozenFiatBalance = isFiatDisabled ? '' - : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(value))); + : '$fiatCurrency ${_getFiatBalance(price: price, cryptoAmount: value.frozen != null ? key.formatAmount(BigInt.from(value.frozen!)) : null)}'; - final secondAdditionalFiatBalance = isFiatDisabled + final secondAvailableFiatBalance = isFiatDisabled ? '' - : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAdditionalBalance)); + : '$fiatCurrency ${_getFiatBalance(price: price, cryptoAmount: value.secondAvailable != null ? key.formatAmount(BigInt.from(value.secondAvailable!)) : null)}'; - final secondAvailableFiatBalance = isFiatDisabled + final secondAdditionalFiatBalance = isFiatDisabled ? '' - : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAvailableBalance)); + : '$fiatCurrency ${_getFiatBalance(price: price, cryptoAmount: value.secondAdditional != null ? key.formatAmount(BigInt.from(value.secondAdditional!)) : null)}'; return MapEntry( - key, - BalanceRecord( - availableBalance: value.formattedAvailableBalance, - additionalBalance: value.formattedAdditionalBalance, - frozenBalance: getFormattedFrozenBalance(value), - secondAvailableBalance: value.formattedSecondAvailableBalance, - secondAdditionalBalance: value.formattedSecondAdditionalBalance, - fiatAdditionalBalance: additionalFiatBalance, - fiatAvailableBalance: availableFiatBalance, - fiatFrozenBalance: frozenFiatBalance, - fiatSecondAvailableBalance: secondAvailableFiatBalance, - fiatSecondAdditionalBalance: secondAdditionalFiatBalance, - asset: key, - formattedAssetTitle: _formatterAsset(key))); + key, + BalanceRecord( + availableBalance: _getFormattedCryptoAmount(key, value.available), + fiatAvailableBalance: availableFiatBalance, + additionalBalance: _getFormattedCryptoAmount(key, value.additional), + fiatAdditionalBalance: additionalFiatBalance, + frozenBalance: + (value.frozen ?? 0) > 0 ? _getFormattedCryptoAmount(key, value.frozen) : '', + fiatFrozenBalance: frozenFiatBalance, + secondAvailableBalance: _getFormattedCryptoAmount(key, value.secondAvailable), + fiatSecondAvailableBalance: secondAvailableFiatBalance, + secondAdditionalBalance: _getFormattedCryptoAmount(key, value.secondAdditional), + fiatSecondAdditionalBalance: secondAdditionalFiatBalance, + asset: key, + formattedAssetTitle: _formatterAsset(key), + ), + ); }); } @@ -331,6 +324,12 @@ abstract class BalanceViewModelBase with Store { return false; } + String _getFormattedCryptoAmount(CryptoCurrency cryptoCurrency, int? amount) { + if (amount == null) return ""; + + return appStore.amountParsingProxy.getCryptoString(amount, cryptoCurrency); + } + @computed List get formattedBalances { final balance = balances.values.toList(); @@ -452,7 +451,4 @@ abstract class BalanceViewModelBase with Store { return asset.toString(); } } - - String getFormattedFrozenBalance(Balance walletBalance) => - walletBalance.formattedUnAvailableBalance; } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 50e8d62b7d..f3d6bab8da 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -43,7 +43,6 @@ import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; import 'package:cake_wallet/view_model/settings/sync_mode.dart'; import 'package:cryptography/cryptography.dart'; import 'package:cw_core/balance.dart'; -import 'package:cw_core/cake_hive.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_history.dart'; @@ -230,7 +229,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('monero_transaction_history_item_${transaction.id}_key'), ), ), @@ -260,7 +259,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('wownero_transaction_history_item_${transaction.id}_key'), ), ), @@ -274,7 +273,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('${_wallet.type.name}_transaction_history_item_${transaction.id}_key'), ), ), @@ -362,7 +361,7 @@ abstract class DashboardViewModelBase with Store { transactions.addAll(relevantTxs.map((tx) => TransactionListItem( transaction: tx, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'), ))); } finally { @@ -973,7 +972,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('${wallet.type.name}_transaction_history_item_${transaction.id}_key'), ), ), @@ -1025,7 +1024,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('monero_transaction_history_item_${transaction.id}_key'), ), ), @@ -1045,7 +1044,7 @@ abstract class DashboardViewModelBase with Store { (transaction) => TransactionListItem( transaction: transaction, balanceViewModel: balanceViewModel, - settingsStore: appStore.settingsStore, + appStore: appStore, key: ValueKey('wownero_transaction_history_item_${transaction.id}_key'), ), ), diff --git a/lib/view_model/dashboard/trade_list_item.dart b/lib/view_model/dashboard/trade_list_item.dart index 973f5b76f0..9ea0cb6bbf 100644 --- a/lib/view_model/dashboard/trade_list_item.dart +++ b/lib/view_model/dashboard/trade_list_item.dart @@ -1,26 +1,29 @@ -import 'package:cake_wallet/entities/balance_display_mode.dart'; -import 'package:cake_wallet/exchange/trade.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import "package:cake_wallet/entities/balance_display_mode.dart"; +import "package:cake_wallet/exchange/trade.dart"; +import "package:cake_wallet/store/app_store.dart"; +import "package:cake_wallet/view_model/dashboard/action_list_item.dart"; class TradeListItem extends ActionListItem { TradeListItem({ required this.trade, - required this.settingsStore, + required this.appStore, required super.key, }); final Trade trade; - final SettingsStore settingsStore; + final AppStore appStore; - BalanceDisplayMode get displayMode => settingsStore.balanceDisplayMode; + BalanceDisplayMode get displayMode => appStore.settingsStore.balanceDisplayMode; - String get tradeFormattedAmount => - displayMode == BalanceDisplayMode.hiddenBalance ? '---' : trade.amountFormatted(); + String get tradeFormattedAmount => displayMode == BalanceDisplayMode.hiddenBalance + ? "---" + : appStore.amountParsingProxy.getCryptoOutputAmount(trade.amountFormatted(), trade.from!); + + String get tradeFormattedReceiveAmount => displayMode == BalanceDisplayMode.hiddenBalance + ? "---" + : appStore.amountParsingProxy + .getCryptoOutputAmount(trade.receiveAmountFormatted(), trade.to!); - String get tradeFormattedReceiveAmount => - displayMode == BalanceDisplayMode.hiddenBalance ? '---' : trade.receiveAmountFormatted(); - @override DateTime get date => trade.createdAt!; } diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart index 33df3ea241..5847bb0438 100644 --- a/lib/view_model/dashboard/transaction_list_item.dart +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -9,13 +9,13 @@ import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/solana/solana.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/tron/tron.dart'; import 'package:cake_wallet/wownero/wownero.dart'; import 'package:cake_wallet/zano/zano.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; -import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; @@ -28,17 +28,17 @@ class TransactionListItem extends ActionListItem with Keyable { TransactionListItem({ required this.transaction, required this.balanceViewModel, - required this.settingsStore, + required AppStore appStore, required super.key, - }); + }) : _appStore = appStore; final TransactionInfo transaction; final BalanceViewModel balanceViewModel; - final SettingsStore settingsStore; + final AppStore _appStore; double get price => balanceViewModel.price; - FiatCurrency get fiatCurrency => settingsStore.fiatCurrency; + FiatCurrency get fiatCurrency => _appStore.settingsStore.fiatCurrency; BalanceDisplayMode get displayMode => balanceViewModel.displayMode; @@ -51,7 +51,13 @@ class TransactionListItem extends ActionListItem with Keyable { balanceViewModel.wallet.type == WalletType.tron; String get formattedCryptoAmount { - return displayMode == BalanceDisplayMode.hiddenBalance ? '---' : transaction.amountFormatted(); + if (displayMode == BalanceDisplayMode.hiddenBalance) return '---'; + if (balanceViewModel.wallet.type == WalletType.bitcoin) { + final isLightning = (transaction.additionalInfo["isLightning"] as bool?) ?? false; + final crypto = isLightning ? CryptoCurrency.btcln : CryptoCurrency.btc; + return '${_appStore.amountParsingProxy.getCryptoString(transaction.amount, crypto)} ${_appStore.amountParsingProxy.getCryptoSymbol(crypto)}'; + } + return transaction.amountFormatted(); } String get formattedTitle { diff --git a/lib/view_model/exchange/exchange_trade_view_model.dart b/lib/view_model/exchange/exchange_trade_view_model.dart index fec47f3f35..c0a8aaf1fb 100644 --- a/lib/view_model/exchange/exchange_trade_view_model.dart +++ b/lib/view_model/exchange/exchange_trade_view_model.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:cake_wallet/core/amount_parsing_proxy.dart'; import 'package:cake_wallet/core/payment_uris.dart'; import 'package:cake_wallet/entities/calculate_fiat_amount.dart'; import 'package:cake_wallet/entities/fiat_currency.dart'; @@ -18,7 +19,6 @@ import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart'; import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart'; import 'package:cake_wallet/exchange/trade.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/arbitrum/arbitrum.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; @@ -104,6 +104,8 @@ abstract class ExchangeTradeViewModelBase with Store { late Output output; + AmountParsingProxy get _amountParsingProxy => sendViewModel.amountParsingProxy; + @observable Trade trade; @@ -116,18 +118,18 @@ abstract class ExchangeTradeViewModelBase with Store { wallet.currency != trade.from; String get extraInfo => trade.extraId != null && trade.extraId!.isNotEmpty - ? '\n\n' + S.current.exchange_extra_info - : ''; + ? "\n\n${S.current.exchange_extra_info}" + : ""; @computed String get pendingTransactionFiatAmountValueFormatted => sendViewModel.isFiatDisabled - ? '' - : sendViewModel.pendingTransactionFiatAmount + ' ' + sendViewModel.fiat.title; + ? "" + : "${sendViewModel.pendingTransactionFiatAmount} ${sendViewModel.fiat.title}"; @computed String get pendingTransactionFeeFiatAmountFormatted => sendViewModel.isFiatDisabled - ? '' - : sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title; + ? "" + : "${sendViewModel.pendingTransactionFeeFiatAmount} ${sendViewModel.fiat.title}"; @observable ObservableList items; @@ -244,12 +246,12 @@ abstract class ExchangeTradeViewModelBase with Store { void _updateItems() { final trade = tradesStore.trade!; - final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom; + final tradeFrom = trade.fromRaw >= 0 ? trade.from : trade.userCurrencyFrom; final tradeTo = trade.toRaw >= 0 ? trade.to : trade.userCurrencyTo; - final tagFrom = tradeFrom?.tag != null ? '${tradeFrom!.tag}' + ' ' : ''; - final tagTo = tradeTo?.tag != null ? '${tradeTo!.tag}' + ' ' : ''; + final tagFrom = tradeFrom?.tag != null ? "${tradeFrom!.tag} " : ""; + final tagTo = tradeTo?.tag != null ? "${tradeTo!.tag} " : ""; items.clear(); @@ -257,7 +259,7 @@ abstract class ExchangeTradeViewModelBase with Store { items.add( ExchangeTradeItem( title: "${trade.provider.title} ${S.current.id}", - data: '${trade.id}', + data: "${trade.id}", isCopied: true, isReceiveDetail: true, isExternalSendDetail: false, @@ -268,21 +270,23 @@ abstract class ExchangeTradeViewModelBase with Store { items.addAll([ ExchangeTradeItem( title: S.current.amount, - data: '${trade.amount} ${tradeFrom}', + data: + "${_amountParsingProxy.getCryptoOutputAmount(trade.amount, tradeFrom!)} ${_amountParsingProxy.getCryptoSymbol(tradeFrom)}", isCopied: false, isReceiveDetail: false, isExternalSendDetail: true, ), ExchangeTradeItem( - title: S.current.you_will_receive_estimated_amount + ':', - data: '${tradesStore.trade?.receiveAmount} ${tradeTo}', + title: "${S.current.you_will_receive_estimated_amount}:", + data: + "${_amountParsingProxy.getCryptoOutputAmount(tradesStore.trade?.receiveAmount ?? "0", tradeTo!)} ${_amountParsingProxy.getCryptoSymbol(tradeTo)}", isCopied: true, isReceiveDetail: true, isExternalSendDetail: false, ), ExchangeTradeItem( - title: S.current.send_to_this_address('${tradeFrom}', tagFrom) + ':', - data: trade.inputAddress ?? '', + title: "${S.current.send_to_this_address("${tradeFrom}", tagFrom)}:", + data: trade.inputAddress ?? "", isCopied: false, isReceiveDetail: false, isExternalSendDetail: true, @@ -295,24 +299,25 @@ abstract class ExchangeTradeViewModelBase with Store { if (isExtraIdExist) { final title = tradeFrom == CryptoCurrency.xrp ? S.current.destination_tag - : tradeFrom == CryptoCurrency.xlm || tradeFrom == CryptoCurrency.ton + : [CryptoCurrency.xlm, CryptoCurrency.ton].contains(tradeFrom) ? S.current.memo : S.current.extra_id; items.add( ExchangeTradeItem( - title: title, - data: trade.extraId ?? '', - isCopied: true, - isReceiveDetail: !isExtraIdExist, - isExternalSendDetail: isExtraIdExist), + title: title, + data: trade.extraId ?? "", + isCopied: true, + isReceiveDetail: !isExtraIdExist, + isExternalSendDetail: isExtraIdExist, + ), ); } items.add( ExchangeTradeItem( - title: S.current.arrive_in_this_address('${tradeTo}', tagTo) + ':', - data: trade.payoutAddress ?? '', + title: "${S.current.arrive_in_this_address("${tradeTo}", tagTo)}:", + data: trade.payoutAddress ?? "", isCopied: true, isReceiveDetail: true, isExternalSendDetail: false, diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index b598bf8bcb..52055e3c1b 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -55,7 +55,6 @@ import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/utils/proxy_wrapper.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; -import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -71,18 +70,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with } ExchangeViewModelBase( - AppStore appStore, + this._appStore, this.trades, this._exchangeTemplateStore, this.tradesStore, - this._settingsStore, this.sharedPreferences, this.contactListViewModel, this.unspentCoinsListViewModel, this.feesViewModel, this.fiatConversionStore, - ) : _cryptoNumberFormat = NumberFormat(), - isSendAllEnabled = false, + ) : isSendAllEnabled = false, isFixedRateMode = false, isReceiveAmountEntered = false, depositAmount = '', @@ -97,11 +94,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with limits = Limits(min: 0, max: 0), tradeState = ExchangeTradeStateInitial(), limitsState = LimitsInitialState(), - receiveCurrency = appStore.wallet!.currency, - depositCurrency = appStore.wallet!.currency, + receiveCurrency = _appStore.wallet!.currency, + depositCurrency = _appStore.wallet!.currency, providerList = [], selectedProviders = ObservableList(), - super(appStore: appStore) { + super(appStore: _appStore) { _useTorOnly = _settingsStore.exchangeStatus == ExchangeApiMode.torOnly; _setProviders(); const excludeDepositCurrencies = [CryptoCurrency.btt]; @@ -357,9 +354,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @observable ObservableList depositCurrencies; - final NumberFormat _cryptoNumberFormat; - - final SettingsStore _settingsStore; + final AppStore _appStore; + SettingsStore get _settingsStore => _appStore.settingsStore; final ContactListViewModel contactListViewModel; @@ -370,6 +366,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with @observable double bestRate = 0.0; + @computed + bool get useSatoshiDeposit => _appStore.amountParsingProxy.useSatoshi(depositCurrency); + + @computed + bool get useSatoshisReceive => _appStore.amountParsingProxy.useSatoshi(receiveCurrency); + late Timer bestRateSync; final FiatConversionStore fiatConversionStore; @@ -436,7 +438,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with return; } - final _enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0; + final _enteredAmount = double.tryParse(_appStore.amountParsingProxy + .getCryptoInputAmount(amount.replaceAll(',', '.'), receiveCurrency)) ?? + 0; if (bestRate == 0) { depositAmount = S.current.fetching; @@ -444,12 +448,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with await calculateBestRate(); } - _cryptoNumberFormat.maximumFractionDigits = depositMaxDigits; - - depositAmount = _cryptoNumberFormat - .format(_enteredAmount / bestRate) - .toString() - .replaceAll(RegExp('\\,'), ''); + final amount_ = _enteredAmount / bestRate; + depositAmount = _appStore.amountParsingProxy.getCryptoOutputAmount( + amount_.toString().withMaxDecimals(depositCurrency.decimals), depositCurrency); } @action @@ -459,9 +460,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with if (price == null || price == 0.0) return; final crypto = _enteredAmount / price; - final receiveAmountTmp = _cryptoNumberFormat.format(crypto); + final receiveAmountTmp = crypto.toString().withMaxDecimals(receiveCurrency.decimals); if (receiveAmount != receiveAmountTmp) { - changeReceiveAmount(amount: receiveAmountTmp.withMaxDecimals(receiveCurrency.decimals)); + changeReceiveAmount(amount: receiveAmountTmp); } } @@ -479,7 +480,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with /// as it should remain exactly what the user set if (isFixedRateMode) return; - final _enteredAmount = double.tryParse(amount.replaceAll(',', '.')) ?? 0; + final _enteredAmount = double.tryParse(_appStore.amountParsingProxy + .getCryptoInputAmount(amount.replaceAll(',', '.'), depositCurrency)) ?? + 0; /// in case the best rate was not calculated yet if (bestRate == 0) { @@ -488,12 +491,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with await calculateBestRate(); } - _cryptoNumberFormat.maximumFractionDigits = receiveMaxDigits; - - receiveAmount = _cryptoNumberFormat - .format(bestRate * _enteredAmount) - .toString() - .replaceAll(RegExp('\\,'), ''); + final amount_ = _enteredAmount * bestRate; + receiveAmount = _appStore.amountParsingProxy.getCryptoOutputAmount( + amount_.toString().withMaxDecimals(receiveCurrency.decimals), receiveCurrency); } bool checkIfInputMeetsMinOrMaxCondition(String input) { @@ -513,7 +513,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with bestRate = 0.0; return; } - final amount = double.tryParse(isFixedRateMode ? receiveAmount : depositAmount) ?? + final amount = double.tryParse( + _appStore.amountParsingProxy.getCryptoInputAmount( + isFixedRateMode ? receiveAmount : depositAmount, + isFixedRateMode ? receiveCurrency : depositCurrency), + ) ?? initialAmountByAssets(isFixedRateMode ? receiveCurrency : depositCurrency); final validProvidersForAmount = _tradeAvailableProviders.where((provider) { @@ -639,7 +643,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with Future createTrade() async { if (isSendAllEnabled) { await calculateDepositAllAmount(); - final amount = double.tryParse(depositAmount); + final amount = double.tryParse(_appStore.amountParsingProxy + .getCryptoInputAmount(depositAmount.replaceAll(',', '.'), depositCurrency)); if (limits.min != null && amount != null && amount < limits.min!) { tradeState = TradeIsCreatedFailure( @@ -678,8 +683,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with final request = TradeRequest( fromCurrency: depositCurrency, toCurrency: receiveCurrency, - fromAmount: depositAmount.replaceAll(',', '.'), - toAmount: receiveAmount.replaceAll(',', '.'), + fromAmount: _appStore.amountParsingProxy + .getCryptoInputAmount(depositAmount.replaceAll(',', '.'), depositCurrency), + toAmount: _appStore.amountParsingProxy + .getCryptoInputAmount(receiveAmount.replaceAll(',', '.'), receiveCurrency), refundAddress: depositAddress, toAddress: receiveAddress, isFixedRate: isFixedRateMode, @@ -792,11 +799,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with wallet.type == WalletType.litecoin ? UnspentCoinType.nonMweb : UnspentCoinType.any, ); - changeDepositAmount(amount: wallet.formatCryptoAmount(amount.toString())); + changeDepositAmount( + amount: _appStore.amountParsingProxy.getCryptoString(amount, wallet.currency)); } else if (wallet.type == WalletType.monero) { final amount = await unspentCoinsListViewModel.getSendingBalance(UnspentCoinType.any); - changeDepositAmount(amount: wallet.formatCryptoAmount(amount.toString())); + changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.from(amount))); } } diff --git a/lib/view_model/send/fees_view_model.dart b/lib/view_model/send/fees_view_model.dart index 49b2120f2c..3492b00274 100644 --- a/lib/view_model/send/fees_view_model.dart +++ b/lib/view_model/send/fees_view_model.dart @@ -1,6 +1,6 @@ -import 'package:cake_wallet/arbitrum/arbitrum.dart'; import 'package:cake_wallet/base/base.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/core/amount_parsing_proxy.dart'; import 'package:cake_wallet/decred/decred.dart'; import 'package:cake_wallet/dogecoin/dogecoin.dart'; import 'package:cake_wallet/entities/priority_for_wallet_type.dart'; @@ -27,7 +27,7 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor FeesViewModelBase( AppStore appStore, this.balanceViewModel, - ) : _settingsStore = appStore.settingsStore, + ) : _appStore = appStore, super(appStore: appStore) { if (wallet.type == WalletType.bitcoin && _settingsStore.priority[wallet.type] == bitcoinTransactionPriorityCustom) { @@ -40,6 +40,10 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor } } + final AppStore _appStore; + SettingsStore get _settingsStore => _appStore.settingsStore; + AmountParsingProxy get amountParsingProxy => _appStore.amountParsingProxy; + @computed WalletType get walletType => wallet.type; CryptoCurrency get currency => wallet.currency; @@ -136,8 +140,6 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; - final SettingsStore _settingsStore; - @action void setTransactionPriority(TransactionPriority priority) => _settingsStore.priority[wallet.type] = priority; diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index 1fffe465f0..401c9fcd0d 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -1,4 +1,4 @@ -import 'dart:math'; +import 'dart:math' show min; import 'package:cake_wallet/arbitrum/arbitrum.dart'; import 'package:cake_wallet/base/base.dart'; @@ -17,6 +17,7 @@ import 'package:cake_wallet/polygon/polygon.dart'; import 'package:cake_wallet/reactions/wallet_connect.dart'; import 'package:cake_wallet/solana/solana.dart'; import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/tron/tron.dart'; @@ -24,6 +25,7 @@ import 'package:cake_wallet/wownero/wownero.dart'; import 'package:cake_wallet/zano/zano.dart'; import 'package:cw_core/balance.dart'; import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/currency_for_wallet_type.dart'; import 'package:cw_core/format_fixed.dart'; import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_info.dart'; @@ -40,8 +42,7 @@ const String cryptoNumberPattern = '0.0'; class Output = OutputBase with _$Output; abstract class OutputBase with Store { - OutputBase( - this._wallet, this._settingsStore, this._fiatConversationStore, this.cryptoCurrencyHandler) + OutputBase(this._wallet, this._appStore, this._fiatConversationStore, this.cryptoCurrencyHandler) : key = UniqueKey(), sendAll = false, cryptoAmount = '', @@ -62,6 +63,8 @@ abstract class OutputBase with Store { Key key; + bool get useSatoshi => _appStore.amountParsingProxy.useSatoshi(cryptoCurrencyHandler()); + @observable String fiatAmount; @@ -111,7 +114,7 @@ abstract class OutputBase with Store { case WalletType.litecoin: case WalletType.bitcoinCash: case WalletType.dogecoin: - _amount = bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount); + _amount = cryptoCurrencyHandler().parseAmount(_cryptoAmount).toInt(); break; case WalletType.decred: _amount = decred!.formatterStringDoubleToDecredAmount(_cryptoAmount); @@ -175,7 +178,12 @@ abstract class OutputBase with Store { switch (_wallet.type) { case WalletType.monero: - estimatedFee = monero!.formatterMoneroAmountToDouble(amount: fee).toString(); + case WalletType.wownero: + case WalletType.litecoin: + case WalletType.bitcoinCash: + case WalletType.dogecoin: + case WalletType.decred: + estimatedFee = walletTypeToCryptoCurrency(_wallet.type).formatAmount(BigInt.from(fee)); break; case WalletType.bitcoin: if (_settingsStore.priority[_wallet.type] == @@ -184,28 +192,17 @@ abstract class OutputBase with Store { _wallet, _settingsStore.customBitcoinFeeRate, formattedCryptoAmount); } - estimatedFee = bitcoin!.formatterBitcoinAmountToDouble(amount: fee).toString(); - break; - case WalletType.litecoin: - case WalletType.bitcoinCash: - case WalletType.dogecoin: - estimatedFee = bitcoin!.formatterBitcoinAmountToDouble(amount: fee).toString(); + estimatedFee = _appStore.amountParsingProxy.getCryptoString(fee, cryptoCurrencyHandler()); break; case WalletType.solana: estimatedFee = solana!.getEstimateFees(_wallet).toString(); break; - case WalletType.wownero: - estimatedFee = wownero!.formatterWowneroAmountToDouble(amount: fee).toString(); - break; case WalletType.zano: estimatedFee = zano! .formatterIntAmountToDouble( amount: fee, currency: cryptoCurrencyHandler(), forFee: true) .toString(); break; - case WalletType.decred: - estimatedFee = decred!.formatterDecredAmountToDouble(amount: fee).toString(); - break; case WalletType.tron: if (cryptoCurrencyHandler() == CryptoCurrency.trx) { estimatedFee = tron!.getTronNativeEstimatedFee(_wallet).toString(); @@ -268,25 +265,30 @@ abstract class OutputBase with Store { try { final currency = (isEVMCompatibleChain(_wallet.type) || - _wallet.type == WalletType.solana || - _wallet.type == WalletType.tron) + [WalletType.solana, WalletType.tron].contains(_wallet.type)) ? _wallet.currency : cryptoCurrencyHandler(); - final fiat = calculateFiatAmountRaw( - price: _fiatConversationStore.prices[currency]!, - cryptoAmount: double.parse(estimatedFee)); - return fiat; + + final cryptoAmount = + double.parse(_appStore.amountParsingProxy.getCryptoInputAmount(estimatedFee, currency)); + + return calculateFiatAmountRaw( + price: _fiatConversationStore.prices[currency]!, cryptoAmount: cryptoAmount); } catch (_) { return '0.00'; } } - WalletType get walletType => _wallet.type; - final CryptoCurrency Function() cryptoCurrencyHandler; @observable WalletBase, TransactionInfo> _wallet; - final SettingsStore _settingsStore; + + WalletType get walletType => _wallet.type; + + final CryptoCurrency Function() cryptoCurrencyHandler; final FiatConversionStore _fiatConversationStore; + final AppStore _appStore; + + SettingsStore get _settingsStore => _appStore.settingsStore; @action void setSendAll(String fullBalance) { @@ -318,10 +320,9 @@ abstract class OutputBase with Store { } @action + /// [setCryptoAmount] always takes in the canonical representation eg. Bitcoin and not Sats void setCryptoAmount(String amount) { - if (amount.toUpperCase() != S.current.all) { - sendAll = false; - } + if (amount.toUpperCase() != S.current.all) sendAll = false; cryptoAmount = amount; _updateFiatAmount(); @@ -336,10 +337,12 @@ abstract class OutputBase with Store { @action void _updateFiatAmount() { try { + var cryptoAmount_ = + sendAll ? cryptoFullBalance.replaceAll(",", ".") : cryptoAmount.replaceAll(',', '.'); + final fiat = calculateFiatAmount( price: _fiatConversationStore.prices[cryptoCurrencyHandler()]!, - cryptoAmount: - sendAll ? cryptoFullBalance.replaceAll(",", ".") : cryptoAmount.replaceAll(',', '.')); + cryptoAmount: cryptoAmount_); if (fiatAmount != fiat) { fiatAmount = fiat; } @@ -356,9 +359,7 @@ abstract class OutputBase with Store { _fiatConversationStore.prices[cryptoCurrencyHandler()]!) .toStringAsFixed(decimals); - if (cryptoAmount != crypto) { - cryptoAmount = crypto; - } + if (cryptoAmount != crypto) cryptoAmount = crypto; } catch (e) { cryptoAmount = ''; } @@ -396,7 +397,7 @@ extension OutputCopyWith on Output { }) { final clone = Output( _wallet, - _settingsStore, + _appStore, _fiatConversationStore, cryptoCurrencyHandler, ); diff --git a/lib/view_model/send/send_template_view_model.dart b/lib/view_model/send/send_template_view_model.dart index 29f576d666..db093485f8 100644 --- a/lib/view_model/send/send_template_view_model.dart +++ b/lib/view_model/send/send_template_view_model.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/view_model/send/template_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency_for_wallet_type.dart'; @@ -11,7 +12,6 @@ import 'package:cake_wallet/core/address_validator.dart'; import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart'; -import 'package:cake_wallet/store/settings_store.dart'; part 'send_template_view_model.g.dart'; @@ -19,12 +19,12 @@ class SendTemplateViewModel = SendTemplateViewModelBase with _$SendTemplateViewM abstract class SendTemplateViewModelBase with Store { final WalletBase _wallet; - final SettingsStore _settingsStore; + final AppStore _appStore; final SendTemplateStore _sendTemplateStore; final FiatConversionStore _fiatConversationStore; SendTemplateViewModelBase( - this._wallet, this._settingsStore, this._sendTemplateStore, this._fiatConversationStore) + this._wallet, this._appStore, this._sendTemplateStore, this._fiatConversationStore) : recipients = ObservableList() { addRecipient(); } @@ -35,7 +35,7 @@ abstract class SendTemplateViewModelBase with Store { void addRecipient() { recipients.add(TemplateViewModel( wallet: _wallet, - settingsStore: _settingsStore, + appStore: _appStore, fiatConversationStore: _fiatConversationStore)); } @@ -65,10 +65,10 @@ abstract class SendTemplateViewModelBase with Store { CryptoCurrency get cryptoCurrency => _wallet.currency; @computed - String get fiatCurrency => _settingsStore.fiatCurrency.title; + String get fiatCurrency => _appStore.settingsStore.fiatCurrency.title; @computed - int get fiatCurrencyDecimals => _settingsStore.fiatCurrency.decimals; + int get fiatCurrencyDecimals => _appStore.settingsStore.fiatCurrency.decimals; @computed ObservableList