Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export function getAdvanceNonceAccountInstruction<
'SysvarRecentB1ockHashes11111111111111111111' as Address<'SysvarRecentB1ockHashes11111111111111111111'>;
}

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.nonceAccount),
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/allocate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function getAllocateInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [getAccountMeta(accounts.newAccount)],
programAddress,
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/allocateWithSeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function getAllocateWithSeedInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.newAccount),
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/assign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function getAssignInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [getAccountMeta(accounts.account)],
programAddress,
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/assignWithSeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export function getAssignWithSeedInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.account),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function getAuthorizeNonceAccountInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.nonceAccount),
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/createAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function getCreateAccountInstruction<
0
);

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.payer),
Expand Down
45 changes: 29 additions & 16 deletions clients/js/src/generated/instructions/createAccountWithSeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ export type CreateAccountWithSeedInstruction<
TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS,
TAccountPayer extends string | AccountMeta<string> = string,
TAccountNewAccount extends string | AccountMeta<string> = string,
TAccountBaseAccount extends string | AccountMeta<string> = string,
TAccountBaseAccount extends
| string
| AccountMeta<string>
| undefined = undefined,
TRemainingAccounts extends readonly AccountMeta<string>[] = [],
> = Instruction<TProgram> &
InstructionWithData<ReadonlyUint8Array> &
Expand All @@ -62,10 +65,14 @@ export type CreateAccountWithSeedInstruction<
TAccountNewAccount extends string
? WritableAccount<TAccountNewAccount>
: TAccountNewAccount,
TAccountBaseAccount extends string
? ReadonlySignerAccount<TAccountBaseAccount> &
AccountSignerMeta<TAccountBaseAccount>
: TAccountBaseAccount,
...(TAccountBaseAccount extends undefined
? []
: [
TAccountBaseAccount extends string
? ReadonlySignerAccount<TAccountBaseAccount> &
AccountSignerMeta<TAccountBaseAccount>
: TAccountBaseAccount,
]),
...TRemainingAccounts,
]
>;
Expand All @@ -74,15 +81,15 @@ export type CreateAccountWithSeedInstructionData = {
discriminator: number;
base: Address;
seed: string;
amount: bigint;
lamports: bigint;
space: bigint;
programAddress: Address;
};

export type CreateAccountWithSeedInstructionDataArgs = {
base: Address;
seed: string;
amount: number | bigint;
lamports: number | bigint;
space: number | bigint;
programAddress: Address;
};
Expand All @@ -93,7 +100,7 @@ export function getCreateAccountWithSeedInstructionDataEncoder(): Encoder<Create
['discriminator', getU32Encoder()],
['base', getAddressEncoder()],
['seed', addEncoderSizePrefix(getUtf8Encoder(), getU64Encoder())],
['amount', getU64Encoder()],
['lamports', getU64Encoder()],
['space', getU64Encoder()],
['programAddress', getAddressEncoder()],
]),
Expand All @@ -109,7 +116,7 @@ export function getCreateAccountWithSeedInstructionDataDecoder(): Decoder<Create
['discriminator', getU32Decoder()],
['base', getAddressDecoder()],
['seed', addDecoderSizePrefix(getUtf8Decoder(), getU64Decoder())],
['amount', getU64Decoder()],
['lamports', getU64Decoder()],
['space', getU64Decoder()],
['programAddress', getAddressDecoder()],
]);
Expand All @@ -132,10 +139,10 @@ export type CreateAccountWithSeedInput<
> = {
payer: TransactionSigner<TAccountPayer>;
newAccount: Address<TAccountNewAccount>;
baseAccount: TransactionSigner<TAccountBaseAccount>;
baseAccount?: TransactionSigner<TAccountBaseAccount>;
base: CreateAccountWithSeedInstructionDataArgs['base'];
seed: CreateAccountWithSeedInstructionDataArgs['seed'];
amount: CreateAccountWithSeedInstructionDataArgs['amount'];
lamports: CreateAccountWithSeedInstructionDataArgs['lamports'];
space: CreateAccountWithSeedInstructionDataArgs['space'];
programAddress: CreateAccountWithSeedInstructionDataArgs['programAddress'];
};
Expand Down Expand Up @@ -175,13 +182,13 @@ export function getCreateAccountWithSeedInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.payer),
getAccountMeta(accounts.newAccount),
getAccountMeta(accounts.baseAccount),
],
].filter(<T,>(x: T | undefined): x is T => x !== undefined),
programAddress,
data: getCreateAccountWithSeedInstructionDataEncoder().encode(
args as CreateAccountWithSeedInstructionDataArgs
Expand All @@ -204,7 +211,7 @@ export type ParsedCreateAccountWithSeedInstruction<
accounts: {
payer: TAccountMetas[0];
newAccount: TAccountMetas[1];
baseAccount: TAccountMetas[2];
baseAccount?: TAccountMetas[2] | undefined;
};
data: CreateAccountWithSeedInstructionData;
};
Expand All @@ -217,7 +224,7 @@ export function parseCreateAccountWithSeedInstruction<
InstructionWithAccounts<TAccountMetas> &
InstructionWithData<ReadonlyUint8Array>
): ParsedCreateAccountWithSeedInstruction<TProgram, TAccountMetas> {
if (instruction.accounts.length < 3) {
if (instruction.accounts.length < 2) {
// TODO: Coded error.
throw new Error('Not enough accounts');
}
Expand All @@ -227,12 +234,18 @@ export function parseCreateAccountWithSeedInstruction<
accountIndex += 1;
return accountMeta;
};
let optionalAccountsRemaining = instruction.accounts.length - 2;
const getNextOptionalAccount = () => {
if (optionalAccountsRemaining === 0) return undefined;
optionalAccountsRemaining -= 1;
return getNextAccount();
};
return {
programAddress: instruction.programAddress,
accounts: {
payer: getNextAccount(),
newAccount: getNextAccount(),
baseAccount: getNextAccount(),
baseAccount: getNextOptionalAccount(),
},
data: getCreateAccountWithSeedInstructionDataDecoder().decode(
instruction.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export function getInitializeNonceAccountInstruction<
'SysvarRent111111111111111111111111111111111' as Address<'SysvarRent111111111111111111111111111111111'>;
}

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.nonceAccount),
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/transferSol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export function getTransferSolInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.source),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export function getTransferSolWithSeedInstruction<
// Original args.
const args = { ...input };

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.source),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function getUpgradeNonceAccountInstruction<
ResolvedAccount
>;

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [getAccountMeta(accounts.nonceAccount)],
programAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export function getWithdrawNonceAccountInstruction<
'SysvarRent111111111111111111111111111111111' as Address<'SysvarRent111111111111111111111111111111111'>;
}

