Skip to content

Commit

Permalink
feat(associated token pda search): add tokenProgramId param
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the tokenProgramId param for the findAssociatedTokenPda() function breaks js tests which use instructions generated by Kinobi. It will also break any code relying on this function.
  • Loading branch information
shotgunofdeath committed Feb 7, 2024
1 parent 61fe45f commit bbac225
Show file tree
Hide file tree
Showing 12 changed files with 77 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ dist
.amman
.crates
.bin
.idea
1 change: 1 addition & 0 deletions clients/js/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.vercel
docs
.idea
2 changes: 1 addition & 1 deletion clients/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@metaplex-foundation/mpl-toolbox",
"version": "0.9.2",
"version": "0.9.3",
"description": "Auto-generated essential Solana and Metaplex programs",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down
7 changes: 5 additions & 2 deletions clients/js/src/createMintWithAssociatedToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '@metaplex-foundation/umi';
import { createMint, CreateMintArgs } from './createMint';
import { createAssociatedToken, mintTokensTo } from './generated';
import { findAssociatedTokenPda } from './hooked';
import { findAssociatedTokenPda, TOKEN_PROGRAM_ID } from './hooked';

// Inputs.
export type CreateMintWithAssociatedTokenArgs = Omit<
Expand Down Expand Up @@ -47,7 +47,10 @@ export function createMintWithAssociatedToken(
mintTokensTo(context, {
amount,
mint: input.mint.publicKey,
token: findAssociatedTokenPda(context, mintAndOwner),
token: findAssociatedTokenPda(context, {
...mintAndOwner,
tokenProgramId: TOKEN_PROGRAM_ID,
}),
mintAuthority:
input.mintAuthority && isSigner(input.mintAuthority)
? input.mintAuthority
Expand Down
6 changes: 4 additions & 2 deletions clients/js/src/hooked/AssociatedToken.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Context, Pda, PublicKey } from '@metaplex-foundation/umi';
import { publicKey } from '@metaplex-foundation/umi/serializers';
import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } from './constants';

export function findAssociatedTokenPda(
context: Pick<Context, 'eddsa' | 'programs'>,
Expand All @@ -8,14 +9,15 @@ export function findAssociatedTokenPda(
mint: PublicKey;
/** The owner of the token account */
owner: PublicKey;
/** The Token or Token2022 Program id */
tokenProgramId: typeof TOKEN_PROGRAM_ID | typeof TOKEN_2022_PROGRAM_ID;
}
): Pda {
const associatedTokenProgramId =
context.programs.getPublicKey('splAssociatedToken');
const tokenProgramId = context.programs.getPublicKey('splToken');
return context.eddsa.findPda(associatedTokenProgramId, [
publicKey().serialize(seeds.owner),
publicKey().serialize(tokenProgramId),
publicKey().serialize(seeds.tokenProgramId),
publicKey().serialize(seeds.mint),
]);
}
11 changes: 11 additions & 0 deletions clients/js/src/hooked/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { publicKey } from '@metaplex-foundation/umi';

/** Address of the SPL Token program */
export const TOKEN_PROGRAM_ID = publicKey(
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
);

/** Address of the SPL Token 2022 program */
export const TOKEN_2022_PROGRAM_ID = publicKey(
'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'
);
1 change: 1 addition & 0 deletions clients/js/src/hooked/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './AssociatedToken';
export * from './resolvers';
export * from './constants';
3 changes: 3 additions & 0 deletions clients/js/test/createAssociatedToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
getTokenSize,
Token,
TokenState,
TOKEN_PROGRAM_ID,
} from '../src';
import { createUmi } from './_setup';

