feat: Load default tokens in available swap currencies (#2926)

David Adegoke committed Feb 19, 2026 at 18:51 UTC 2398e299dc5526c7d67c3e88d48e296ad942b0fb
6 files changed +88 -9
lib/evm/cw_evm.dart
+4
@@ -307,6 +307,10 @@ class CWEVM extends EVM {
307 HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect connect) =>
308 EVMChainTrezorService(connect);
309
310 + @override
311 + List<Erc20Token> getDefaultTokensByChainId(int chainId) =>
312 + EVMChainDefaultTokens.getDefaultTokensByChainId(chainId);
313 +
314 @override
315 List<String> getDefaultTokenContractAddresses(WalletBase wallet) {
316 final chainId = getSelectedChainId(wallet);
lib/solana/cw_solana.dart
+3
@@ -172,6 +172,9 @@ class CWSolana extends Solana {
172 return (wallet as SolanaWallet).estimatedFee;
173 }
174
175 + @override
176 + List<SPLToken> getDefaultSPLTokens() => DefaultSPLTokens().initialSPLTokens;
177 +
178 @override
179 List<String> getDefaultTokenContractAddresses() {
180 return DefaultSPLTokens().initialSPLTokens.map((e) => e.mintAddress).toList();
lib/tron/cw_tron.dart
+3
@@ -134,6 +134,9 @@ class CWTron extends Tron {
134 (wallet as TronWallet).updateScanProviderUsageState(isEnabled);
135 }
136
137 + @override
138 + List<TronToken> getDefaultTronTokens() => DefaultTronTokens().initialTronTokens;
139 +
140 @override
141 List<String> getDefaultTokenContractAddresses() {
142 return DefaultTronTokens().initialTronTokens.map((e) => e.contractAddress).toList();
lib/utils/token_utilities.dart
+69
@@ -1,5 +1,7 @@
1 import 'package:cake_wallet/reactions/wallet_connect.dart';
2 import 'package:cake_wallet/evm/evm.dart';
3 +import 'package:cake_wallet/solana/solana.dart';
4 +import 'package:cake_wallet/tron/tron.dart';
5 import 'package:cw_core/cake_hive.dart';
6 import 'package:cw_core/crypto_currency.dart';
7 import 'package:cw_core/currency_for_wallet_type.dart';
@@ -75,6 +77,73 @@ class TokenUtilities {
77 return unique;
78 }
79
80 + static List<Erc20Token> loadDefaultEvmTokensForSwap() {
81 + if (evm == null) return [];
82 +
83 + final tokens = <Erc20Token>[];
84 + final seen = <String>{};
85 +
86 + for (final chain in evm!.getAllChains()) {
87 + for (final token in evm!.getDefaultTokensByChainId(chain.chainId)) {
88 + final key = '${chain.chainId}|${token.contractAddress.toLowerCase()}';
89 + if (seen.add(key)) tokens.add(token);
90 + }
91 + }
92 +
93 + return tokens;
94 + }
95 +
96 + static List<SPLToken> loadDefaultSolTokensForSwap() =>
97 + solana != null ? solana!.getDefaultSPLTokens() : [];
98 +
99 + static List<TronToken> loadDefaultTronTokensForSwap() =>
100 + tron != null ? tron!.getDefaultTronTokens() : [];
101 +
102 + static Future<List<Erc20Token>> loadEvmTokensForSwap() async {
103 + final defaultTokens = loadDefaultEvmTokensForSwap();
104 + final userTokens = await loadAllUniqueEvmTokens();
105 +
106 + final seen = <String>{};
107 + final result = <Erc20Token>[];
108 +
109 + for (final t in [...defaultTokens, ...userTokens]) {
110 + final key = '${t.tag ?? 'ETH'}|${t.contractAddress.toLowerCase()}';
111 + if (seen.add(key)) result.add(t);
112 + }
113 +
114 + return result;
115 + }
116 +
117 + static Future<List<SPLToken>> loadSolTokensForSwap() async {
118 + final defaultTokens = loadDefaultSolTokensForSwap();
119 + final userTokens = await loadAllUniqueSolTokens();
120 +
121 + final seen = <String>{};
122 + final result = <SPLToken>[];
123 +
124 + for (final t in [...defaultTokens, ...userTokens]) {
125 + final key = t.mintAddress.toLowerCase();
126 + if (seen.add(key)) result.add(t);
127 + }
128 +
129 + return result;
130 + }
131 +
132 + static Future<List<TronToken>> loadTronTokensForSwap() async {
133 + final defaultTokens = loadDefaultTronTokensForSwap();
134 + final userTokens = await loadAllUniqueTronTokens();
135 +
136 + final seen = <String>{};
137 + final result = <TronToken>[];
138 +
139 + for (final t in [...defaultTokens, ...userTokens]) {
140 + final key = t.contractAddress.toLowerCase();
141 + if (seen.add(key)) result.add(t);
142 + }
143 +
144 + return result;
145 + }
146 +
147 /// Finds a token by address across wallets depending on [walletType]
148 /// - EVM chains: match by contractAddress
149 /// - Solana: match by mintAddress
lib/view_model/exchange/exchange_view_model.dart
+6 -9
@@ -1126,12 +1126,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1126
1127 @action
1128 Future<void> _injectUserEthTokensIntoCurrencyLists() async {
1129 - final userTokens = await TokenUtilities.loadAllUniqueEvmTokens();
1130 -
1129 + final tokens = await TokenUtilities.loadEvmTokensForSwap();
1130 final toAddReceive = <CryptoCurrency>[];
1131 final toAddDeposit = <CryptoCurrency>[];
1132
1134 - for (final token in userTokens) {
1133 + for (final token in tokens) {
1134 if (!_listContainsToken(receiveCurrencies, token)) toAddReceive.add(token);
1135 if (!_listContainsToken(depositCurrencies, token)) toAddDeposit.add(token);
1136 }
@@ -1164,12 +1163,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1163
1164 @action
1165 Future<void> _injectUserSplTokensIntoCurrencyLists() async {
1167 - final userTokens = await TokenUtilities.loadAllUniqueSolTokens();
1168 -
1166 + final tokens = await TokenUtilities.loadSolTokensForSwap();
1167 final toAddReceive = <CryptoCurrency>[];
1168 final toAddDeposit = <CryptoCurrency>[];
1169
1172 - for (final token in userTokens) {
1170 + for (final token in tokens) {
1171 if (!_listContainsSplToken(receiveCurrencies, token)) toAddReceive.add(token);
1172 if (!_listContainsSplToken(depositCurrencies, token)) toAddDeposit.add(token);
1173 }
@@ -1192,12 +1190,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1190
1191 @action
1192 Future<void> _injectUserTronTokensIntoCurrencyLists() async {
1195 - final userTokens = await TokenUtilities.loadAllUniqueTronTokens();
1196 -
1193 + final tokens = await TokenUtilities.loadTronTokensForSwap();
1194 final toAddReceive = <CryptoCurrency>[];
1195 final toAddDeposit = <CryptoCurrency>[];
1196
1200 - for (final token in userTokens) {
1197 + for (final token in tokens) {
1198 if (!_listContainsTronToken(receiveCurrencies, token)) toAddReceive.add(token);
1199 if (!_listContainsTronToken(depositCurrencies, token)) toAddDeposit.add(token);
1200 }
tool/configure.dart
+3
@@ -968,6 +968,7 @@ abstract class Solana {
968 String getTokenAddress(CryptoCurrency asset);
969 List<int>? getValidationLength(CryptoCurrency type);
970 double? getEstimateFees(WalletBase wallet);
971 + List<SPLToken> getDefaultSPLTokens();
972 List<String> getDefaultTokenContractAddresses();
973 List<String> getDefaultTokenSymbols();
974 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
@@ -1094,6 +1095,7 @@ abstract class Tron {
1095 String? getTronTRC20EstimatedFee(WalletBase wallet);
1096
1097 void updateTronGridUsageState(WalletBase wallet, bool isEnabled);
1098 + List<TronToken> getDefaultTronTokens();
1099 List<String> getDefaultTokenContractAddresses();
1100 List<String> getDefaultTokenSymbols();
1101 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);
@@ -1490,6 +1492,7 @@ abstract class EVM {
1492 HardwareWalletService getTrezorHardwareWalletService(trezor.TrezorConnect connect);
1493
1494 // Utility methods
1495 + List<Erc20Token> getDefaultTokensByChainId(int chainId);
1496 List<String> getDefaultTokenContractAddresses(WalletBase wallet);
1497 List<String> getDefaultTokenSymbols(WalletBase wallet);
1498 bool isTokenAlreadyAdded(WalletBase wallet, String contractAddress);