From b217b4d443c46dd9912e53bb35c96ca70532dd77 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 01:53:51 +0200 Subject: [PATCH 1/5] add derivation of createAssociatedTokenAccountIdempotentInstruction --- .../instructions/associatedTokenAccount.ts | 33 ++++++++++++++++++ token/js/test/common.ts | 1 + token/js/test/unit/index.test.ts | 34 +++++++++++++++++++ 3 files changed, 68 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/common.ts b/token/js/test/common.ts index 06ff1ef7ebf..b554c8d7beb 100644 --- a/token/js/test/common.ts +++ b/token/js/test/common.ts @@ -5,6 +5,7 @@ import { TOKEN_PROGRAM_ID } from '../src'; export async function newAccountWithLamports(connection: Connection, lamports = 1000000): Promise { const account = Keypair.generate(); const signature = await connection.requestAirdrop(account.publicKey, lamports); + // TODO: use deprecated method await connection.confirmTransaction(signature); return account; } diff --git a/token/js/test/unit/index.test.ts b/token/js/test/unit/index.test.ts index 60b155f7d07..c3446f6d764 100644 --- a/token/js/test/unit/index.test.ts +++ b/token/js/test/unit/index.test.ts @@ -3,6 +3,7 @@ import { expect, use } from 'chai'; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, + createAssociatedTokenAccountIdempotentInstructionWithDerivation, createReallocateInstruction, createInitializeMintInstruction, createInitializeMint2Instruction, @@ -23,8 +24,10 @@ import { createAmountToUiAmountInstruction, createUiAmountToAmountInstruction, getMintLen, + createAssociatedTokenAccountIdempotentInstruction, } from '../../src'; import chaiAsPromised from 'chai-as-promised'; +import { generateKeyPairSync } from 'crypto'; use(chaiAsPromised); describe('spl-token instructions', () => { @@ -167,6 +170,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', () => { From ec88464612e47f152f38d189090b6155a2ac8790 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 02:00:35 +0200 Subject: [PATCH 2/5] fix minor issues --- token/js/test/unit/index.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/token/js/test/unit/index.test.ts b/token/js/test/unit/index.test.ts index c3446f6d764..656b2a44531 100644 --- a/token/js/test/unit/index.test.ts +++ b/token/js/test/unit/index.test.ts @@ -3,6 +3,7 @@ import { expect, use } from 'chai'; import { ASSOCIATED_TOKEN_PROGRAM_ID, createAssociatedTokenAccountInstruction, + createAssociatedTokenAccountIdempotentInstruction, createAssociatedTokenAccountIdempotentInstructionWithDerivation, createReallocateInstruction, createInitializeMintInstruction, @@ -24,10 +25,8 @@ import { createAmountToUiAmountInstruction, createUiAmountToAmountInstruction, getMintLen, - createAssociatedTokenAccountIdempotentInstruction, } from '../../src'; import chaiAsPromised from 'chai-as-promised'; -import { generateKeyPairSync } from 'crypto'; use(chaiAsPromised); describe('spl-token instructions', () => { @@ -198,7 +197,7 @@ describe('spl-associated-token-account instructions', () => { const mint = Keypair.generate().publicKey; const associatedToken = getAssociatedTokenAddressSync(mint, owner, true); const ix = createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint); - const ixDerivation = createAssociatedTokenAccountIdempotentInstructionWithDerivation(payer, owner, mint); + const ixDerivation = createAssociatedTokenAccountIdempotentInstructionWithDerivation(payer, owner, mint); expect(ix).to.deep.eq(ixDerivation); }); }); From 698f3ad7ac918598f1f288fe2d031dc24ad35a73 Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 08:54:22 +0200 Subject: [PATCH 3/5] fix format --- token/js/src/instructions/associatedTokenAccount.ts | 2 +- token/js/test/unit/index.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/token/js/src/instructions/associatedTokenAccount.ts b/token/js/src/instructions/associatedTokenAccount.ts index d8d47c7bac9..d4c5b4e35fd 100644 --- a/token/js/src/instructions/associatedTokenAccount.ts +++ b/token/js/src/instructions/associatedTokenAccount.ts @@ -1,7 +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'; +import { getAssociatedTokenAddressSync } from '../state'; /** * Construct a CreateAssociatedTokenAccount instruction diff --git a/token/js/test/unit/index.test.ts b/token/js/test/unit/index.test.ts index 656b2a44531..c974bd0f292 100644 --- a/token/js/test/unit/index.test.ts +++ b/token/js/test/unit/index.test.ts @@ -197,7 +197,7 @@ describe('spl-associated-token-account instructions', () => { const mint = Keypair.generate().publicKey; const associatedToken = getAssociatedTokenAddressSync(mint, owner, true); const ix = createAssociatedTokenAccountIdempotentInstruction(payer, associatedToken, owner, mint); - const ixDerivation = createAssociatedTokenAccountIdempotentInstructionWithDerivation(payer, owner, mint); + const ixDerivation = createAssociatedTokenAccountIdempotentInstructionWithDerivation(payer, owner, mint); expect(ix).to.deep.eq(ixDerivation); }); }); From 1cb3cdc2f04d1a09efb33832386ee09cceb0abda Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 09:02:49 +0200 Subject: [PATCH 4/5] fix lint --- token/js/src/instructions/associatedTokenAccount.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/token/js/src/instructions/associatedTokenAccount.ts b/token/js/src/instructions/associatedTokenAccount.ts index d4c5b4e35fd..d8d47c7bac9 100644 --- a/token/js/src/instructions/associatedTokenAccount.ts +++ b/token/js/src/instructions/associatedTokenAccount.ts @@ -1,7 +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'; +import { getAssociatedTokenAddressSync } from '../state/mint.js'; /** * Construct a CreateAssociatedTokenAccount instruction From e8b929ec8d19f923413dcc568d1d74d2c2a0c7ce Mon Sep 17 00:00:00 2001 From: Juan Aguilar Santillana Date: Fri, 23 Aug 2024 18:04:03 +0200 Subject: [PATCH 5/5] remove TODO comment --- token/js/test/common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/token/js/test/common.ts b/token/js/test/common.ts index b554c8d7beb..06ff1ef7ebf 100644 --- a/token/js/test/common.ts +++ b/token/js/test/common.ts @@ -5,7 +5,6 @@ import { TOKEN_PROGRAM_ID } from '../src'; export async function newAccountWithLamports(connection: Connection, lamports = 1000000): Promise { const account = Keypair.generate(); const signature = await connection.requestAirdrop(account.publicKey, lamports); - // TODO: use deprecated method await connection.confirmTransaction(signature); return account; }