diff --git a/clients/js/src/mintToATA.ts b/clients/js/src/mintToATA.ts index 238e62d1..d53d6662 100644 --- a/clients/js/src/mintToATA.ts +++ b/clients/js/src/mintToATA.ts @@ -1,4 +1,8 @@ import { InstructionPlan, sequentialInstructionPlan, Address, TransactionSigner } from '@solana/kit'; +import { + getAddressFromResolvedInstructionAccount, + type InstructionAccountInput, +} from '@solana/kit/program-client-core'; import { findAssociatedTokenPda, @@ -16,11 +20,11 @@ export type MintToATAInstructionPlanInput = { * Note: Use {@link getMintToATAInstructionPlanAsync} instead to derive this automatically. * Note: Use {@link findAssociatedTokenPda} to derive the associated token account address. */ - ata: Address; + ata: InstructionAccountInput; /** Wallet address for the associated token account. */ - owner: Address; + owner: InstructionAccountInput; /** The token mint for the associated token account. */ - mint: Address; + mint: InstructionAccountInput; /** The mint's minting authority or its multisignature account. */ mintAuthority: Address | TransactionSigner; /** The amount of new tokens to mint. */ @@ -81,9 +85,9 @@ export async function getMintToATAInstructionPlanAsync( let ata = input.ata; if (!ata) { [ata] = await findAssociatedTokenPda({ - owner: input.owner, + owner: getAddressFromResolvedInstructionAccount('owner', input.owner), tokenProgram, - mint: input.mint, + mint: getAddressFromResolvedInstructionAccount('mint', input.mint), }); } return getMintToATAInstructionPlan( diff --git a/clients/js/src/transferToATA.ts b/clients/js/src/transferToATA.ts index 449461b2..b0157e1b 100644 --- a/clients/js/src/transferToATA.ts +++ b/clients/js/src/transferToATA.ts @@ -1,4 +1,8 @@ import { InstructionPlan, sequentialInstructionPlan, Address, TransactionSigner } from '@solana/kit'; +import { + getAddressFromResolvedInstructionAccount, + type InstructionAccountInput, +} from '@solana/kit/program-client-core'; import { findAssociatedTokenPda, @@ -12,9 +16,9 @@ export type TransferToATAInstructionPlanInput = { /** Funding account (must be a system account). */ payer: TransactionSigner; /** The token mint to transfer. */ - mint: Address; + mint: InstructionAccountInput; /** The source account for the transfer. */ - source: Address; + source: InstructionAccountInput; /** The source account's owner/delegate or its multisignature account. */ authority: Address | TransactionSigner; /** Associated token account address to transfer to. @@ -22,9 +26,9 @@ export type TransferToATAInstructionPlanInput = { * Note: Use {@link getTransferToATAInstructionPlanAsync} instead to derive this automatically. * Note: Use {@link findAssociatedTokenPda} to derive the associated token account address. */ - destination: Address; + destination: InstructionAccountInput; /** Wallet address for the destination. */ - recipient: Address; + recipient: InstructionAccountInput; /** The amount of tokens to transfer. */ amount: number | bigint; /** Expected number of base 10 digits to the right of the decimal place. */ @@ -84,23 +88,23 @@ export async function getTransferToATAInstructionPlanAsync( ): Promise { const tokenProgram = config?.tokenProgram ?? TOKEN_PROGRAM_ADDRESS; + const mint = getAddressFromResolvedInstructionAccount('mint', input.mint); + let destination = input.destination; if (!destination) { [destination] = await findAssociatedTokenPda({ - owner: input.recipient, + owner: getAddressFromResolvedInstructionAccount('recipient', input.recipient), tokenProgram, - mint: input.mint, + mint, }); } let source = input.source; if (!source) { - const authorityAddress: Address = - typeof input.authority === 'string' ? input.authority : input.authority.address; const [sourceAta] = await findAssociatedTokenPda({ - owner: authorityAddress, + owner: getAddressFromResolvedInstructionAccount('authority', input.authority), tokenProgram, - mint: input.mint, + mint, }); source = sourceAta; } diff --git a/clients/js/test/mintToATA.test.ts b/clients/js/test/mintToATA.test.ts index 89e20ce5..049e1888 100644 --- a/clients/js/test/mintToATA.test.ts +++ b/clients/js/test/mintToATA.test.ts @@ -129,3 +129,36 @@ it('also mints to an existing associated token account', async () => { }, }); }); + +it('accepts address wrappers for the mint and owner', async () => { + // Given a mint account, its mint authority and a token owner. + const client = await createTestClient(); + const [mintAuthority, owner, mint] = await Promise.all([ + generateKeyPairSigner(), + generateKeyPairSigner(), + generateKeyPairSigner(), + ]); + const decimals = 2; + await client.token.instructions + .createMint({ newMint: mint, decimals, mintAuthority: mintAuthority.address }) + .sendTransaction(); + + // When we mint to the owner using HasAddress wrappers. + await client.token.instructions + .mintToATA({ + mint: { address: mint.address }, + owner: { address: owner.address }, + mintAuthority, + amount: 1_000n, + decimals, + }) + .sendTransaction(); + + // Then we expect the derived ATA to hold the minted tokens. + const [ata] = await findAssociatedTokenPda({ + mint: mint.address, + owner: owner.address, + tokenProgram: TOKEN_PROGRAM_ADDRESS, + }); + expect(await fetchToken(client.rpc, ata)).toMatchObject({ data: { amount: 1000n } }); +}); diff --git a/clients/js/test/transferToATA.test.ts b/clients/js/test/transferToATA.test.ts index 812b2c36..48e42482 100644 --- a/clients/js/test/transferToATA.test.ts +++ b/clients/js/test/transferToATA.test.ts @@ -169,3 +169,43 @@ it('derives both source and destination ATAs and transfers tokens', async () => expect(tokenDataA).toMatchObject({ amount: 50n }); expect(tokenDataB).toMatchObject({ amount: 50n }); }); + +it('accepts address wrappers for the mint and recipient', async () => { + // Given a mint account and ownerA's ATA with 100 tokens. + const client = await createTestClient(); + const [mintAuthority, ownerA, ownerB, mint] = await Promise.all([ + generateKeyPairSigner(), + generateKeyPairSigner(), + generateKeyPairSigner(), + generateKeyPairSigner(), + ]); + const decimals = 2; + await client.token.instructions + .createMint({ newMint: mint, decimals, mintAuthority: mintAuthority.address }) + .sendTransaction(); + const tokenA = await createTokenPdaWithAmount(client, mintAuthority, mint.address, ownerA.address, 100n, decimals); + + // When owner A transfers 50 tokens to owner B using HasAddress wrappers. + await client.token.instructions + .transferToATA({ + mint: { address: mint.address }, + authority: ownerA, + recipient: { address: ownerB.address }, + amount: 50n, + decimals, + }) + .sendTransaction(); + + // Then we expect both ATAs to have the correct balances. + const [tokenB] = await findAssociatedTokenPda({ + owner: ownerB.address, + mint: mint.address, + tokenProgram: TOKEN_PROGRAM_ADDRESS, + }); + const [{ data: tokenDataA }, { data: tokenDataB }] = await Promise.all([ + fetchToken(client.rpc, tokenA), + fetchToken(client.rpc, tokenB), + ]); + expect(tokenDataA).toMatchObject({ amount: 50n }); + expect(tokenDataB).toMatchObject({ amount: 50n }); +});