| 1 | import "package:cake_wallet/evm/evm.dart"; |
| 2 | import "package:cw_core/crypto_currency.dart"; |
| 3 | import "package:cw_core/currency_for_wallet_type.dart"; |
| 4 | import "package:cw_core/currency_groups.dart"; |
| 5 | import "package:cw_core/erc20_token.dart"; |
| 6 | import "package:cw_core/spl_token.dart"; |
| 7 | import "package:cw_core/tron_token.dart"; |
| 8 | import "package:cw_core/wallet_type.dart"; |
| 9 | |
| 10 | String chainNameForCurrency(CryptoCurrency c) { |
| 11 | if (c == CryptoCurrency.btcln) { |
| 12 | return "Lightning"; |
| 13 | } |
| 14 | final wt = cryptoCurrencyOrTokenToWalletType(c); |
| 15 | return wt != null ? walletTypeToString(wt) : (c.tag ?? ""); |
| 16 | } |
| 17 | |
| 18 | final Set<String> _stablecoinSymbols = { |
| 19 | for (final c in CryptoCurrency.all) |
| 20 | if (c.groups.contains(CurrencyGroups.stablecoin)) c.title.toUpperCase(), |
| 21 | }; |
| 22 | |
| 23 | bool isTrustedStablecoin(CryptoCurrency c) => |
| 24 | (c.groups.contains(CurrencyGroups.stablecoin) || |
| 25 | _stablecoinSymbols.contains(c.title.toUpperCase())) && |
| 26 | !c.isPotentialScam; |
| 27 | |
| 28 | const _kEvmDefaultTokenNatives = <CryptoCurrency>[ |
| 29 | CryptoCurrency.baseEth, |
| 30 | CryptoCurrency.arbEth, |
| 31 | CryptoCurrency.maticpoly, |
| 32 | ]; |
| 33 | |
| 34 | void appendEvmDefaultTokens(List<CryptoCurrency> into) { |
| 35 | if (evm == null) { |
| 36 | return; |
| 37 | } |
| 38 | String keyFor(CryptoCurrency c) { |
| 39 | final wt = cryptoCurrencyOrTokenToWalletType(c); |
| 40 | final chain = wt?.toString() ?? (c.tag ?? "").toUpperCase(); |
| 41 | return "${c.title.toUpperCase()}|$chain"; |
| 42 | } |
| 43 | |
| 44 | final seen = <String>{for (final c in into) keyFor(c)}; |
| 45 | for (final native in _kEvmDefaultTokenNatives) { |
| 46 | final chainId = getChainIdByCryptoCurrency(native); |
| 47 | if (chainId == null) { |
| 48 | continue; |
| 49 | } |
| 50 | for (final t in evm!.getDefaultTokensByChainId(chainId)) { |
| 51 | if (seen.add(keyFor(t))) { |
| 52 | into.add(t); |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | class CurrencyPickerBalance { |
| 59 | const CurrencyPickerBalance({required this.amount, this.fiat, this.fiatValue}); |
| 60 | |
| 61 | final String amount; |
| 62 | final String? fiat; |
| 63 | final double? fiatValue; |
| 64 | } |
| 65 | |
| 66 | String? _assetAddressKey(CryptoCurrency c) { |
| 67 | if (c is Erc20Token) { |
| 68 | return c.contractAddress.toLowerCase(); |
| 69 | } |
| 70 | if (c is TronToken) { |
| 71 | return c.contractAddress.toLowerCase(); |
| 72 | } |
| 73 | if (c is SPLToken) { |
| 74 | return c.mintAddress.toLowerCase(); |
| 75 | } |
| 76 | return null; |
| 77 | } |
| 78 | |
| 79 | CurrencyPickerBalance? balanceForAsset( |
| 80 | Map<CryptoCurrency, CurrencyPickerBalance>? balances, |
| 81 | CryptoCurrency asset, |
| 82 | ) { |
| 83 | if (balances == null || balances.isEmpty) { |
| 84 | return null; |
| 85 | } |
| 86 | |
| 87 | final direct = balances[asset]; |
| 88 | if (direct != null) { |
| 89 | return direct; |
| 90 | } |
| 91 | |
| 92 | final addressKey = _assetAddressKey(asset); |
| 93 | if (addressKey != null) { |
| 94 | for (final entry in balances.entries) { |
| 95 | if (_assetAddressKey(entry.key) == addressKey) { |
| 96 | return entry.value; |
| 97 | } |
| 98 | } |
| 99 | return null; |
| 100 | } |
| 101 | |
| 102 | final title = asset.title.toUpperCase(); |
| 103 | CurrencyPickerBalance? byTitle; |
| 104 | for (final entry in balances.entries) { |
| 105 | if (entry.key.title.toUpperCase() == title) { |
| 106 | if (byTitle != null) { |
| 107 | return null; |
| 108 | } |
| 109 | byTitle = entry.value; |
| 110 | } |
| 111 | } |
| 112 | return byTitle; |
| 113 | } |
| 114 | |
| 115 | enum RecentsSource { none, trades, orders } |
| 116 | |
| 117 | class CurrencyPickerArgs { |
| 118 | const CurrencyPickerArgs({ |
| 119 | this.selected, |
| 120 | required this.items, |
| 121 | this.balanceByAsset, |
| 122 | this.filterByNetwork, |
| 123 | required this.onSelected, |
| 124 | required this.symbolResolver, |
| 125 | this.recentsSource = RecentsSource.none, |
| 126 | this.useSingleNetworkLayout = false, |
| 127 | }); |
| 128 | |
| 129 | final CryptoCurrency? selected; |
| 130 | final List<CryptoCurrency> items; |
| 131 | final WalletType? filterByNetwork; |
| 132 | final void Function(CryptoCurrency) onSelected; |
| 133 | final String Function(CryptoCurrency) symbolResolver; |
| 134 | final Map<CryptoCurrency, CurrencyPickerBalance>? balanceByAsset; |
| 135 | final RecentsSource recentsSource; |
| 136 | final bool useSingleNetworkLayout; |
| 137 | } |