From ab9fa9a69a436d512184d7c90675d549ca1752a1 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 18:19:45 +0200 Subject: [PATCH] token-js: add derivation of createAssociatedTokenAccountIdempotentInstruction (#7183) * add derivation of createAssociatedTokenAccountIdempotentInstruction * fix minor issues * fix format * fix lint * remove TODO comment --- .../instructions/associatedTokenAccount.ts | 33 +++++++++++++++++++ token/js/test/unit/index.test.ts | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/token/js/src/instructions/associatedTokenAccount.ts b/token/js/src/instructions/associatedTokenAccount.ts index 306425ddf32..d8d47c7bac9 100644 --- a/token/js/src/instructions/associatedTokenAccount.ts +++ b/token/js/src/instructions/associatedTokenAccount.ts @@ -1,6 +1,7 @@ import type { PublicKey } from '@solana/web3.js'; import { SystemProgram, TransactionInstruction } from '@solana/web3.js'; import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from '../constants.js'; +import { getAssociatedTokenAddressSync } from '../state/mint.js'; /** * Construct a CreateAssociatedTokenAccount instruction @@ -64,6 +65,38 @@ export function createAssociatedTokenAccountIdempotentInstruction( ); } +/** + * Derive the associated token account and construct a CreateAssociatedTokenAccountIdempotent instruction + * + * @param payer Payer of the initialization fees + * @param owner Owner of the new account + * @param mint Token mint account + * @param allowOwnerOffCurve Allow the owner account to be a PDA (Program Derived Address) + * @param programId SPL Token program account + * @param associatedTokenProgramId SPL Associated Token program account + * + * @return Instruction to add to a transaction + */ +export function createAssociatedTokenAccountIdempotentInstructionWithDerivation( + payer: PublicKey, + owner: PublicKey, + mint: PublicKey, + allowOwnerOffCurve = true, + programId = TOKEN_PROGRAM_ID, + associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID, +) { + const associatedToken = getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve); + + return createAssociatedTokenAccountIdempotentInstruction( + payer, + associatedToken, + owner, + mint, + programId, + associatedTokenProgramId, + ); +} + function buildAssociatedTokenAccountInstruction( payer: PublicKey, associatedToken: PublicKey, diff --git a/token/js/test/unit/index.test.ts b/token/js/test/unit/index.test.ts index 60b155f7d07..c974bd0f292 100644 --- a/token/js/test/unit/index.test.ts +++ b/token/js/test/unit/index.test.ts @@ -3,6 +3,8 @@ import { expect, use } from 'chai'; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, + createAssociatedTokenAccountIdempotentInstruction, + createAssociatedTokenAccountIdempotentInstructionWithDerivation, createReallocateInstruction, createInitializeMintInstruction, createInitializeMint2Instruction, @@ -167,6 +169,37 @@ describe('spl-associated-token-account instructions', () => { expect(ix.programId).to.eql(ASSOCIATED_TOKEN_PROGRAM_ID); expect(ix.keys).to.have.length(6); }); + + it('create idempotent', () => { + const ix = createAssociatedTokenAccountIdempotentInstruction( + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, + ); + expect(ix.programId).to.eql(ASSOCIATED_TOKEN_PROGRAM_ID); + expect(ix.keys).to.have.length(6); + }); + + it('create idempotent with derivation', () => { + const ix = createAssociatedTokenAccountIdempotentInstructionWithDerivation( + Keypair.generate().publicKey, + Keypair.generate().publicKey, + Keypair.generate().publicKey, + ); + expect(ix.programId).to.eql(ASSOCIATED_TOKEN_PROGRAM_ID); + expect(ix.keys).to.have.length(6); + }); + + it('create idempotent with derivation same without', () => { + const payer = Keypair.generate().publicKey; + const owner = Keypair.generate().publicKey; + const mint = Keypair.generate().publicKey; + const associatedToken = getAssociatedTokenAddressSync(mint, owner, true); + const ix = createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint); + const ixDerivation = createAssociatedTokenAccountIdempotentInstructionWithDerivation(payer, owner, mint); + expect(ix).to.deep.eq(ixDerivation); + }); }); describe('state', () => {