| 1 | import "package:cw_core/crypto_currency.dart"; |
| 2 | import "package:cw_core/spl_token.dart"; |
| 3 | import "package:cw_solana/solana_client.dart"; |
| 4 | import "package:cw_solana/solana_exceptions.dart"; |
| 5 | import "package:cw_solana/solana_wallet.dart"; |
| 6 | import "package:flutter_test/flutter_test.dart"; |
| 7 | |
| 8 | void main() { |
| 9 | group("currencyForRawAmount", () { |
| 10 | test("keeps the stored token when its decimals match the mint", () { |
| 11 | final jup = SPLToken( |
| 12 | name: "Jupiter", |
| 13 | symbol: "JUP", |
| 14 | mint: "jup", |
| 15 | mintAddress: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", |
| 16 | decimal: 6, |
| 17 | ); |
| 18 | |
| 19 | expect(SolanaWalletClient.currencyForRawAmount(jup, 6), same(jup)); |
| 20 | }); |
| 21 | |
| 22 | test("prefers the mint decimals when the stored token disagrees", () { |
| 23 | final staleJup = SPLToken( |
| 24 | name: "Jupiter", |
| 25 | symbol: "JUP", |
| 26 | mint: "jup", |
| 27 | mintAddress: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", |
| 28 | decimal: 0, |
| 29 | ); |
| 30 | |
| 31 | final resolved = SolanaWalletClient.currencyForRawAmount(staleJup, 6); |
| 32 | |
| 33 | expect(resolved.decimals, 6); |
| 34 | expect(resolved.title, "JUP"); |
| 35 | expect(resolved, isNot(same(staleJup))); |
| 36 | }); |
| 37 | |
| 38 | test("falls back to a placeholder title when the token is unknown", () { |
| 39 | final resolved = SolanaWalletClient.currencyForRawAmount(null, 8); |
| 40 | |
| 41 | expect(resolved.decimals, 8); |
| 42 | expect(resolved.title, "TOKEN"); |
| 43 | expect(resolved.name, "token"); |
| 44 | }); |
| 45 | |
| 46 | test("always reports the mint decimals", () { |
| 47 | for (final decimals in [0, 1, 6, 8, 9, 18]) { |
| 48 | expect(SolanaWalletClient.currencyForRawAmount(null, decimals).decimals, decimals); |
| 49 | } |
| 50 | }); |
| 51 | }); |
| 52 | |
| 53 | group("resolveTransactionCurrency", () { |
| 54 | final realUsdc = SPLToken( |
| 55 | name: "USD Coin", |
| 56 | symbol: "USDC", |
| 57 | mint: "usdc", |
| 58 | mintAddress: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", |
| 59 | decimal: 6, |
| 60 | ); |
| 61 | |
| 62 | final scamUsdc = SPLToken( |
| 63 | name: "USD Coin", |
| 64 | symbol: "USDC", |
| 65 | mint: "usdc", |
| 66 | mintAddress: "scamMintAddressClaimingTheUsdcSymbol", |
| 67 | decimal: 9, |
| 68 | ); |
| 69 | |
| 70 | test("picks the requested mint even when another token claims the symbol", () { |
| 71 | final resolved = SolanaWalletBase.resolveTransactionCurrency(realUsdc, [scamUsdc, realUsdc]); |
| 72 | |
| 73 | expect(resolved, same(realUsdc)); |
| 74 | expect((resolved as SPLToken).mintAddress, realUsdc.mintAddress); |
| 75 | }); |
| 76 | |
| 77 | test("picks the scam mint only when the scam mint is the one requested", () { |
| 78 | final resolved = SolanaWalletBase.resolveTransactionCurrency(scamUsdc, [scamUsdc, realUsdc]); |
| 79 | |
| 80 | expect(resolved, same(scamUsdc)); |
| 81 | }); |
| 82 | |
| 83 | test("throws when the requested mint is not in the wallet", () { |
| 84 | expect( |
| 85 | () => SolanaWalletBase.resolveTransactionCurrency(realUsdc, [scamUsdc]), |
| 86 | throwsA(isA<Exception>()), |
| 87 | ); |
| 88 | }); |
| 89 | |
| 90 | test("throws on ambiguity when a symbol lookup matches two tokens", () { |
| 91 | expect( |
| 92 | () => SolanaWalletBase.resolveTransactionCurrency( |
| 93 | CryptoCurrency(name: "usdc", title: "USDC", decimals: 6, tag: "SOL"), |
| 94 | [scamUsdc, realUsdc], |
| 95 | ), |
| 96 | throwsA(isA<SolanaAmbiguousTokenSymbolException>()), |
| 97 | ); |
| 98 | }); |
| 99 | |
| 100 | test("resolves a native currency by title and tag", () { |
| 101 | expect( |
| 102 | SolanaWalletBase.resolveTransactionCurrency( |
| 103 | CryptoCurrency.sol, [CryptoCurrency.sol, realUsdc]), |
| 104 | same(CryptoCurrency.sol), |
| 105 | ); |
| 106 | }); |
| 107 | }); |
| 108 | } |