Expand All @@ -32,6 +33,7 @@ test('it can create new associated token accounts with minimum configuration', a
const [ata] = findAssociatedTokenPda(umi, {
mint: newMint.publicKey,
owner: umi.identity.publicKey,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
Expand Down Expand Up @@ -62,6 +64,7 @@ test('it can create new associated token accounts with maximum configuration', a
const [ata] = findAssociatedTokenPda(umi, {
mint: newMint.publicKey,
owner: newOwner.publicKey,
tokenProgramId: TOKEN_PROGRAM_ID,
});
await createMint(umi, { mint: newMint }).sendAndConfirm(umi);

Expand Down
7 changes: 6 additions & 1 deletion clients/js/test/createLutForTransactionBuilder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
findAddressLookupTablePda,
findAssociatedTokenPda,
transferSol,
TOKEN_PROGRAM_ID,
} from '../src';
import { createUmi } from './_setup';

Expand All @@ -24,7 +25,11 @@ test('it generates LUT builders for a given transaction builder', async (t) => {
// And a base builder that creates an associated token account.
const mint = generateSigner(umi);
const owner = generateSigner(umi).publicKey;
const [ata] = findAssociatedTokenPda(umi, { mint: mint.publicKey, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const baseBuilder = transactionBuilder()
.add(createMint(umi, { mint }))
.add(createAssociatedToken(umi, { mint: mint.publicKey, owner }));
Expand Down
26 changes: 22 additions & 4 deletions clients/js/test/createMintWithAssociatedToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Mint,
Token,
TokenState,
TOKEN_PROGRAM_ID,
} from '../src';
import { createUmi } from './_setup';

Expand All @@ -37,7 +38,11 @@ test('it can create a new mint and token account with no tokens', async (t) => {
});

// And a new associated token account with no tokens.
const [ata] = findAssociatedTokenPda(umi, { mint: mint.publicKey, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
publicKey: ata,
Expand Down Expand Up @@ -77,7 +82,11 @@ test('it can create a new mint and token account with a single token', async (t)
});

// And a new associated token account with one token.
const [ata] = findAssociatedTokenPda(umi, { mint: mint.publicKey, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
publicKey: ata,
Expand Down Expand Up @@ -117,7 +126,11 @@ test('it can create a new mint and token account with many tokens', async (t) =>
});

// And a new associated token account with 42 tokens.
const [ata] = findAssociatedTokenPda(umi, { mint: mint.publicKey, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
publicKey: ata,
Expand Down Expand Up @@ -158,7 +171,11 @@ test('it can create a new mint and token account with decimals', async (t) => {
});

// And a new associated token account with 42 tokens.
const [ata] = findAssociatedTokenPda(umi, { mint: mint.publicKey, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
publicKey: ata,
Expand Down Expand Up @@ -196,6 +213,7 @@ test('it defaults to using the identity as the owner', async (t) => {
const [ata] = findAssociatedTokenPda(umi, {
mint: mint.publicKey,
owner: umi.identity.publicKey,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const tokenAccount = await fetchToken(umi, ata);
t.like(tokenAccount, <Token>{
Expand Down
25 changes: 21 additions & 4 deletions clients/js/test/createTokenIfMissing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
TokExInvalidTokenMintError,
TokExInvalidTokenOwnerError,
TokExInvalidTokenProgramError,
TOKEN_PROGRAM_ID,
} from '../src';
import { createMint, createUmi } from './_setup';

Expand All @@ -35,7 +36,11 @@ test('it creates a new associated token if missing', async (t) => {
await createTokenIfMissing(umi, { mint, owner }).sendAndConfirm(umi);

// Then a new associated token account was created.
const [ata] = findAssociatedTokenPda(umi, { mint, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const ataAccount = await fetchToken(umi, ata);
t.like(ataAccount, <Token>{
publicKey: ata,
Expand All @@ -56,7 +61,11 @@ test('it defaults to the identity if no owner is provided', async (t) => {
await createTokenIfMissing(umi, { mint }).sendAndConfirm(umi);

// Then a new associated token account was created for the identity.
const [ata] = findAssociatedTokenPda(umi, { mint, owner: identity });
const [ata] = findAssociatedTokenPda(umi, {
mint,
owner: identity,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const ataAccount = await fetchToken(umi, ata);
t.like(ataAccount, <Token>{
publicKey: ata,
Expand All @@ -83,7 +92,11 @@ test('the payer pays for the storage fees if a token account gets created', asyn
t.deepEqual(payerBalance, subtractAmounts(sol(100), storageFee));

// And this matches the lamports on the ATA account.
const ata = findAssociatedTokenPda(umi, { mint, owner: identity });
const ata = findAssociatedTokenPda(umi, {
mint,
owner: identity,
tokenProgramId: TOKEN_PROGRAM_ID,
});
const ataAccount = await fetchToken(umi, ata);
t.deepEqual(ataAccount.header.lamports, storageFee);
});
Expand All @@ -93,7 +106,11 @@ test('it does not create an account if an associated token account already exist
const umi = await createUmi();
const mint = (await createMint(umi)).publicKey;
const owner = generateSigner(umi).publicKey;
const [ata] = findAssociatedTokenPda(umi, { mint, owner });
const [ata] = findAssociatedTokenPda(umi, {
mint,
owner,
tokenProgramId: TOKEN_PROGRAM_ID,
});
await createAssociatedToken(umi, { mint, owner }).sendAndConfirm(umi);
t.true(await umi.rpc.accountExists(ata));

Expand Down
1 change: 1 addition & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bbac225

Please sign in to comment.