import 'package:hash_wallet/entities/balance_display_mode.dart'; import 'package:hash_wallet/entities/fiat_currency.dart'; import 'package:hash_wallet/evm/evm.dart'; import 'package:hash_wallet/generated/i18n.dart'; import 'package:hash_wallet/nano/nano.dart'; import 'package:hash_wallet/reactions/wallet_connect.dart'; import 'package:hash_wallet/store/app_store.dart'; import 'package:hash_wallet/wownero/wownero.dart'; import 'package:cw_core/crypto_amount_format.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_info.dart'; import 'package:hash_wallet/view_model/dashboard/action_list_item.dart'; import 'package:hash_wallet/monero/monero.dart'; import 'package:hash_wallet/bitcoin/bitcoin.dart'; import 'package:hash_wallet/entities/calculate_fiat_amount_raw.dart'; import 'package:hash_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cw_core/keyable.dart'; import 'package:cw_core/wallet_type.dart'; class TransactionListItem extends ActionListItem with Keyable { TransactionListItem({ required this.transaction, required this.balanceViewModel, required AppStore appStore, required super.key, }) : _appStore = appStore; final TransactionInfo transaction; final BalanceViewModel balanceViewModel; final AppStore _appStore; double get price => balanceViewModel.price; FiatCurrency get fiatCurrency => _appStore.settingsStore.fiatCurrency; BalanceDisplayMode get displayMode => balanceViewModel.displayMode; @override dynamic get keyIndex => transaction.id; bool get hasTokens => isEVMCompatibleChain(balanceViewModel.wallet.type); String get formattedCryptoAmount { 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; final amount = _appStore.amountParsingProxy .getDisplayCryptoString(transaction.amount, crypto) .withMaxDecimals(8) .withLocalSeperator(_appStore.settingsStore.languageCode); return '$amount ${_appStore.amountParsingProxy.getCryptoSymbol(crypto)}'; } return transaction.amountFormatted(); } String get formattedTitle { if (transaction.additionalInfo['autoShield'] == true) { return "Autoshield"; } if (transaction.isPending) { final status = formattedStatus; final baseString = transaction.direction == TransactionDirection.incoming ? S.current.receiving : S.current.sending; return status.isNotEmpty ? "$baseString $status" : "$baseString..."; } if (transaction.direction == TransactionDirection.incoming) { return S.current.received; } return S.current.sent; } int get neededConfirmations { switch (balanceViewModel.wallet.type) { case WalletType.monero: return 10; case WalletType.wownero: return 3; case WalletType.litecoin: bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false; bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false; if(isPegOut || fromPegOut) return 6; default: return 0; } return 0; } String get formattedPendingStatus { switch (balanceViewModel.wallet.type) { case WalletType.monero: if (transaction.confirmations >= 0 && transaction.confirmations < 10) { return ' (${transaction.confirmations}/10)'; } break; case WalletType.wownero: if (transaction.confirmations >= 0 && transaction.confirmations < 3) { return ' (${transaction.confirmations}/3)'; } break; case WalletType.litecoin: bool isPegIn = (transaction.additionalInfo["isPegIn"] as bool?) ?? false; bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false; bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false; String str = ''; if (transaction.confirmations <= 0) { str = S.current.pending; } if ((isPegOut || fromPegOut) && transaction.confirmations >= 0 && transaction.confirmations < 6) { str = " (${transaction.confirmations}/6)"; } if (isPegIn) { str += " (Mask)"; } if (isPegOut) { str += " (Unmask)"; } return str; default: return ''; } return ''; } String get formattedStatus { if ([ WalletType.monero, WalletType.wownero, WalletType.litecoin, ].contains(balanceViewModel.wallet.type)) { return formattedPendingStatus; } return ""; } String get formattedType { if (transaction.evmSignatureName == 'approval') { return ' (${transaction.evmSignatureName})'; } return ''; } CryptoCurrency? get assetOfTransaction { try { if (isEVMCompatibleChain(balanceViewModel.wallet.type)) { final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction); return asset; } } catch (e) { return null; } return null; } String get formattedFiatAmount { var amount = ''; switch (balanceViewModel.wallet.type) { case WalletType.monero: amount = calculateFiatAmountRaw( cryptoAmount: monero!.formatterMoneroAmountToDouble(amount: transaction.amount), price: price, ).withLocalSeperator(_appStore.settingsStore.languageCode); break; case WalletType.wownero: amount = calculateFiatAmountRaw( cryptoAmount: wownero!.formatterWowneroAmountToDouble(amount: transaction.amount), price: price, ).withLocalSeperator(_appStore.settingsStore.languageCode); break; case WalletType.bitcoin: case WalletType.litecoin: case WalletType.bitcoinCash: case WalletType.dogecoin: amount = calculateFiatAmountRaw( cryptoAmount: bitcoin!.formatterBitcoinAmountToDouble(amount: transaction.amount), price: price, ).withLocalSeperator(_appStore.settingsStore.languageCode); break; case WalletType.ethereum: case WalletType.polygon: case WalletType.base: case WalletType.arbitrum: case WalletType.bsc: final asset = evm!.assetOfTransaction(balanceViewModel.wallet, transaction); final price = balanceViewModel.fiatConversionStore.prices[asset]; amount = calculateFiatAmountRaw( cryptoAmount: evm!.formatterEVMAmountToDouble(transaction: transaction), price: price, ).withLocalSeperator(_appStore.settingsStore.languageCode); break; case WalletType.nano: amount = calculateFiatAmountRaw( cryptoAmount: double.parse(nanoUtil!.getRawAsUsableString( nano!.getTransactionAmountRaw(transaction).toString(), nanoUtil!.rawPerNano)), price: price, ).withLocalSeperator(_appStore.settingsStore.languageCode); break; case WalletType.none: case WalletType.banano: break; } transaction.changeFiatAmount(amount); return displayMode == BalanceDisplayMode.hiddenBalance ? '---' : fiatCurrency.title + ' ' + transaction.fiatAmount(); } @override DateTime get date => transaction.date; @override bool operator ==(Object other) { if (other is TransactionListItem) { return other.transaction.txHash == transaction.txHash && other.transaction.confirmations == transaction.confirmations && other.transaction.isPending == transaction.isPending && other.transaction.direction == transaction.direction; } return false; } }