diff --git a/cw_core/lib/payment_uris.dart b/cw_core/lib/payment_uris.dart index 6ad43a875..daf56af2f 100644 --- a/cw_core/lib/payment_uris.dart +++ b/cw_core/lib/payment_uris.dart @@ -176,14 +176,23 @@ class PolygonURI extends PaymentURI { } class SolanaURI extends PaymentURI { - SolanaURI({required super.amount, required super.address}); + SolanaURI({required super.amount, required super.address, this.contractAddress}); + + final String? contractAddress; @override String toString() { var base = 'solana:$address'; + final params = []; if (amount.isNotEmpty) { - base += '?amount=${amount.replaceAll(',', '.')}'; + params.add('amount=${amount.replaceAll(',', '.')}'); + } + if (contractAddress != null && contractAddress!.isNotEmpty) { + params.add('spl-token=$contractAddress'); + } + if (params.isNotEmpty) { + base += '?${params.join('&')}'; } return base; @@ -191,14 +200,23 @@ class SolanaURI extends PaymentURI { } class TronURI extends PaymentURI { - TronURI({required super.amount, required super.address}); + TronURI({required super.amount, required super.address, this.contractAddress}); + + final String? contractAddress; @override String toString() { var base = 'tron:$address'; + final params = []; if (amount.isNotEmpty) { - base += '?amount=${amount.replaceAll(',', '.')}'; + params.add('amount=${amount.replaceAll(',', '.')}'); + } + if (contractAddress != null && contractAddress!.isNotEmpty) { + params.add('token=$contractAddress'); + } + if (params.isNotEmpty) { + base += '?${params.join('&')}'; } return base; diff --git a/lib/new-ui/pages/send_page.dart b/lib/new-ui/pages/send_page.dart index af09b68ab..fec5e06f5 100644 --- a/lib/new-ui/pages/send_page.dart +++ b/lib/new-ui/pages/send_page.dart @@ -228,6 +228,14 @@ class _NewSendPageState extends State { _addressControllers[0].text = widget.initialPaymentRequest!.address; _amountControllers[0].text = widget.initialPaymentRequest!.amount; _memoControllers[0].text = widget.initialPaymentRequest!.note; + final contractAddress = widget.initialPaymentRequest!.contractAddress; + if (contractAddress != null && contractAddress.isNotEmpty) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + widget.sendViewModel.fetchTokenForContractAddress(contractAddress); + } + }); + } } /// if the current wallet doesn't match the one in the qr code diff --git a/lib/utils/payment_request.dart b/lib/utils/payment_request.dart index c0d747080..fdc48b1eb 100644 --- a/lib/utils/payment_request.dart +++ b/lib/utils/payment_request.dart @@ -60,6 +60,16 @@ class PaymentRequest { address = paymentUri.address; amount = paymentUri.amount; contractAddress = paymentUri.contractAddress; + } else if (scheme == "tron") { + final token = uri.queryParameters['token']; + if (token != null && token.isNotEmpty) { + contractAddress = token; + } + } else if (scheme == "solana") { + final splToken = uri.queryParameters['spl-token']; + if (splToken != null && splToken.isNotEmpty) { + contractAddress = splToken; + } } } diff --git a/lib/utils/token_utilities.dart b/lib/utils/token_utilities.dart index 8e70e3e28..34dc393a1 100644 --- a/lib/utils/token_utilities.dart +++ b/lib/utils/token_utilities.dart @@ -144,7 +144,7 @@ class TokenUtilities { return result; } - /// Finds a token by address across wallets depending on [walletType] + /// Finds a token by address for the given [walletType]. /// - EVM chains: match by contractAddress /// - Solana: match by mintAddress /// - Tron: match by contractAddress @@ -152,34 +152,15 @@ class TokenUtilities { required WalletType walletType, required String address, }) async { - if(address.isEmpty) return null; + if (address.isEmpty) return null; final lower = address.toLowerCase(); - switch (walletType) { - case WalletType.ethereum: - case WalletType.polygon: - case WalletType.base: - case WalletType.arbitrum: - case WalletType.bsc: - final tokens = await loadAllUniqueEvmTokens(); - for (final t in tokens) { - if (t.contractAddress.toLowerCase() == lower) return t; - } - return null; - case WalletType.solana: - final solTokens = await loadAllUniqueSolTokens(); - for (final t in solTokens) { - if (t.mintAddress.toLowerCase() == lower) return t; - } - return null; - case WalletType.tron: - final tronTokens = await loadAllUniqueTronTokens(); - for (final t in tronTokens) { - if (t.contractAddress.toLowerCase() == lower) return t; - } - return null; - default: - return null; + final tokens = await getAvailableTokensForNetwork(walletType); + for (final t in tokens) { + if (t is Erc20Token && t.contractAddress.toLowerCase() == lower) return t; + if (t is SPLToken && t.mintAddress.toLowerCase() == lower) return t; + if (t is TronToken && t.contractAddress.toLowerCase() == lower) return t; } + return null; } static Future> _openEvmTokensBoxFor(WalletInfo walletInfo) async { diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 89c5374f7..f097e5d12 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -34,6 +34,8 @@ import 'package:cw_core/currency.dart'; import 'package:cw_core/currency_for_wallet_type.dart'; import 'package:cw_core/erc20_token.dart'; import 'package:cw_core/payment_uris.dart'; +import 'package:cw_core/spl_token.dart'; +import 'package:cw_core/tron_token.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:mobx/mobx.dart'; @@ -202,6 +204,20 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo amount: _amount, contractAddress: (tokenCurrency as Erc20Token).contractAddress); } + if (tokenCurrency is TronToken && wallet.type == WalletType.tron) { + return TronURI( + amount: _amount, + address: wallet.walletAddresses.address, + contractAddress: (tokenCurrency as TronToken).contractAddress, + ); + } + if (tokenCurrency is SPLToken && wallet.type == WalletType.solana) { + return SolanaURI( + amount: _amount, + address: wallet.walletAddresses.address, + contractAddress: (tokenCurrency as SPLToken).mintAddress, + ); + } if (isLightning && _lnPaymentRequest != null) return _lnPaymentRequest!; return wallet.walletAddresses.getPaymentUri(_amount); }