import 'package:hash_wallet/bitcoin_cash/bitcoin_cash.dart'; import 'package:hash_wallet/core/amount_parsing_proxy.dart'; import 'package:hash_wallet/dogecoin/dogecoin.dart'; import 'package:hash_wallet/entities/priority_for_wallet_type.dart'; import 'package:hash_wallet/core/wallet_change_listener_view_model.dart'; import 'package:hash_wallet/evm/evm.dart'; import 'package:hash_wallet/monero/monero.dart'; import 'package:hash_wallet/store/app_store.dart'; import 'package:hash_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:mobx/mobx.dart'; import 'package:hash_wallet/entities/fiat_currency.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:hash_wallet/store/settings_store.dart'; import 'package:hash_wallet/bitcoin/bitcoin.dart'; import 'package:collection/collection.dart'; part 'fees_view_model.g.dart'; class FeesViewModel = FeesViewModelBase with _$FeesViewModel; abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Store { FeesViewModelBase( AppStore appStore, this.balanceViewModel, ) : _appStore = appStore, super(appStore: appStore) { final priority = _settingsStore.getPriority(wallet.type, chainId: wallet.chainId); if (wallet.type == WalletType.bitcoin && priority == bitcoinTransactionPriorityCustom) { setTransactionPriority(bitcoinTransactionPriorityMedium); } final priorities = priorityForWalletType(wallet.type); if (!priorities.contains(priority) && priorities.isNotEmpty) { _settingsStore.setPriority(wallet.type, priorities.first, chainId: wallet.chainId); } } final AppStore _appStore; SettingsStore get _settingsStore => _appStore.settingsStore; AmountParsingProxy get amountParsingProxy => _appStore.amountParsingProxy; @computed WalletType get walletType => wallet.type; CryptoCurrency get currency => wallet.currency; FiatCurrency get fiat => _settingsStore.fiatCurrency; bool get isFiatDisabled => balanceViewModel.isFiatDisabled; final BalanceViewModel balanceViewModel; TransactionPriority get transactionPriority { final priority = _settingsStore.getPriority(wallet.type, chainId: wallet.chainId); if (priority == null && hasFeesPriority) { throw Exception('Unexpected type ${wallet.type}'); } return priority!; } int? getCustomPriorityIndex(List priorities) { if (wallet.type == WalletType.bitcoin) { final customItem = priorities .firstWhereOrNull((element) => element == bitcoin!.getBitcoinTransactionPriorityCustom()); return customItem != null ? priorities.indexOf(customItem) : null; } return null; } int? get maxCustomFeeRate { if (wallet.type == WalletType.bitcoin) { return bitcoin!.getMaxCustomFeeRate(wallet); } return null; } bool get isLowFee { if (wallet.chainId == 42161) return false; switch (wallet.type) { case WalletType.monero: case WalletType.wownero: return transactionPriority == monero!.getMoneroTransactionPrioritySlow(); case WalletType.bitcoin: return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow(); case WalletType.litecoin: return transactionPriority == bitcoin!.getLitecoinTransactionPrioritySlow(); case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.bsc: return transactionPriority == evm!.getEVMTransactionPrioritySlow(); case WalletType.bitcoinCash: return transactionPriority == bitcoinCash!.getBitcoinCashTransactionPrioritySlow(); case WalletType.dogecoin: return transactionPriority == dogecoin!.getDogeCoinTransactionPrioritySlow(); case WalletType.none: case WalletType.nano: case WalletType.banano: case WalletType.arbitrum: return false; } } @computed int get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate; void set customBitcoinFeeRate(int value) => _settingsStore.customBitcoinFeeRate = value; @computed bool get hasFees => wallet.type != WalletType.nano && wallet.type != WalletType.banano; @computed bool get hasFeesPriority => wallet.type != WalletType.nano && wallet.type != WalletType.banano && wallet.chainId != 42161; // Wallet type is generic for all EVM chains, so we need to check the chainId @computed bool get isElectrumWallet => wallet.type == WalletType.bitcoin || wallet.type == WalletType.litecoin || wallet.type == WalletType.bitcoinCash || wallet.type == WalletType.dogecoin; String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name; @computed FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency; @action void setTransactionPriority(TransactionPriority priority) => _settingsStore.setPriority(wallet.type, priority, chainId: wallet.chainId); bool showAlertForCustomFeeRate() { if (wallet.type != WalletType.bitcoin || isLowFee) { return false; } if (transactionPriority != bitcoinTransactionPriorityCustom) { return false; } final mediumRate = bitcoin!.getFeeRate(wallet, bitcoinTransactionPriorityMedium); return customBitcoinFeeRate < mediumRate; } String displayFeeRate(dynamic priority, int? customValue) { final _priority = priority as TransactionPriority; if (wallet.type == WalletType.bitcoin) { final rate = bitcoin!.getFeeRate(wallet, _priority); return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate, customRate: customValue); } if (isElectrumWallet) { final rate = bitcoin!.getFeeRate(wallet, _priority); return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate); } return priority.toString(); } TransactionPriority get bitcoinTransactionPriorityCustom => bitcoin!.getBitcoinTransactionPriorityCustom(); TransactionPriority get bitcoinTransactionPriorityMedium => bitcoin!.getBitcoinTransactionPriorityMedium(); @action void setDefaultTransactionPriority() { switch (wallet.type) { case WalletType.monero: case WalletType.wownero: _settingsStore.setPriority(wallet.type, monero!.getMoneroTransactionPriorityAutomatic()); break; case WalletType.bitcoin: _settingsStore.setPriority(wallet.type, bitcoin!.getBitcoinTransactionPriorityMedium()); break; case WalletType.litecoin: _settingsStore.setPriority(wallet.type, bitcoin!.getLitecoinTransactionPriorityMedium()); break; case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.bsc: _settingsStore.setPriority( wallet.type, evm!.getDefaultTransactionPriority(), chainId: wallet.chainId, ); break; case WalletType.bitcoinCash: _settingsStore.setPriority(wallet.type, bitcoinCash!.getDefaultTransactionPriority()); break; case WalletType.dogecoin: _settingsStore.setPriority(wallet.type, dogecoin!.getDefaultTransactionPriority()); break; default: break; } } }