Skip to content

Commit

Permalink
Add memo transfer to post init helper
Browse files Browse the repository at this point in the history
  • Loading branch information
lorisleiva committed Oct 10, 2024
1 parent dac96d9 commit fa472f0
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 28 deletions.
17 changes: 13 additions & 4 deletions clients/js/src/getInitializeInstructionsForExtensions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Address, IInstruction } from '@solana/web3.js';
import { Address, IInstruction, TransactionSigner } from '@solana/web3.js';
import {
ExtensionArgs,
getDisableMemoTransfersInstruction,
getEnableMemoTransfersInstruction,
getInitializeConfidentialTransferMintInstruction,
getInitializeDefaultAccountStateInstruction,
getInitializeTransferFeeConfigInstruction,
Expand Down Expand Up @@ -66,16 +68,23 @@ export function getPostInitializeInstructionsForMintExtensions(
}

/**
* Given a token address and a list of token extensions, returns a list of
* instructions that MUST be run _after_ the `initializeAccount` instruction
* Given a token address, its owner and a list of token extensions, returns a list
* of instructions that MUST be run _after_ the `initializeAccount` instruction
* to properly initialize the given extensions on the token account.
*/
export function getPostInitializeInstructionsForTokenExtensions(
_token: Address,
token: Address,
owner: TransactionSigner,
extensions: ExtensionArgs[]
): IInstruction[] {
return extensions.flatMap((extension) => {
switch (extension.__kind) {
case 'MemoTransfer':
return [
extension.requireIncomingTransferMemos
? getEnableMemoTransfersInstruction({ owner, token })
: getDisableMemoTransfersInstruction({ owner, token }),
];
default:
return [];
}
Expand Down
30 changes: 25 additions & 5 deletions clients/js/test/_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
getMintToInstruction,
getTokenSize,
getPostInitializeInstructionsForMintExtensions,
getPostInitializeInstructionsForTokenExtensions,
} from '../src';

type Client = {
Expand Down Expand Up @@ -185,34 +186,53 @@ export const createMint = async (
};

export const createToken = async (
input: Omit<Parameters<typeof getCreateTokenInstructions>[0], 'token'>
input: Omit<
Parameters<typeof getCreateTokenInstructions>[0],
'token' | 'owner'
> & { owner: TransactionSigner }
): Promise<Address> => {
const token = await generateKeyPairSigner();
const [createAccount, initToken] = await getCreateTokenInstructions({
...input,
owner: input.owner.address,
token,
});
await sendAndConfirmInstructions(input.client, input.payer, [
createAccount,
initToken,
...getPostInitializeInstructionsForMintExtensions(
...getPostInitializeInstructionsForTokenExtensions(
token.address,
input.owner,
input.extensions ?? []
),
]);
return token.address;
};

export const createTokenWithAmount = async (
input: Omit<Parameters<typeof getCreateTokenInstructions>[0], 'token'> & {
input: Omit<
Parameters<typeof getCreateTokenInstructions>[0],
'token' | 'owner'
> & {
amount: number | bigint;
mintAuthority: TransactionSigner;
owner: TransactionSigner;
}
): Promise<Address> => {
const token = await generateKeyPairSigner();
const instructions = await getCreateTokenInstructions({ ...input, token });
const [createAccount, initToken] = await getCreateTokenInstructions({
...input,
owner: input.owner.address,
token,
});
await sendAndConfirmInstructions(input.client, input.payer, [
...instructions,
createAccount,
initToken,
...getPostInitializeInstructionsForTokenExtensions(
token.address,
input.owner,
input.extensions ?? []
),
getMintToInstruction({
mint: input.mint,
token: token.address,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Account, address, generateKeyPairSigner, some } from '@solana/web3.js';
import { Account, generateKeyPairSigner, some } from '@solana/web3.js';
import test from 'ava';
import {
AccountState,
Expand Down Expand Up @@ -65,9 +65,10 @@ test('it initializes a mint account with a default account state extension', asy
test('it initializes a token account with the default state defined on the mint account', async (t) => {
// Given some signer accounts.
const client = createDefaultSolanaClient();
const [authority, freezeAuthority] = await Promise.all([
const [authority, freezeAuthority, owner] = await Promise.all([
generateKeyPairSignerWithSol(client),
generateKeyPairSigner(),
generateKeyPairSigner(),
]);

// And a mint account initialized with a default account state extension.
Expand All @@ -82,12 +83,7 @@ test('it initializes a token account with the default state defined on the mint
});

// When we create a new token account for the mint.
const token = await createToken({
client,
mint,
owner: address('HHS1XymmkBpYAkg3XTbZLxgHa5n11PAWUCWdiVtRmzzS'),
payer: authority,
});
const token = await createToken({ client, mint, owner, payer: authority });

// Then we expect the token account to have the default state defined on the mint account.
const tokenAccount = await fetchToken(client.rpc, token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test('it disables an active memo transfers extension', async (t) => {
extension('MemoTransfer', { requireIncomingTransferMemos: true }),
],
mint,
owner: owner.address,
owner,
payer: authority,
});
await sendAndConfirmInstructions(client, authority, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test('it enables an disabled memo transfers extension', async (t) => {
extension('MemoTransfer', { requireIncomingTransferMemos: false }),
],
mint,
owner: owner.address,
owner,
payer: authority,
});
await sendAndConfirmInstructions(client, authority, [
Expand Down
2 changes: 1 addition & 1 deletion clients/js/test/extensions/reallocate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test('it reallocates token accounts to fit the provided extensions', async (t) =
const token = await createToken({
client,
mint,
owner: owner.address,
owner,
payer: authority,
});
t.is(await getAccountLength(client, token), 165);
Expand Down
7 changes: 1 addition & 6 deletions clients/js/test/mintTo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,7 @@ test('it mints tokens to a token account', async (t) => {
payer,
authority: mintAuthority.address,
});
const token = await createToken({
client,
payer,
mint,
owner: owner.address,
});
const token = await createToken({ client, payer, mint, owner });

// When the mint authority mints tokens to the token account.
const mintTo = getMintToInstruction({
Expand Down
4 changes: 2 additions & 2 deletions clients/js/test/transfer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ test('it transfers tokens from one account to another', async (t) => {
payer,
mintAuthority,
mint,
owner: ownerA.address,
owner: ownerA,
amount: 100n,
}),
createToken({ client, payer, mint, owner: ownerB.address }),
createToken({ client, payer, mint, owner: ownerB }),
]);

// When owner A transfers 50 tokens to owner B.
Expand Down

0 comments on commit fa472f0

Please sign in to comment.