diff --git a/packages/solana/lib/src/helpers.dart b/packages/solana/lib/src/helpers.dart index f5b5d78da..8fb1704e1 100644 --- a/packages/solana/lib/src/helpers.dart +++ b/packages/solana/lib/src/helpers.dart @@ -35,9 +35,10 @@ bool isPointOnEd25519Curve(Iterable data) { Future findAssociatedTokenAddress({ required Ed25519HDPublicKey owner, required Ed25519HDPublicKey mint, + TokenProgramType tokenProgramType = TokenProgramType.tokenProgram, }) => Ed25519HDPublicKey.findProgramAddress( - seeds: [owner.bytes, TokenProgram.id.toByteArray(), mint.bytes], + seeds: [owner.bytes, tokenProgramType.id.toByteArray(), mint.bytes], programId: AssociatedTokenAccountProgram.id, ); diff --git a/packages/solana/lib/src/programs/associated_token_account_program/instruction.dart b/packages/solana/lib/src/programs/associated_token_account_program/instruction.dart index f77d01f3b..85d1b33d2 100644 --- a/packages/solana/lib/src/programs/associated_token_account_program/instruction.dart +++ b/packages/solana/lib/src/programs/associated_token_account_program/instruction.dart @@ -28,6 +28,7 @@ class AssociatedTokenAccountInstruction extends Instruction { required Ed25519HDPublicKey address, required Ed25519HDPublicKey owner, required Ed25519HDPublicKey mint, + Ed25519HDPublicKey? tokenProgramId, }) => AssociatedTokenAccountInstruction._( accounts: [ @@ -40,7 +41,9 @@ class AssociatedTokenAccountInstruction extends Instruction { isSigner: false, ), AccountMeta.readonly( - pubKey: Ed25519HDPublicKey.fromBase58(TokenProgram.programId), + pubKey: Ed25519HDPublicKey.fromBase58( + tokenProgramId?.toBase58() ?? TokenProgram.id.toBase58(), + ), isSigner: false, ), AccountMeta.readonly( diff --git a/packages/solana/lib/src/programs/associated_token_account_program/solana_client_ext.dart b/packages/solana/lib/src/programs/associated_token_account_program/solana_client_ext.dart index 83b2ccef3..b375129e0 100644 --- a/packages/solana/lib/src/programs/associated_token_account_program/solana_client_ext.dart +++ b/packages/solana/lib/src/programs/associated_token_account_program/solana_client_ext.dart @@ -50,6 +50,7 @@ extension SolanaClientAssociatedTokenAccontProgram on SolanaClient { Ed25519HDPublicKey? owner, required Ed25519HDPublicKey mint, required Wallet funder, + TokenProgramType tokenProgramType = TokenProgramType.tokenProgram, SignatureCallback? onSigned, Commitment commitment = Commitment.finalized, }) async { @@ -58,6 +59,7 @@ extension SolanaClientAssociatedTokenAccontProgram on SolanaClient { final derivedAddress = await findAssociatedTokenAddress( owner: effectiveOwner, mint: mint, + tokenProgramType: tokenProgramType, ); final instruction = AssociatedTokenAccountInstruction.createAccount( mint: mint, @@ -129,9 +131,14 @@ extension SolanaClientAssociatedTokenAccontProgram on SolanaClient { Future getTokenBalance({ required Ed25519HDPublicKey owner, required Ed25519HDPublicKey mint, + TokenProgramType tokenProgramType = TokenProgramType.tokenProgram, Commitment commitment = Commitment.finalized, }) async { - final ata = await findAssociatedTokenAddress(owner: owner, mint: mint); + final ata = await findAssociatedTokenAddress( + owner: owner, + mint: mint, + tokenProgramType: tokenProgramType, + ); return rpcClient .getTokenAccountBalance(ata.toBase58(), commitment: commitment) diff --git a/packages/solana/lib/src/programs/token_program/extension_type.dart b/packages/solana/lib/src/programs/token_program/extension_type.dart new file mode 100644 index 000000000..4b2f0d707 --- /dev/null +++ b/packages/solana/lib/src/programs/token_program/extension_type.dart @@ -0,0 +1,28 @@ +enum ExtensionType { + uninitialized(0), + transferFeeConfig(1), + transferFeeAmount(2), + mintCloseAuthority(3), + confidentialTransferMint(4), + confidentialTransferAccount(5), + defaultAccountState(6), + immutableOwner(7), + memoTransfer(8), + nonTransferable(9), + interestBearingConfig(10), + cpiGuard(11), + permanentDelegate(12), + nonTransferableAccount(13), + transferHook(14), + transferHookAccount(15), + metadataPointer(18), + tokenMetadata(19), + groupPointer(20), + tokenGroup(21), + groupMemberPointer(22), + tokenGroupMember(23); + + const ExtensionType(this.value); + + final int value; +} diff --git a/packages/solana/lib/src/programs/token_program/instruction.dart b/packages/solana/lib/src/programs/token_program/instruction.dart index e8952ade9..5e8e9320c 100644 --- a/packages/solana/lib/src/programs/token_program/instruction.dart +++ b/packages/solana/lib/src/programs/token_program/instruction.dart @@ -1,10 +1,8 @@ -import 'package:solana/src/crypto/ed25519_hd_public_key.dart'; +import 'package:solana/solana.dart'; import 'package:solana/src/encoder/account_meta.dart'; import 'package:solana/src/encoder/byte_array.dart'; import 'package:solana/src/encoder/constants.dart'; import 'package:solana/src/encoder/instruction.dart'; -import 'package:solana/src/programs/system_program/instruction.dart'; -import 'package:solana/src/programs/token_program/program.dart'; enum AuthorityType { mintTokens, @@ -18,8 +16,9 @@ class TokenInstruction extends Instruction { TokenInstruction._({ required super.accounts, required super.data, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) : super( - programId: TokenProgram.id, + programId: tokenProgram.id, ); /// Construct an instruction to initialize a new spl token with address @@ -36,6 +35,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey mintAuthority, Ed25519HDPublicKey? freezeAuthority, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -55,6 +55,7 @@ class TokenInstruction extends Instruction { else ByteArray(List.filled(32, 0)), ]), + tokenProgram: tokenProgram, ); /// Initializes a new [account] to hold tokens. @@ -67,6 +68,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey account, required Ed25519HDPublicKey mint, required Ed25519HDPublicKey owner, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -79,6 +81,7 @@ class TokenInstruction extends Instruction { ), ], data: TokenProgram.initializeAccountInstructionIndex, + tokenProgram: tokenProgram, ); /// Initializes a multisignature [account] with N provided [signers]. @@ -89,6 +92,7 @@ class TokenInstruction extends Instruction { factory TokenInstruction.initializeMultisig({ required Ed25519HDPublicKey account, required List signers, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -105,6 +109,7 @@ class TokenInstruction extends Instruction { TokenProgram.initializeMintInstructionIndex, ByteArray.u8(signers.length), ]), + tokenProgram: tokenProgram, ); /// Transfers tokens from one [source] account to [destination] either @@ -118,6 +123,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey destination, required Ed25519HDPublicKey owner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -135,6 +141,7 @@ class TokenInstruction extends Instruction { TokenProgram.transferInstructionIndex, ByteArray.u64(amount), ]), + tokenProgram: tokenProgram, ); /// Approves a [delegate]. @@ -147,6 +154,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey delegate, required Ed25519HDPublicKey sourceOwner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -166,6 +174,7 @@ class TokenInstruction extends Instruction { ByteArray.u64(amount), ], ), + tokenProgram: tokenProgram, ); /// Revokes the delegate's authority. @@ -173,6 +182,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey source, required Ed25519HDPublicKey sourceOwner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -186,6 +196,7 @@ class TokenInstruction extends Instruction { ), ], data: TokenProgram.revokeInstructionIndex, + tokenProgram: tokenProgram, ); /// Sets a new authority of a mint or account. @@ -198,6 +209,7 @@ class TokenInstruction extends Instruction { required AuthorityType authorityType, Ed25519HDPublicKey? newAuthority, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -219,6 +231,7 @@ class TokenInstruction extends Instruction { ] else ByteArray.u8(0), ]), + tokenProgram: tokenProgram, ); /// Mint the [destination] account with [amount] tokens of the [mint] token. @@ -231,6 +244,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey destination, required Ed25519HDPublicKey authority, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -243,6 +257,7 @@ class TokenInstruction extends Instruction { TokenProgram.mintToInstructionIndex, ByteArray.u64(amount), ]), + tokenProgram: tokenProgram, ); /// Burns tokens by removing them from an account. @@ -255,6 +270,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey owner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -272,6 +288,7 @@ class TokenInstruction extends Instruction { TokenProgram.burnInstructionIndex, ByteArray.u64(amount), ]), + tokenProgram: tokenProgram, ); /// Close an account by transferring all its SOL to the destination account. @@ -282,6 +299,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey destination, required Ed25519HDPublicKey owner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -296,6 +314,7 @@ class TokenInstruction extends Instruction { ), ], data: TokenProgram.closeAccountInstructionIndex, + tokenProgram: tokenProgram, ); /// Freeze an Initialized [account] using the mint's [freezeAuthority]. @@ -304,6 +323,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey freezeAuthority, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -318,6 +338,7 @@ class TokenInstruction extends Instruction { ), ], data: TokenProgram.freezeAccountInstructionIndex, + tokenProgram: tokenProgram, ); /// Thaw a Frozen [account] using the mint's [freezeAuthority]. @@ -326,6 +347,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey freezeAuthority, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -340,6 +362,7 @@ class TokenInstruction extends Instruction { ), ], data: TokenProgram.thawAccountInstructionIndex, + tokenProgram: tokenProgram, ); /// Transfers tokens from one account to another either directly or via a @@ -357,6 +380,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey destination, required Ed25519HDPublicKey owner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -376,6 +400,7 @@ class TokenInstruction extends Instruction { ByteArray.u64(amount), ByteArray.u8(decimals), ]), + tokenProgram: tokenProgram, ); /// Approves a delegate. A delegate is given the authority over tokens on @@ -392,6 +417,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey delegate, required Ed25519HDPublicKey sourceOwner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -413,6 +439,7 @@ class TokenInstruction extends Instruction { ByteArray.u8(decimals), ], ), + tokenProgram: tokenProgram, ); /// Mints new tokens to an account. The native mint does not support minting. @@ -426,6 +453,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey destination, required Ed25519HDPublicKey authority, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -439,6 +467,7 @@ class TokenInstruction extends Instruction { ByteArray.u64(amount), ByteArray.u8(decimals), ]), + tokenProgram: tokenProgram, ); /// Burns tokens by removing them from an account. @@ -456,6 +485,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey owner, List signers = const [], + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -474,6 +504,7 @@ class TokenInstruction extends Instruction { ByteArray.u64(amount), ByteArray.u8(decimals), ]), + tokenProgram: tokenProgram, ); /// Like [TokenInstruction.initializeAccount], but the owner pubkey is passed @@ -484,6 +515,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey pubKey, required Ed25519HDPublicKey mint, required Ed25519HDPublicKey owner, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -498,6 +530,7 @@ class TokenInstruction extends Instruction { TokenProgram.initializeAccount2InstructionIndex, owner.toByteArray(), ]), + tokenProgram: tokenProgram, ); /// Given a wrapped / native token account (a token account containing SOL) @@ -507,12 +540,14 @@ class TokenInstruction extends Instruction { /// and needs to have its token `amount` field updated. factory TokenInstruction.syncNative({ required Ed25519HDPublicKey nativeTokenAccount, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ AccountMeta.writeable(pubKey: nativeTokenAccount, isSigner: false), ], data: TokenProgram.syncNativeInstructionIndex, + tokenProgram: tokenProgram, ); /// Like [TokenInstruction.initializeAccount2], but does not require the Rent @@ -521,6 +556,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey pubKey, required Ed25519HDPublicKey mint, required Ed25519HDPublicKey owner, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -531,6 +567,7 @@ class TokenInstruction extends Instruction { TokenProgram.initializeAccount3InstructionIndex, owner.toByteArray(), ]), + tokenProgram: tokenProgram, ); /// Like [TokenInstruction.initializeMultisig], but does not require the Rent @@ -538,6 +575,7 @@ class TokenInstruction extends Instruction { factory TokenInstruction.initializeMultisig2({ required Ed25519HDPublicKey pubKey, required List signerPubKeys, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -550,6 +588,7 @@ class TokenInstruction extends Instruction { TokenProgram.initializeMultisig2InstructionIndex, ByteArray.u8(signerPubKeys.length), ]), + tokenProgram: tokenProgram, ); /// Like [TokenInstruction.initializeMint], but does not require the Rent @@ -559,6 +598,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey mint, required Ed25519HDPublicKey mintAuthority, Ed25519HDPublicKey? freezeAuthority, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => TokenInstruction._( accounts: [ @@ -574,6 +614,193 @@ class TokenInstruction extends Instruction { else ByteArray(List.filled(32, 0)), ]), + tokenProgram: tokenProgram, + ); + + /// Gets the required size of an account for the given mint as a + /// little-endian `u64`. + factory TokenInstruction.getAccountDataSize({ + required Ed25519HDPublicKey mint, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.readonly(pubKey: mint, isSigner: false), + ], + data: TokenProgram.getAccountDataSizeInstructionIndex, + tokenProgram: tokenProgram, + ); + + /// Initialize the Immutable Owner extension for the given token account + /// + /// Fails if the account has already been initialized, so must be called + /// before [TokenInstruction.initializeAccount]. + factory TokenInstruction.initializeImmutableOwner({ + required Ed25519HDPublicKey account, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: account, isSigner: false), + ], + data: TokenProgram.initializeImmutableOwnerInstructionIndex, + tokenProgram: tokenProgram, + ); + + /// Convert an [amount] of tokens to a UiAmount `string`, using the given + /// mint. In this version of the program, the [mint] can only specify the + /// number of decimals. + /// + /// Fails on an invalid mint. + factory TokenInstruction.amountToUiAmount({ + required Ed25519HDPublicKey mint, + required int amount, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.readonly(pubKey: mint, isSigner: false), + ], + data: ByteArray.merge( + [ + TokenProgram.amountToUiAmountInstructionIndex, + ByteArray.u64(amount), + ], + ), + tokenProgram: tokenProgram, + ); + + /// Convert a UiAmount of tokens to a little-endian `u64` raw [amount], using + /// the given [mint]. + factory TokenInstruction.uiAmountToAmount({ + required Ed25519HDPublicKey mint, + required String amount, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.readonly(pubKey: mint, isSigner: false), + ], + data: ByteArray.merge( + [ + TokenProgram.uiAmountToAmountInstructionIndex, + ByteArray.fromString(amount), + ], + ), + tokenProgram: tokenProgram, + ); + + /// Initialize the close account authority on a new mint. + /// + /// Fails if the [mint] has already been initialized, so must be called before + /// `InitializeMint`. + /// + /// The mint must have exactly enough space allocated for the base mint (82 + /// bytes), plus 83 bytes of padding, 1 byte reserved for the account type, + /// then space required for this extension, plus any others. + factory TokenInstruction.initializeMintCloseAuthority({ + required Ed25519HDPublicKey mint, + required Ed25519HDPublicKey? closeAuthority, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: mint, isSigner: false), + ], + data: ByteArray.merge( + [ + Token2022Program.initializeMintCloseAuthorityInstructionIndex, + if (closeAuthority != null) closeAuthority.toByteArray(), + ], + ), + tokenProgram: TokenProgramType.token2022Program, + ); + + /// Check to see if a token [account] is large enough for a list of + /// [extensionTypes], and if not, use reallocation to increase the data + /// size. + factory TokenInstruction.reallocate({ + required Ed25519HDPublicKey account, + required Ed25519HDPublicKey payer, + required List extensionTypes, + required Ed25519HDPublicKey owner, + List signers = const [], + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: account, isSigner: false), + AccountMeta.writeable(pubKey: payer, isSigner: true), + AccountMeta.readonly(pubKey: SystemProgram.id, isSigner: false), + AccountMeta.writeable( + pubKey: owner, + isSigner: signers.isEmpty, + ), + ...signers.map( + (pubKey) => AccountMeta.readonly(pubKey: pubKey, isSigner: true), + ), + ], + data: ByteArray.merge([ + Token2022Program.reallocateInstructionIndex, + ByteArray.merge( + extensionTypes.map((e) => ByteArray.u16(e.value)), + ), + ]), + tokenProgram: TokenProgramType.token2022Program, + ); + + /// Creates the native mint. + /// + /// This instruction only needs to be invoked once after deployment and is + /// permissionless, Wrapped SOL will not be available until this instruction + /// is successfully executed. + factory TokenInstruction.createNativeMint({ + required Ed25519HDPublicKey payer, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: payer, isSigner: true), + AccountMeta.writeable(pubKey: nativeMint2022, isSigner: false), + AccountMeta.readonly(pubKey: SystemProgram.id, isSigner: false), + ], + data: Token2022Program.createNativeMintInstructionIndex, + tokenProgram: TokenProgramType.token2022Program, + ); + + /// Initialize the non transferable extension for the given [mint] account + /// + /// Fails if the account has already been initialized, so must be called + /// before `InitializeMint`. + factory TokenInstruction.initializeNonTransferableMint({ + required Ed25519HDPublicKey mint, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: mint, isSigner: false), + ], + data: Token2022Program.initializeNonTransferableMintInstructionIndex, + tokenProgram: TokenProgramType.token2022Program, + ); + + // Initialize the permanent delegate on a new [mint]. + /// + /// Fails if the [mint] has already been initialized, so must be called before + /// `InitializeMint`. + /// + /// The [mint] must have exactly enough space allocated for the base mint (82 + /// bytes), plus 83 bytes of padding, 1 byte reserved for the account type, + /// then space required for this extension, plus any others. + factory TokenInstruction.initializePermanentDelegate({ + required Ed25519HDPublicKey mint, + required Ed25519HDPublicKey? delegate, + }) => + TokenInstruction._( + accounts: [ + AccountMeta.writeable(pubKey: mint, isSigner: false), + ], + data: ByteArray.merge([ + Token2022Program.initializePermanentDelegateInstructionIndex, + if (delegate != null) delegate.toByteArray(), + ]), + tokenProgram: TokenProgramType.token2022Program, ); /// Initialize a new spl token with address [mint], [decimals] decimal places, @@ -591,6 +818,7 @@ class TokenInstruction extends Instruction { required int space, required int decimals, Ed25519HDPublicKey? freezeAuthority, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => [ SystemInstruction.createAccount( @@ -598,13 +826,14 @@ class TokenInstruction extends Instruction { fundingAccount: mintAuthority, lamports: rent, space: space, - owner: Ed25519HDPublicKey.fromBase58(TokenProgram.programId), + owner: Ed25519HDPublicKey.fromBase58(tokenProgram.programId), ), TokenInstruction.initializeMint( mint: mint, decimals: decimals, mintAuthority: mintAuthority, freezeAuthority: freezeAuthority, + tokenProgram: tokenProgram, ), ]; @@ -627,6 +856,7 @@ class TokenInstruction extends Instruction { required Ed25519HDPublicKey owner, required int rent, required int space, + TokenProgramType tokenProgram = TokenProgramType.tokenProgram, }) => [ SystemInstruction.createAccount( @@ -634,12 +864,13 @@ class TokenInstruction extends Instruction { fundingAccount: owner, lamports: rent, space: space, - owner: Ed25519HDPublicKey.fromBase58(TokenProgram.programId), + owner: Ed25519HDPublicKey.fromBase58(tokenProgram.programId), ), TokenInstruction.initializeAccount( mint: mint, account: address, owner: owner, + tokenProgram: tokenProgram, ), ]; } diff --git a/packages/solana/lib/src/programs/token_program/program.dart b/packages/solana/lib/src/programs/token_program/program.dart index 3e6bd5301..cbf44fa11 100644 --- a/packages/solana/lib/src/programs/token_program/program.dart +++ b/packages/solana/lib/src/programs/token_program/program.dart @@ -2,9 +2,11 @@ import 'package:solana/src/crypto/ed25519_hd_public_key.dart'; import 'package:solana/src/encoder/byte_array.dart'; export 'exceptions.dart'; +export 'extension_type.dart'; export 'instruction.dart'; export 'mint.dart'; export 'solana_client_ext.dart'; +export 'token_program_type.dart'; /// Construct token programs conveniently abstract class TokenProgram { @@ -34,6 +36,10 @@ abstract class TokenProgram { static final initializeAccount3InstructionIndex = ByteArray(const [18]); static final initializeMultisig2InstructionIndex = ByteArray(const [19]); static final initializeMint2InstructionIndex = ByteArray(const [20]); + static final getAccountDataSizeInstructionIndex = ByteArray(const [21]); + static final initializeImmutableOwnerInstructionIndex = ByteArray(const [22]); + static final amountToUiAmountInstructionIndex = ByteArray(const [23]); + static final uiAmountToAmountInstructionIndex = ByteArray(const [24]); // This is computed by adding the bytes in the following // structure @@ -63,3 +69,40 @@ abstract class TokenProgram { // closeAuthority: PubKey (32 bytes) static const neededAccountSpace = 165; } + +abstract class Token2022Program { + static const programId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'; + + static final Ed25519HDPublicKey id = Ed25519HDPublicKey.fromBase58(programId); + + // Token 2022 Instruction indexes + static final initializeMintCloseAuthorityInstructionIndex = + ByteArray(const [25]); + static final transferFeeExtensionInstructionIndex = ByteArray(const [26]); + static final confidentialTransferExtensionInstructionIndex = + ByteArray(const [27]); + static final defaultAccountStateExtensionInstructionIndex = + ByteArray(const [28]); + static final reallocateInstructionIndex = ByteArray(const [29]); + static final memoTransferExtensionInstructionIndex = ByteArray(const [30]); + static final createNativeMintInstructionIndex = ByteArray(const [31]); + static final initializeNonTransferableMintInstructionIndex = + ByteArray(const [32]); + static final interestBearingMintExtensionInstructionIndex = + ByteArray(const [33]); + static final cpiGuardExtensionInstructionIndex = ByteArray(const [34]); + static final initializePermanentDelegateInstructionIndex = + ByteArray(const [35]); + static final transferHookExtensionInstructionIndex = ByteArray(const [36]); + static final confidentialTransferFeeExtensionInstructionIndex = + ByteArray(const [37]); + static final withdrawExcessLamportsInstructionIndex = ByteArray(const [38]); + static final metadataPointerExtensionInstructionIndex = ByteArray(const [39]); + static final groupPointerExtensionInstructionIndex = ByteArray(const [40]); + static final groupMemberPointerExtensionInstructionIndex = + ByteArray(const [41]); +} + +final nativeMint2022 = Ed25519HDPublicKey.fromBase58( + '9pan9bMn5HatX4EJdBwg9VgCa7Uz5HL8N1m5D3NdXejP', +); diff --git a/packages/solana/lib/src/programs/token_program/solana_client_ext.dart b/packages/solana/lib/src/programs/token_program/solana_client_ext.dart index f187cdea0..d0fe043db 100644 --- a/packages/solana/lib/src/programs/token_program/solana_client_ext.dart +++ b/packages/solana/lib/src/programs/token_program/solana_client_ext.dart @@ -59,6 +59,7 @@ extension SolanaClientTokenProgram on SolanaClient { required int decimals, Ed25519HDPublicKey? freezeAuthority, SignatureCallback? onSigned, + TokenProgramType tokenProgramType = TokenProgramType.tokenProgram, Commitment commitment = Commitment.finalized, }) async { final mint = await Ed25519HDKeyPair.random(); @@ -76,6 +77,7 @@ extension SolanaClientTokenProgram on SolanaClient { rent: rent, space: space, decimals: decimals, + tokenProgram: tokenProgramType, ); final message = Message(instructions: instructions); diff --git a/packages/solana/lib/src/programs/token_program/token_program_type.dart b/packages/solana/lib/src/programs/token_program/token_program_type.dart new file mode 100644 index 000000000..7d9308f27 --- /dev/null +++ b/packages/solana/lib/src/programs/token_program/token_program_type.dart @@ -0,0 +1,26 @@ +import 'package:solana/solana.dart'; + +enum TokenProgramType { + tokenProgram, + token2022Program, +} + +extension TokenProgramTypeExt on TokenProgramType { + Ed25519HDPublicKey get id { + switch (this) { + case TokenProgramType.tokenProgram: + return TokenProgram.id; + case TokenProgramType.token2022Program: + return Token2022Program.id; + } + } + + String get programId { + switch (this) { + case TokenProgramType.tokenProgram: + return TokenProgram.programId; + case TokenProgramType.token2022Program: + return Token2022Program.programId; + } + } +} diff --git a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.dart b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.dart index 5f82ca67d..2e7060fdc 100644 --- a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.dart +++ b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.dart @@ -11,6 +11,11 @@ class ParsedAccountData with _$ParsedAccountData implements AccountData { SplTokenProgramAccountData parsed, ) = ParsedSplTokenProgramAccountData; + @FreezedUnionValue('spl-token-2022') + const factory ParsedAccountData.token2022( + SplTokenProgramAccountData parsed, + ) = ParsedSplToken2022ProgramAccountData; + const factory ParsedAccountData.stake( StakeProgramAccountData parsed, ) = ParsedStakeProgramAccountData; diff --git a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.freezed.dart b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.freezed.dart index 16724b571..6470a4226 100644 --- a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.freezed.dart +++ b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.freezed.dart @@ -12,12 +12,14 @@ part of 'parsed_account_data.dart'; T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); ParsedAccountData _$ParsedAccountDataFromJson(Map json) { switch (json['program']) { case 'spl-token': return ParsedSplTokenProgramAccountData.fromJson(json); + case 'spl-token-2022': + return ParsedSplToken2022ProgramAccountData.fromJson(json); case 'stake': return ParsedStakeProgramAccountData.fromJson(json); @@ -32,6 +34,7 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult when({ required TResult Function(SplTokenProgramAccountData parsed) splToken, + required TResult Function(SplTokenProgramAccountData parsed) token2022, required TResult Function(StakeProgramAccountData parsed) stake, required TResult Function(Map parsed) unsupported, }) => @@ -39,6 +42,7 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult? whenOrNull({ TResult? Function(SplTokenProgramAccountData parsed)? splToken, + TResult? Function(SplTokenProgramAccountData parsed)? token2022, TResult? Function(StakeProgramAccountData parsed)? stake, TResult? Function(Map parsed)? unsupported, }) => @@ -46,6 +50,7 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult maybeWhen({ TResult Function(SplTokenProgramAccountData parsed)? splToken, + TResult Function(SplTokenProgramAccountData parsed)? token2022, TResult Function(StakeProgramAccountData parsed)? stake, TResult Function(Map parsed)? unsupported, required TResult orElse(), @@ -54,6 +59,8 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult map({ required TResult Function(ParsedSplTokenProgramAccountData value) splToken, + required TResult Function(ParsedSplToken2022ProgramAccountData value) + token2022, required TResult Function(ParsedStakeProgramAccountData value) stake, required TResult Function(UnsupportedProgramAccountData value) unsupported, }) => @@ -61,6 +68,7 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult? mapOrNull({ TResult? Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult? Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult? Function(ParsedStakeProgramAccountData value)? stake, TResult? Function(UnsupportedProgramAccountData value)? unsupported, }) => @@ -68,6 +76,7 @@ mixin _$ParsedAccountData { @optionalTypeArgs TResult maybeMap({ TResult Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult Function(ParsedStakeProgramAccountData value)? stake, TResult Function(UnsupportedProgramAccountData value)? unsupported, required TResult orElse(), @@ -185,6 +194,7 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult when({ required TResult Function(SplTokenProgramAccountData parsed) splToken, + required TResult Function(SplTokenProgramAccountData parsed) token2022, required TResult Function(StakeProgramAccountData parsed) stake, required TResult Function(Map parsed) unsupported, }) { @@ -195,6 +205,7 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult? whenOrNull({ TResult? Function(SplTokenProgramAccountData parsed)? splToken, + TResult? Function(SplTokenProgramAccountData parsed)? token2022, TResult? Function(StakeProgramAccountData parsed)? stake, TResult? Function(Map parsed)? unsupported, }) { @@ -205,6 +216,7 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult maybeWhen({ TResult Function(SplTokenProgramAccountData parsed)? splToken, + TResult Function(SplTokenProgramAccountData parsed)? token2022, TResult Function(StakeProgramAccountData parsed)? stake, TResult Function(Map parsed)? unsupported, required TResult orElse(), @@ -219,6 +231,8 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult map({ required TResult Function(ParsedSplTokenProgramAccountData value) splToken, + required TResult Function(ParsedSplToken2022ProgramAccountData value) + token2022, required TResult Function(ParsedStakeProgramAccountData value) stake, required TResult Function(UnsupportedProgramAccountData value) unsupported, }) { @@ -229,6 +243,7 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult? mapOrNull({ TResult? Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult? Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult? Function(ParsedStakeProgramAccountData value)? stake, TResult? Function(UnsupportedProgramAccountData value)? unsupported, }) { @@ -239,6 +254,7 @@ class _$ParsedSplTokenProgramAccountDataImpl @optionalTypeArgs TResult maybeMap({ TResult Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult Function(ParsedStakeProgramAccountData value)? stake, TResult Function(UnsupportedProgramAccountData value)? unsupported, required TResult orElse(), @@ -273,6 +289,194 @@ abstract class ParsedSplTokenProgramAccountData implements ParsedAccountData { get copyWith => throw _privateConstructorUsedError; } +/// @nodoc +abstract class _$$ParsedSplToken2022ProgramAccountDataImplCopyWith<$Res> { + factory _$$ParsedSplToken2022ProgramAccountDataImplCopyWith( + _$ParsedSplToken2022ProgramAccountDataImpl value, + $Res Function(_$ParsedSplToken2022ProgramAccountDataImpl) then) = + __$$ParsedSplToken2022ProgramAccountDataImplCopyWithImpl<$Res>; + @useResult + $Res call({SplTokenProgramAccountData parsed}); + + $SplTokenProgramAccountDataCopyWith<$Res> get parsed; +} + +/// @nodoc +class __$$ParsedSplToken2022ProgramAccountDataImplCopyWithImpl<$Res> + extends _$ParsedAccountDataCopyWithImpl<$Res, + _$ParsedSplToken2022ProgramAccountDataImpl> + implements _$$ParsedSplToken2022ProgramAccountDataImplCopyWith<$Res> { + __$$ParsedSplToken2022ProgramAccountDataImplCopyWithImpl( + _$ParsedSplToken2022ProgramAccountDataImpl _value, + $Res Function(_$ParsedSplToken2022ProgramAccountDataImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? parsed = null, + }) { + return _then(_$ParsedSplToken2022ProgramAccountDataImpl( + null == parsed + ? _value.parsed + : parsed // ignore: cast_nullable_to_non_nullable + as SplTokenProgramAccountData, + )); + } + + @override + @pragma('vm:prefer-inline') + $SplTokenProgramAccountDataCopyWith<$Res> get parsed { + return $SplTokenProgramAccountDataCopyWith<$Res>(_value.parsed, (value) { + return _then(_value.copyWith(parsed: value)); + }); + } +} + +/// @nodoc +@JsonSerializable() +class _$ParsedSplToken2022ProgramAccountDataImpl + implements ParsedSplToken2022ProgramAccountData { + const _$ParsedSplToken2022ProgramAccountDataImpl(this.parsed, + {final String? $type}) + : $type = $type ?? 'spl-token-2022'; + + factory _$ParsedSplToken2022ProgramAccountDataImpl.fromJson( + Map json) => + _$$ParsedSplToken2022ProgramAccountDataImplFromJson(json); + + @override + final SplTokenProgramAccountData parsed; + + @JsonKey(name: 'program') + final String $type; + + @override + String toString() { + return 'ParsedAccountData.token2022(parsed: $parsed)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ParsedSplToken2022ProgramAccountDataImpl && + (identical(other.parsed, parsed) || other.parsed == parsed)); + } + + @JsonKey(ignore: true) + @override + int get hashCode => Object.hash(runtimeType, parsed); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ParsedSplToken2022ProgramAccountDataImplCopyWith< + _$ParsedSplToken2022ProgramAccountDataImpl> + get copyWith => __$$ParsedSplToken2022ProgramAccountDataImplCopyWithImpl< + _$ParsedSplToken2022ProgramAccountDataImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(SplTokenProgramAccountData parsed) splToken, + required TResult Function(SplTokenProgramAccountData parsed) token2022, + required TResult Function(StakeProgramAccountData parsed) stake, + required TResult Function(Map parsed) unsupported, + }) { + return token2022(parsed); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(SplTokenProgramAccountData parsed)? splToken, + TResult? Function(SplTokenProgramAccountData parsed)? token2022, + TResult? Function(StakeProgramAccountData parsed)? stake, + TResult? Function(Map parsed)? unsupported, + }) { + return token2022?.call(parsed); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(SplTokenProgramAccountData parsed)? splToken, + TResult Function(SplTokenProgramAccountData parsed)? token2022, + TResult Function(StakeProgramAccountData parsed)? stake, + TResult Function(Map parsed)? unsupported, + required TResult orElse(), + }) { + if (token2022 != null) { + return token2022(parsed); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(ParsedSplTokenProgramAccountData value) splToken, + required TResult Function(ParsedSplToken2022ProgramAccountData value) + token2022, + required TResult Function(ParsedStakeProgramAccountData value) stake, + required TResult Function(UnsupportedProgramAccountData value) unsupported, + }) { + return token2022(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult? Function(ParsedSplToken2022ProgramAccountData value)? token2022, + TResult? Function(ParsedStakeProgramAccountData value)? stake, + TResult? Function(UnsupportedProgramAccountData value)? unsupported, + }) { + return token2022?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult Function(ParsedSplToken2022ProgramAccountData value)? token2022, + TResult Function(ParsedStakeProgramAccountData value)? stake, + TResult Function(UnsupportedProgramAccountData value)? unsupported, + required TResult orElse(), + }) { + if (token2022 != null) { + return token2022(this); + } + return orElse(); + } + + @override + Map toJson() { + return _$$ParsedSplToken2022ProgramAccountDataImplToJson( + this, + ); + } +} + +abstract class ParsedSplToken2022ProgramAccountData + implements ParsedAccountData { + const factory ParsedSplToken2022ProgramAccountData( + final SplTokenProgramAccountData parsed) = + _$ParsedSplToken2022ProgramAccountDataImpl; + + factory ParsedSplToken2022ProgramAccountData.fromJson( + Map json) = + _$ParsedSplToken2022ProgramAccountDataImpl.fromJson; + + @override + SplTokenProgramAccountData get parsed; + @JsonKey(ignore: true) + _$$ParsedSplToken2022ProgramAccountDataImplCopyWith< + _$ParsedSplToken2022ProgramAccountDataImpl> + get copyWith => throw _privateConstructorUsedError; +} + /// @nodoc abstract class _$$ParsedStakeProgramAccountDataImplCopyWith<$Res> { factory _$$ParsedStakeProgramAccountDataImplCopyWith( @@ -363,6 +567,7 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult when({ required TResult Function(SplTokenProgramAccountData parsed) splToken, + required TResult Function(SplTokenProgramAccountData parsed) token2022, required TResult Function(StakeProgramAccountData parsed) stake, required TResult Function(Map parsed) unsupported, }) { @@ -373,6 +578,7 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult? whenOrNull({ TResult? Function(SplTokenProgramAccountData parsed)? splToken, + TResult? Function(SplTokenProgramAccountData parsed)? token2022, TResult? Function(StakeProgramAccountData parsed)? stake, TResult? Function(Map parsed)? unsupported, }) { @@ -383,6 +589,7 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult maybeWhen({ TResult Function(SplTokenProgramAccountData parsed)? splToken, + TResult Function(SplTokenProgramAccountData parsed)? token2022, TResult Function(StakeProgramAccountData parsed)? stake, TResult Function(Map parsed)? unsupported, required TResult orElse(), @@ -397,6 +604,8 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult map({ required TResult Function(ParsedSplTokenProgramAccountData value) splToken, + required TResult Function(ParsedSplToken2022ProgramAccountData value) + token2022, required TResult Function(ParsedStakeProgramAccountData value) stake, required TResult Function(UnsupportedProgramAccountData value) unsupported, }) { @@ -407,6 +616,7 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult? mapOrNull({ TResult? Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult? Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult? Function(ParsedStakeProgramAccountData value)? stake, TResult? Function(UnsupportedProgramAccountData value)? unsupported, }) { @@ -417,6 +627,7 @@ class _$ParsedStakeProgramAccountDataImpl @optionalTypeArgs TResult maybeMap({ TResult Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult Function(ParsedStakeProgramAccountData value)? stake, TResult Function(UnsupportedProgramAccountData value)? unsupported, required TResult orElse(), @@ -539,6 +750,7 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult when({ required TResult Function(SplTokenProgramAccountData parsed) splToken, + required TResult Function(SplTokenProgramAccountData parsed) token2022, required TResult Function(StakeProgramAccountData parsed) stake, required TResult Function(Map parsed) unsupported, }) { @@ -549,6 +761,7 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult? whenOrNull({ TResult? Function(SplTokenProgramAccountData parsed)? splToken, + TResult? Function(SplTokenProgramAccountData parsed)? token2022, TResult? Function(StakeProgramAccountData parsed)? stake, TResult? Function(Map parsed)? unsupported, }) { @@ -559,6 +772,7 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult maybeWhen({ TResult Function(SplTokenProgramAccountData parsed)? splToken, + TResult Function(SplTokenProgramAccountData parsed)? token2022, TResult Function(StakeProgramAccountData parsed)? stake, TResult Function(Map parsed)? unsupported, required TResult orElse(), @@ -573,6 +787,8 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult map({ required TResult Function(ParsedSplTokenProgramAccountData value) splToken, + required TResult Function(ParsedSplToken2022ProgramAccountData value) + token2022, required TResult Function(ParsedStakeProgramAccountData value) stake, required TResult Function(UnsupportedProgramAccountData value) unsupported, }) { @@ -583,6 +799,7 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult? mapOrNull({ TResult? Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult? Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult? Function(ParsedStakeProgramAccountData value)? stake, TResult? Function(UnsupportedProgramAccountData value)? unsupported, }) { @@ -593,6 +810,7 @@ class _$UnsupportedProgramAccountDataImpl @optionalTypeArgs TResult maybeMap({ TResult Function(ParsedSplTokenProgramAccountData value)? splToken, + TResult Function(ParsedSplToken2022ProgramAccountData value)? token2022, TResult Function(ParsedStakeProgramAccountData value)? stake, TResult Function(UnsupportedProgramAccountData value)? unsupported, required TResult orElse(), diff --git a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.g.dart b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.g.dart index 0b192b055..54e34f5d1 100644 --- a/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.g.dart +++ b/packages/solana/lib/src/rpc/dto/account_data/parsed_account_data.g.dart @@ -22,6 +22,22 @@ Map _$$ParsedSplTokenProgramAccountDataImplToJson( 'program': instance.$type, }; +_$ParsedSplToken2022ProgramAccountDataImpl + _$$ParsedSplToken2022ProgramAccountDataImplFromJson( + Map json) => + _$ParsedSplToken2022ProgramAccountDataImpl( + SplTokenProgramAccountData.fromJson( + json['parsed'] as Map), + $type: json['program'] as String?, + ); + +Map _$$ParsedSplToken2022ProgramAccountDataImplToJson( + _$ParsedSplToken2022ProgramAccountDataImpl instance) => + { + 'parsed': instance.parsed.toJson(), + 'program': instance.$type, + }; + _$ParsedStakeProgramAccountDataImpl _$$ParsedStakeProgramAccountDataImplFromJson(Map json) => _$ParsedStakeProgramAccountDataImpl( diff --git a/packages/solana/lib/src/solana_pay/solana_client_ext.dart b/packages/solana/lib/src/solana_pay/solana_client_ext.dart index 2849fb5eb..c51843593 100644 --- a/packages/solana/lib/src/solana_pay/solana_client_ext.dart +++ b/packages/solana/lib/src/solana_pay/solana_client_ext.dart @@ -212,6 +212,7 @@ extension SolanaClientSolanaPay on SolanaClient { required Decimal amount, Ed25519HDPublicKey? splToken, Iterable? reference, + TokenProgramType tokenProgramType = TokenProgramType.tokenProgram, Commitment commitment = Commitment.finalized, }) async { final response = await rpcClient.getTransaction( @@ -247,8 +248,11 @@ extension SolanaClientSolanaPay on SolanaClient { postAmount = Decimal.fromInt(meta.postBalances[accountIndex]) .shift(-solDecimalPlaces); } else { - final recipientATA = - await findAssociatedTokenAddress(owner: recipient, mint: splToken); + final recipientATA = await findAssociatedTokenAddress( + owner: recipient, + mint: splToken, + tokenProgramType: tokenProgramType, + ); final accountIndex = (response.transaction as ParsedTransaction) .message .accountKeys