const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted');
const instruction = {
accounts: [
getAccountMeta(accounts.nonceAccount),
Expand Down
82 changes: 82 additions & 0 deletions clients/js/test/createAccountWithSeed.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
appendTransactionMessageInstruction,
createAddressWithSeed,
fetchEncodedAccount,
generateKeyPairSigner,
KeyPairSigner,
pipe,
} from '@solana/kit';
import test, { ExecutionContext } from 'ava';
import { getCreateAccountWithSeedInstruction } from '../src';
import {
createDefaultSolanaClient,
createDefaultTransaction,
generateKeyPairSignerWithSol,
signAndSendTransaction,
} from './_setup';

async function createAccountWithSeedTest(
t: ExecutionContext<unknown>,
baseIsPayer: boolean
) {
const client = createDefaultSolanaClient();
const space = 42n;
const [payer, program, lamports] = await Promise.all([
generateKeyPairSignerWithSol(client),
generateKeyPairSigner(),
client.rpc.getMinimumBalanceForRentExemption(space).send(),
]);
let baseAccount = await generateKeyPairSigner();

if (baseIsPayer) {
baseAccount = payer;
}

const programAddress = program.address;
const SEED = '123456789';
const newAccount = await createAddressWithSeed({
baseAddress: baseAccount.address,
programAddress,
seed: SEED,
});

let extraArgs: {} | { baseAccount: KeyPairSigner<string> } = {};
if (!baseIsPayer) {
extraArgs = { baseAccount };
}

// When we call createAccountWithSeed in a transaction.
const createAccount = getCreateAccountWithSeedInstruction({
payer,
newAccount,
base: baseAccount.address,
seed: SEED,
space,
lamports,
programAddress,
...extraArgs,
});
await pipe(
await createDefaultTransaction(client, payer),
(tx) => appendTransactionMessageInstruction(createAccount, tx),
(tx) => signAndSendTransaction(client, tx)
);

// Then we expect the following account data.
const fetchedAccount = await fetchEncodedAccount(client.rpc, newAccount);
t.deepEqual(fetchedAccount, {
executable: false,
lamports,
programAddress,
address: newAccount,
data: new Uint8Array(Array.from({ length: 42 }, () => 0)),
exists: true,
space: 42n,
});
}

test('it creates a new empty account when base is not payer', (t) =>
createAccountWithSeedTest(t, false));

test('it creates a new empty account when base is payer', (t) =>
createAccountWithSeedTest(t, true));
Loading
Loading