From 9e26bcfbb98d8c02916c877df9479bf2139621fb Mon Sep 17 00:00:00 2001 From: Arrowana Date: Fri, 5 Sep 2025 17:33:12 +1000 Subject: [PATCH 1/8] fix: Base is optional --- .../instructions/advanceNonceAccount.ts | 2 +- .../js/src/generated/instructions/allocate.ts | 2 +- .../instructions/allocateWithSeed.ts | 35 ++- .../js/src/generated/instructions/assign.ts | 2 +- .../generated/instructions/assignWithSeed.ts | 35 ++- .../instructions/authorizeNonceAccount.ts | 2 +- .../generated/instructions/createAccount.ts | 2 +- .../instructions/createAccountWithSeed.ts | 35 ++- .../instructions/initializeNonceAccount.ts | 2 +- .../src/generated/instructions/transferSol.ts | 2 +- .../instructions/transferSolWithSeed.ts | 2 +- .../instructions/upgradeNonceAccount.ts | 2 +- .../instructions/withdrawNonceAccount.ts | 2 +- .../instructions/allocate_with_seed.rs | 54 ++-- .../instructions/assign_with_seed.rs | 54 ++-- .../instructions/create_account_with_seed.rs | 54 ++-- program/idl.json | 234 +++++++++++++----- 17 files changed, 349 insertions(+), 172 deletions(-) diff --git a/clients/js/src/generated/instructions/advanceNonceAccount.ts b/clients/js/src/generated/instructions/advanceNonceAccount.ts index 7341d77..c07ef01 100644 --- a/clients/js/src/generated/instructions/advanceNonceAccount.ts +++ b/clients/js/src/generated/instructions/advanceNonceAccount.ts @@ -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), diff --git a/clients/js/src/generated/instructions/allocate.ts b/clients/js/src/generated/instructions/allocate.ts index ed7801e..388d387 100644 --- a/clients/js/src/generated/instructions/allocate.ts +++ b/clients/js/src/generated/instructions/allocate.ts @@ -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, diff --git a/clients/js/src/generated/instructions/allocateWithSeed.ts b/clients/js/src/generated/instructions/allocateWithSeed.ts index 243bbd8..31c004e 100644 --- a/clients/js/src/generated/instructions/allocateWithSeed.ts +++ b/clients/js/src/generated/instructions/allocateWithSeed.ts @@ -47,7 +47,10 @@ export function getAllocateWithSeedDiscriminatorBytes() { export type AllocateWithSeedInstruction< TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, TAccountNewAccount extends string | AccountMeta = string, - TAccountBaseAccount extends string | AccountMeta = string, + TAccountBaseAccount extends + | string + | AccountMeta + | undefined = undefined, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & @@ -56,10 +59,14 @@ export type AllocateWithSeedInstruction< TAccountNewAccount extends string ? WritableAccount : TAccountNewAccount, - TAccountBaseAccount extends string - ? ReadonlySignerAccount & - AccountSignerMeta - : TAccountBaseAccount, + ...(TAccountBaseAccount extends undefined + ? [] + : [ + TAccountBaseAccount extends string + ? ReadonlySignerAccount & + AccountSignerMeta + : TAccountBaseAccount, + ]), ...TRemainingAccounts, ] >; @@ -117,7 +124,7 @@ export type AllocateWithSeedInput< TAccountBaseAccount extends string = string, > = { newAccount: Address; - baseAccount: TransactionSigner; + baseAccount?: TransactionSigner; base: AllocateWithSeedInstructionDataArgs['base']; seed: AllocateWithSeedInstructionDataArgs['seed']; space: AllocateWithSeedInstructionDataArgs['space']; @@ -152,12 +159,12 @@ export function getAllocateWithSeedInstruction< // Original args. const args = { ...input }; - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted'); const instruction = { accounts: [ getAccountMeta(accounts.newAccount), getAccountMeta(accounts.baseAccount), - ], + ].filter((x: T | undefined): x is T => x !== undefined), programAddress, data: getAllocateWithSeedInstructionDataEncoder().encode( args as AllocateWithSeedInstructionDataArgs @@ -178,7 +185,7 @@ export type ParsedAllocateWithSeedInstruction< programAddress: Address; accounts: { newAccount: TAccountMetas[0]; - baseAccount: TAccountMetas[1]; + baseAccount?: TAccountMetas[1] | undefined; }; data: AllocateWithSeedInstructionData; }; @@ -191,7 +198,7 @@ export function parseAllocateWithSeedInstruction< InstructionWithAccounts & InstructionWithData ): ParsedAllocateWithSeedInstruction { - if (instruction.accounts.length < 2) { + if (instruction.accounts.length < 1) { // TODO: Coded error. throw new Error('Not enough accounts'); } @@ -201,11 +208,17 @@ export function parseAllocateWithSeedInstruction< accountIndex += 1; return accountMeta; }; + let optionalAccountsRemaining = instruction.accounts.length - 1; + const getNextOptionalAccount = () => { + if (optionalAccountsRemaining === 0) return undefined; + optionalAccountsRemaining -= 1; + return getNextAccount(); + }; return { programAddress: instruction.programAddress, accounts: { newAccount: getNextAccount(), - baseAccount: getNextAccount(), + baseAccount: getNextOptionalAccount(), }, data: getAllocateWithSeedInstructionDataDecoder().decode(instruction.data), }; diff --git a/clients/js/src/generated/instructions/assign.ts b/clients/js/src/generated/instructions/assign.ts index 4721cee..925bbaa 100644 --- a/clients/js/src/generated/instructions/assign.ts +++ b/clients/js/src/generated/instructions/assign.ts @@ -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, diff --git a/clients/js/src/generated/instructions/assignWithSeed.ts b/clients/js/src/generated/instructions/assignWithSeed.ts index 081725e..b67031a 100644 --- a/clients/js/src/generated/instructions/assignWithSeed.ts +++ b/clients/js/src/generated/instructions/assignWithSeed.ts @@ -47,7 +47,10 @@ export function getAssignWithSeedDiscriminatorBytes() { export type AssignWithSeedInstruction< TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, TAccountAccount extends string | AccountMeta = string, - TAccountBaseAccount extends string | AccountMeta = string, + TAccountBaseAccount extends + | string + | AccountMeta + | undefined = undefined, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & @@ -56,10 +59,14 @@ export type AssignWithSeedInstruction< TAccountAccount extends string ? WritableAccount : TAccountAccount, - TAccountBaseAccount extends string - ? ReadonlySignerAccount & - AccountSignerMeta - : TAccountBaseAccount, + ...(TAccountBaseAccount extends undefined + ? [] + : [ + TAccountBaseAccount extends string + ? ReadonlySignerAccount & + AccountSignerMeta + : TAccountBaseAccount, + ]), ...TRemainingAccounts, ] >; @@ -113,7 +120,7 @@ export type AssignWithSeedInput< TAccountBaseAccount extends string = string, > = { account: Address; - baseAccount: TransactionSigner; + baseAccount?: TransactionSigner; base: AssignWithSeedInstructionDataArgs['base']; seed: AssignWithSeedInstructionDataArgs['seed']; programAddress: AssignWithSeedInstructionDataArgs['programAddress']; @@ -147,12 +154,12 @@ export function getAssignWithSeedInstruction< // Original args. const args = { ...input }; - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted'); const instruction = { accounts: [ getAccountMeta(accounts.account), getAccountMeta(accounts.baseAccount), - ], + ].filter((x: T | undefined): x is T => x !== undefined), programAddress, data: getAssignWithSeedInstructionDataEncoder().encode( args as AssignWithSeedInstructionDataArgs @@ -173,7 +180,7 @@ export type ParsedAssignWithSeedInstruction< programAddress: Address; accounts: { account: TAccountMetas[0]; - baseAccount: TAccountMetas[1]; + baseAccount?: TAccountMetas[1] | undefined; }; data: AssignWithSeedInstructionData; }; @@ -186,7 +193,7 @@ export function parseAssignWithSeedInstruction< InstructionWithAccounts & InstructionWithData ): ParsedAssignWithSeedInstruction { - if (instruction.accounts.length < 2) { + if (instruction.accounts.length < 1) { // TODO: Coded error. throw new Error('Not enough accounts'); } @@ -196,11 +203,17 @@ export function parseAssignWithSeedInstruction< accountIndex += 1; return accountMeta; }; + let optionalAccountsRemaining = instruction.accounts.length - 1; + const getNextOptionalAccount = () => { + if (optionalAccountsRemaining === 0) return undefined; + optionalAccountsRemaining -= 1; + return getNextAccount(); + }; return { programAddress: instruction.programAddress, accounts: { account: getNextAccount(), - baseAccount: getNextAccount(), + baseAccount: getNextOptionalAccount(), }, data: getAssignWithSeedInstructionDataDecoder().decode(instruction.data), }; diff --git a/clients/js/src/generated/instructions/authorizeNonceAccount.ts b/clients/js/src/generated/instructions/authorizeNonceAccount.ts index 3d695ff..2e5bcde 100644 --- a/clients/js/src/generated/instructions/authorizeNonceAccount.ts +++ b/clients/js/src/generated/instructions/authorizeNonceAccount.ts @@ -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), diff --git a/clients/js/src/generated/instructions/createAccount.ts b/clients/js/src/generated/instructions/createAccount.ts index 9dca20d..0a12bc1 100644 --- a/clients/js/src/generated/instructions/createAccount.ts +++ b/clients/js/src/generated/instructions/createAccount.ts @@ -155,7 +155,7 @@ export function getCreateAccountInstruction< 0 ); - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted'); const instruction = { accounts: [ getAccountMeta(accounts.payer), diff --git a/clients/js/src/generated/instructions/createAccountWithSeed.ts b/clients/js/src/generated/instructions/createAccountWithSeed.ts index ba42a37..700088e 100644 --- a/clients/js/src/generated/instructions/createAccountWithSeed.ts +++ b/clients/js/src/generated/instructions/createAccountWithSeed.ts @@ -49,7 +49,10 @@ export type CreateAccountWithSeedInstruction< TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, TAccountPayer extends string | AccountMeta = string, TAccountNewAccount extends string | AccountMeta = string, - TAccountBaseAccount extends string | AccountMeta = string, + TAccountBaseAccount extends + | string + | AccountMeta + | undefined = undefined, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & @@ -62,10 +65,14 @@ export type CreateAccountWithSeedInstruction< TAccountNewAccount extends string ? WritableAccount : TAccountNewAccount, - TAccountBaseAccount extends string - ? ReadonlySignerAccount & - AccountSignerMeta - : TAccountBaseAccount, + ...(TAccountBaseAccount extends undefined + ? [] + : [ + TAccountBaseAccount extends string + ? ReadonlySignerAccount & + AccountSignerMeta + : TAccountBaseAccount, + ]), ...TRemainingAccounts, ] >; @@ -132,7 +139,7 @@ export type CreateAccountWithSeedInput< > = { payer: TransactionSigner; newAccount: Address; - baseAccount: TransactionSigner; + baseAccount?: TransactionSigner; base: CreateAccountWithSeedInstructionDataArgs['base']; seed: CreateAccountWithSeedInstructionDataArgs['seed']; amount: CreateAccountWithSeedInstructionDataArgs['amount']; @@ -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((x: T | undefined): x is T => x !== undefined), programAddress, data: getCreateAccountWithSeedInstructionDataEncoder().encode( args as CreateAccountWithSeedInstructionDataArgs @@ -204,7 +211,7 @@ export type ParsedCreateAccountWithSeedInstruction< accounts: { payer: TAccountMetas[0]; newAccount: TAccountMetas[1]; - baseAccount: TAccountMetas[2]; + baseAccount?: TAccountMetas[2] | undefined; }; data: CreateAccountWithSeedInstructionData; }; @@ -217,7 +224,7 @@ export function parseCreateAccountWithSeedInstruction< InstructionWithAccounts & InstructionWithData ): ParsedCreateAccountWithSeedInstruction { - if (instruction.accounts.length < 3) { + if (instruction.accounts.length < 2) { // TODO: Coded error. throw new Error('Not enough accounts'); } @@ -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 diff --git a/clients/js/src/generated/instructions/initializeNonceAccount.ts b/clients/js/src/generated/instructions/initializeNonceAccount.ts index 358f1e4..e3caf71 100644 --- a/clients/js/src/generated/instructions/initializeNonceAccount.ts +++ b/clients/js/src/generated/instructions/initializeNonceAccount.ts @@ -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), diff --git a/clients/js/src/generated/instructions/transferSol.ts b/clients/js/src/generated/instructions/transferSol.ts index c2b520e..b8192f6 100644 --- a/clients/js/src/generated/instructions/transferSol.ts +++ b/clients/js/src/generated/instructions/transferSol.ts @@ -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), diff --git a/clients/js/src/generated/instructions/transferSolWithSeed.ts b/clients/js/src/generated/instructions/transferSolWithSeed.ts index df2483f..d0f4a55 100644 --- a/clients/js/src/generated/instructions/transferSolWithSeed.ts +++ b/clients/js/src/generated/instructions/transferSolWithSeed.ts @@ -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), diff --git a/clients/js/src/generated/instructions/upgradeNonceAccount.ts b/clients/js/src/generated/instructions/upgradeNonceAccount.ts index ce96cea..8f193f2 100644 --- a/clients/js/src/generated/instructions/upgradeNonceAccount.ts +++ b/clients/js/src/generated/instructions/upgradeNonceAccount.ts @@ -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, diff --git a/clients/js/src/generated/instructions/withdrawNonceAccount.ts b/clients/js/src/generated/instructions/withdrawNonceAccount.ts index 2a3b9ff..4905dea 100644 --- a/clients/js/src/generated/instructions/withdrawNonceAccount.ts +++ b/clients/js/src/generated/instructions/withdrawNonceAccount.ts @@ -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), diff --git a/clients/rust/src/generated/instructions/allocate_with_seed.rs b/clients/rust/src/generated/instructions/allocate_with_seed.rs index 71d3220..78f9d85 100644 --- a/clients/rust/src/generated/instructions/allocate_with_seed.rs +++ b/clients/rust/src/generated/instructions/allocate_with_seed.rs @@ -15,7 +15,7 @@ use solana_program::pubkey::Pubkey; pub struct AllocateWithSeed { pub new_account: solana_program::pubkey::Pubkey, - pub base_account: solana_program::pubkey::Pubkey, + pub base_account: Option, } impl AllocateWithSeed { @@ -37,10 +37,12 @@ impl AllocateWithSeed { self.new_account, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - self.base_account, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + base_account, + true, + )); + } accounts.extend_from_slice(remaining_accounts); let mut data = borsh::to_vec(&AllocateWithSeedInstructionData::new()).unwrap(); let mut args = borsh::to_vec(&args).unwrap(); @@ -86,7 +88,7 @@ pub struct AllocateWithSeedInstructionArgs { /// ### Accounts: /// /// 0. `[writable]` new_account -/// 1. `[signer]` base_account +/// 1. `[signer, optional]` base_account #[derive(Clone, Debug, Default)] pub struct AllocateWithSeedBuilder { new_account: Option, @@ -107,9 +109,13 @@ impl AllocateWithSeedBuilder { self.new_account = Some(new_account); self } + /// `[optional account]` #[inline(always)] - pub fn base_account(&mut self, base_account: solana_program::pubkey::Pubkey) -> &mut Self { - self.base_account = Some(base_account); + pub fn base_account( + &mut self, + base_account: Option, + ) -> &mut Self { + self.base_account = base_account; self } #[inline(always)] @@ -154,7 +160,7 @@ impl AllocateWithSeedBuilder { pub fn instruction(&self) -> solana_program::instruction::Instruction { let accounts = AllocateWithSeed { new_account: self.new_account.expect("new_account is not set"), - base_account: self.base_account.expect("base_account is not set"), + base_account: self.base_account, }; let args = AllocateWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), @@ -174,7 +180,7 @@ impl AllocateWithSeedBuilder { pub struct AllocateWithSeedCpiAccounts<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, } /// `allocate_with_seed` CPI instruction. @@ -184,7 +190,7 @@ pub struct AllocateWithSeedCpi<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The arguments for the instruction. pub __args: AllocateWithSeedInstructionArgs, } @@ -241,10 +247,12 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { *self.new_account.key, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *self.base_account.key, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *base_account.key, + true, + )); + } remaining_accounts.iter().for_each(|remaining_account| { accounts.push(solana_program::instruction::AccountMeta { pubkey: *remaining_account.0.key, @@ -264,7 +272,9 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); account_infos.push(self.__program.clone()); account_infos.push(self.new_account.clone()); - account_infos.push(self.base_account.clone()); + if let Some(base_account) = self.base_account { + account_infos.push(base_account.clone()); + } remaining_accounts .iter() .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); @@ -282,7 +292,7 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { /// ### Accounts: /// /// 0. `[writable]` new_account -/// 1. `[signer]` base_account +/// 1. `[signer, optional]` base_account #[derive(Clone, Debug)] pub struct AllocateWithSeedCpiBuilder<'a, 'b> { instruction: Box>, @@ -310,12 +320,13 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { self.instruction.new_account = Some(new_account); self } + /// `[optional account]` #[inline(always)] pub fn base_account( &mut self, - base_account: &'b solana_program::account_info::AccountInfo<'a>, + base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, ) -> &mut Self { - self.instruction.base_account = Some(base_account); + self.instruction.base_account = base_account; self } #[inline(always)] @@ -397,10 +408,7 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { .new_account .expect("new_account is not set"), - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/clients/rust/src/generated/instructions/assign_with_seed.rs b/clients/rust/src/generated/instructions/assign_with_seed.rs index 4ccbd59..683ce3c 100644 --- a/clients/rust/src/generated/instructions/assign_with_seed.rs +++ b/clients/rust/src/generated/instructions/assign_with_seed.rs @@ -15,7 +15,7 @@ use solana_program::pubkey::Pubkey; pub struct AssignWithSeed { pub account: solana_program::pubkey::Pubkey, - pub base_account: solana_program::pubkey::Pubkey, + pub base_account: Option, } impl AssignWithSeed { @@ -37,10 +37,12 @@ impl AssignWithSeed { self.account, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - self.base_account, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + base_account, + true, + )); + } accounts.extend_from_slice(remaining_accounts); let mut data = borsh::to_vec(&AssignWithSeedInstructionData::new()).unwrap(); let mut args = borsh::to_vec(&args).unwrap(); @@ -85,7 +87,7 @@ pub struct AssignWithSeedInstructionArgs { /// ### Accounts: /// /// 0. `[writable]` account -/// 1. `[signer]` base_account +/// 1. `[signer, optional]` base_account #[derive(Clone, Debug, Default)] pub struct AssignWithSeedBuilder { account: Option, @@ -105,9 +107,13 @@ impl AssignWithSeedBuilder { self.account = Some(account); self } + /// `[optional account]` #[inline(always)] - pub fn base_account(&mut self, base_account: solana_program::pubkey::Pubkey) -> &mut Self { - self.base_account = Some(base_account); + pub fn base_account( + &mut self, + base_account: Option, + ) -> &mut Self { + self.base_account = base_account; self } #[inline(always)] @@ -147,7 +153,7 @@ impl AssignWithSeedBuilder { pub fn instruction(&self) -> solana_program::instruction::Instruction { let accounts = AssignWithSeed { account: self.account.expect("account is not set"), - base_account: self.base_account.expect("base_account is not set"), + base_account: self.base_account, }; let args = AssignWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), @@ -166,7 +172,7 @@ impl AssignWithSeedBuilder { pub struct AssignWithSeedCpiAccounts<'a, 'b> { pub account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, } /// `assign_with_seed` CPI instruction. @@ -176,7 +182,7 @@ pub struct AssignWithSeedCpi<'a, 'b> { pub account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The arguments for the instruction. pub __args: AssignWithSeedInstructionArgs, } @@ -233,10 +239,12 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { *self.account.key, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *self.base_account.key, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *base_account.key, + true, + )); + } remaining_accounts.iter().for_each(|remaining_account| { accounts.push(solana_program::instruction::AccountMeta { pubkey: *remaining_account.0.key, @@ -256,7 +264,9 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); account_infos.push(self.__program.clone()); account_infos.push(self.account.clone()); - account_infos.push(self.base_account.clone()); + if let Some(base_account) = self.base_account { + account_infos.push(base_account.clone()); + } remaining_accounts .iter() .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); @@ -274,7 +284,7 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { /// ### Accounts: /// /// 0. `[writable]` account -/// 1. `[signer]` base_account +/// 1. `[signer, optional]` base_account #[derive(Clone, Debug)] pub struct AssignWithSeedCpiBuilder<'a, 'b> { instruction: Box>, @@ -301,12 +311,13 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { self.instruction.account = Some(account); self } + /// `[optional account]` #[inline(always)] pub fn base_account( &mut self, - base_account: &'b solana_program::account_info::AccountInfo<'a>, + base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, ) -> &mut Self { - self.instruction.base_account = Some(base_account); + self.instruction.base_account = base_account; self } #[inline(always)] @@ -379,10 +390,7 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { account: self.instruction.account.expect("account is not set"), - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/clients/rust/src/generated/instructions/create_account_with_seed.rs b/clients/rust/src/generated/instructions/create_account_with_seed.rs index e397827..73b258c 100644 --- a/clients/rust/src/generated/instructions/create_account_with_seed.rs +++ b/clients/rust/src/generated/instructions/create_account_with_seed.rs @@ -17,7 +17,7 @@ pub struct CreateAccountWithSeed { pub new_account: solana_program::pubkey::Pubkey, - pub base_account: solana_program::pubkey::Pubkey, + pub base_account: Option, } impl CreateAccountWithSeed { @@ -42,10 +42,12 @@ impl CreateAccountWithSeed { self.new_account, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - self.base_account, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + base_account, + true, + )); + } accounts.extend_from_slice(remaining_accounts); let mut data = borsh::to_vec(&CreateAccountWithSeedInstructionData::new()).unwrap(); let mut args = borsh::to_vec(&args).unwrap(); @@ -93,7 +95,7 @@ pub struct CreateAccountWithSeedInstructionArgs { /// /// 0. `[writable, signer]` payer /// 1. `[writable]` new_account -/// 2. `[signer]` base_account +/// 2. `[signer, optional]` base_account #[derive(Clone, Debug, Default)] pub struct CreateAccountWithSeedBuilder { payer: Option, @@ -121,9 +123,13 @@ impl CreateAccountWithSeedBuilder { self.new_account = Some(new_account); self } + /// `[optional account]` #[inline(always)] - pub fn base_account(&mut self, base_account: solana_program::pubkey::Pubkey) -> &mut Self { - self.base_account = Some(base_account); + pub fn base_account( + &mut self, + base_account: Option, + ) -> &mut Self { + self.base_account = base_account; self } #[inline(always)] @@ -174,7 +180,7 @@ impl CreateAccountWithSeedBuilder { let accounts = CreateAccountWithSeed { payer: self.payer.expect("payer is not set"), new_account: self.new_account.expect("new_account is not set"), - base_account: self.base_account.expect("base_account is not set"), + base_account: self.base_account, }; let args = CreateAccountWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), @@ -197,7 +203,7 @@ pub struct CreateAccountWithSeedCpiAccounts<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, } /// `create_account_with_seed` CPI instruction. @@ -209,7 +215,7 @@ pub struct CreateAccountWithSeedCpi<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: &'b solana_program::account_info::AccountInfo<'a>, + pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, /// The arguments for the instruction. pub __args: CreateAccountWithSeedInstructionArgs, } @@ -271,10 +277,12 @@ impl<'a, 'b> CreateAccountWithSeedCpi<'a, 'b> { *self.new_account.key, false, )); - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *self.base_account.key, - true, - )); + if let Some(base_account) = self.base_account { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *base_account.key, + true, + )); + } remaining_accounts.iter().for_each(|remaining_account| { accounts.push(solana_program::instruction::AccountMeta { pubkey: *remaining_account.0.key, @@ -295,7 +303,9 @@ impl<'a, 'b> CreateAccountWithSeedCpi<'a, 'b> { account_infos.push(self.__program.clone()); account_infos.push(self.payer.clone()); account_infos.push(self.new_account.clone()); - account_infos.push(self.base_account.clone()); + if let Some(base_account) = self.base_account { + account_infos.push(base_account.clone()); + } remaining_accounts .iter() .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); @@ -314,7 +324,7 @@ impl<'a, 'b> CreateAccountWithSeedCpi<'a, 'b> { /// /// 0. `[writable, signer]` payer /// 1. `[writable]` new_account -/// 2. `[signer]` base_account +/// 2. `[signer, optional]` base_account #[derive(Clone, Debug)] pub struct CreateAccountWithSeedCpiBuilder<'a, 'b> { instruction: Box>, @@ -349,12 +359,13 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { self.instruction.new_account = Some(new_account); self } + /// `[optional account]` #[inline(always)] pub fn base_account( &mut self, - base_account: &'b solana_program::account_info::AccountInfo<'a>, + base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, ) -> &mut Self { - self.instruction.base_account = Some(base_account); + self.instruction.base_account = base_account; self } #[inline(always)] @@ -444,10 +455,7 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { .new_account .expect("new_account is not set"), - base_account: self - .instruction - .base_account - .expect("base_account is not set"), + base_account: self.instruction.base_account, __args: args, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/program/idl.json b/program/idl.json index 4464dad..ef14793 100644 --- a/program/idl.json +++ b/program/idl.json @@ -12,25 +12,35 @@ { "kind": "structFieldTypeNode", "name": "version", - "type": { "kind": "definedTypeLinkNode", "name": "nonceVersion" }, + "type": { + "kind": "definedTypeLinkNode", + "name": "nonceVersion" + }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "state", - "type": { "kind": "definedTypeLinkNode", "name": "nonceState" }, + "type": { + "kind": "definedTypeLinkNode", + "name": "nonceState" + }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "authority", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "blockhash", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] }, { @@ -62,7 +72,9 @@ "isSigner": true, "isOptional": false, "docs": [], - "defaultValue": { "kind": "payerValueNode" } + "defaultValue": { + "kind": "payerValueNode" + } }, { "kind": "instructionAccountNode", @@ -83,7 +95,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 0 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 0 + }, "defaultValueStrategy": "omitted" }, { @@ -109,14 +124,19 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], "byteDeltas": [ { "kind": "instructionByteDeltaNode", - "value": { "kind": "argumentValueNode", "name": "space" }, + "value": { + "kind": "argumentValueNode", + "name": "space" + }, "withHeader": true } ], @@ -130,7 +150,7 @@ "name": "createAccount", "idlName": "CreateAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -154,13 +174,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 1 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 1 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -174,7 +199,7 @@ "name": "assign", "idlName": "Assign", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -206,7 +231,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 2 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 2 + }, "defaultValueStrategy": "omitted" }, { @@ -230,7 +258,7 @@ "name": "transferSol", "idlName": "TransferSol", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -242,7 +270,9 @@ "isSigner": true, "isOptional": false, "docs": [], - "defaultValue": { "kind": "payerValueNode" } + "defaultValue": { + "kind": "payerValueNode" + } }, { "kind": "instructionAccountNode", @@ -257,7 +287,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": false, + "isOptional": true, "docs": [] } ], @@ -271,13 +301,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 3 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 3 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] }, { @@ -285,7 +320,10 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -317,7 +355,9 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -331,7 +371,7 @@ "name": "createAccountWithSeed", "idlName": "CreateAccountWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -375,7 +415,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 4 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 4 + }, "defaultValueStrategy": "omitted" } ], @@ -389,7 +432,7 @@ "name": "advanceNonceAccount", "idlName": "AdvanceNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -453,7 +496,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 5 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 5 + }, "defaultValueStrategy": "omitted" }, { @@ -477,7 +523,7 @@ "name": "withdrawNonceAccount", "idlName": "WithdrawNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -525,13 +571,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 6 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 6 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "nonceAuthority", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -545,7 +596,7 @@ "name": "initializeNonceAccount", "idlName": "InitializeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -577,13 +628,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 7 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 7 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "newNonceAuthority", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -597,7 +653,7 @@ "name": "authorizeNonceAccount", "idlName": "AuthorizeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -621,7 +677,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 8 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 8 + }, "defaultValueStrategy": "omitted" }, { @@ -645,7 +704,7 @@ "name": "allocate", "idlName": "Allocate", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -663,7 +722,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": false, + "isOptional": true, "docs": [] } ], @@ -677,13 +736,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 9 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 9 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] }, { @@ -691,7 +755,10 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -713,7 +780,9 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -727,7 +796,7 @@ "name": "allocateWithSeed", "idlName": "AllocateWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -745,7 +814,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": false, + "isOptional": true, "docs": [] } ], @@ -759,13 +828,18 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 10 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 10 + }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] }, { @@ -773,7 +847,10 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -785,7 +862,9 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -799,7 +878,7 @@ "name": "assignWithSeed", "idlName": "AssignWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -839,7 +918,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 11 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 11 + }, "defaultValueStrategy": "omitted" }, { @@ -857,7 +939,10 @@ "name": "fromSeed", "type": { "kind": "sizePrefixTypeNode", - "type": { "kind": "stringTypeNode", "encoding": "utf8" }, + "type": { + "kind": "stringTypeNode", + "encoding": "utf8" + }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -869,7 +954,9 @@ { "kind": "instructionArgumentNode", "name": "fromOwner", - "type": { "kind": "publicKeyTypeNode" }, + "type": { + "kind": "publicKeyTypeNode" + }, "docs": [] } ], @@ -883,7 +970,7 @@ "name": "transferSolWithSeed", "idlName": "TransferSolWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -907,7 +994,10 @@ "endian": "le" }, "docs": [], - "defaultValue": { "kind": "numberValueNode", "number": 12 }, + "defaultValue": { + "kind": "numberValueNode", + "number": 12 + }, "defaultValueStrategy": "omitted" } ], @@ -921,7 +1011,7 @@ "name": "upgradeNonceAccount", "idlName": "UpgradeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" } ], "definedTypes": [ @@ -931,10 +1021,20 @@ "type": { "kind": "enumTypeNode", "variants": [ - { "kind": "enumEmptyVariantTypeNode", "name": "legacy" }, - { "kind": "enumEmptyVariantTypeNode", "name": "current" } + { + "kind": "enumEmptyVariantTypeNode", + "name": "legacy" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "current" + } ], - "size": { "kind": "numberTypeNode", "format": "u32", "endian": "le" } + "size": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } }, "idlName": "NonceVersion", "docs": [] @@ -945,10 +1045,20 @@ "type": { "kind": "enumTypeNode", "variants": [ - { "kind": "enumEmptyVariantTypeNode", "name": "uninitialized" }, - { "kind": "enumEmptyVariantTypeNode", "name": "initialized" } + { + "kind": "enumEmptyVariantTypeNode", + "name": "uninitialized" + }, + { + "kind": "enumEmptyVariantTypeNode", + "name": "initialized" + } ], - "size": { "kind": "numberTypeNode", "format": "u32", "endian": "le" } + "size": { + "kind": "numberTypeNode", + "format": "u32", + "endian": "le" + } }, "idlName": "NonceState", "docs": [] @@ -981,7 +1091,9 @@ "idlName": "InvalidProgramId", "code": 2, "message": "cannot assign account to this program id", - "docs": ["InvalidProgramId: cannot assign account to this program id"] + "docs": [ + "InvalidProgramId: cannot assign account to this program id" + ] }, { "kind": "errorNode", @@ -999,7 +1111,9 @@ "idlName": "MaxSeedLengthExceeded", "code": 4, "message": "length of requested seed is too long", - "docs": ["MaxSeedLengthExceeded: length of requested seed is too long"] + "docs": [ + "MaxSeedLengthExceeded: length of requested seed is too long" + ] }, { "kind": "errorNode", @@ -1051,4 +1165,4 @@ "additionalPrograms": [], "standard": "codama", "version": "1.0.0" -} +} \ No newline at end of file From 2766eb2c92531b9e2533181e1580681a97210a5c Mon Sep 17 00:00:00 2001 From: Arrowana Date: Sat, 6 Sep 2025 09:49:11 +1000 Subject: [PATCH 2/8] No, only create with seed --- .../instructions/allocateWithSeed.ts | 33 +-- .../generated/instructions/assignWithSeed.ts | 33 +-- .../instructions/allocate_with_seed.rs | 54 ++--- .../instructions/assign_with_seed.rs | 54 ++--- program/idl.json | 206 ++++-------------- 5 files changed, 112 insertions(+), 268 deletions(-) diff --git a/clients/js/src/generated/instructions/allocateWithSeed.ts b/clients/js/src/generated/instructions/allocateWithSeed.ts index 31c004e..0acbd8b 100644 --- a/clients/js/src/generated/instructions/allocateWithSeed.ts +++ b/clients/js/src/generated/instructions/allocateWithSeed.ts @@ -47,10 +47,7 @@ export function getAllocateWithSeedDiscriminatorBytes() { export type AllocateWithSeedInstruction< TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, TAccountNewAccount extends string | AccountMeta = string, - TAccountBaseAccount extends - | string - | AccountMeta - | undefined = undefined, + TAccountBaseAccount extends string | AccountMeta = string, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & @@ -59,14 +56,10 @@ export type AllocateWithSeedInstruction< TAccountNewAccount extends string ? WritableAccount : TAccountNewAccount, - ...(TAccountBaseAccount extends undefined - ? [] - : [ - TAccountBaseAccount extends string - ? ReadonlySignerAccount & - AccountSignerMeta - : TAccountBaseAccount, - ]), + TAccountBaseAccount extends string + ? ReadonlySignerAccount & + AccountSignerMeta + : TAccountBaseAccount, ...TRemainingAccounts, ] >; @@ -124,7 +117,7 @@ export type AllocateWithSeedInput< TAccountBaseAccount extends string = string, > = { newAccount: Address; - baseAccount?: TransactionSigner; + baseAccount: TransactionSigner; base: AllocateWithSeedInstructionDataArgs['base']; seed: AllocateWithSeedInstructionDataArgs['seed']; space: AllocateWithSeedInstructionDataArgs['space']; @@ -164,7 +157,7 @@ export function getAllocateWithSeedInstruction< accounts: [ getAccountMeta(accounts.newAccount), getAccountMeta(accounts.baseAccount), - ].filter((x: T | undefined): x is T => x !== undefined), + ], programAddress, data: getAllocateWithSeedInstructionDataEncoder().encode( args as AllocateWithSeedInstructionDataArgs @@ -185,7 +178,7 @@ export type ParsedAllocateWithSeedInstruction< programAddress: Address; accounts: { newAccount: TAccountMetas[0]; - baseAccount?: TAccountMetas[1] | undefined; + baseAccount: TAccountMetas[1]; }; data: AllocateWithSeedInstructionData; }; @@ -198,7 +191,7 @@ export function parseAllocateWithSeedInstruction< InstructionWithAccounts & InstructionWithData ): ParsedAllocateWithSeedInstruction { - if (instruction.accounts.length < 1) { + if (instruction.accounts.length < 2) { // TODO: Coded error. throw new Error('Not enough accounts'); } @@ -208,17 +201,11 @@ export function parseAllocateWithSeedInstruction< accountIndex += 1; return accountMeta; }; - let optionalAccountsRemaining = instruction.accounts.length - 1; - const getNextOptionalAccount = () => { - if (optionalAccountsRemaining === 0) return undefined; - optionalAccountsRemaining -= 1; - return getNextAccount(); - }; return { programAddress: instruction.programAddress, accounts: { newAccount: getNextAccount(), - baseAccount: getNextOptionalAccount(), + baseAccount: getNextAccount(), }, data: getAllocateWithSeedInstructionDataDecoder().decode(instruction.data), }; diff --git a/clients/js/src/generated/instructions/assignWithSeed.ts b/clients/js/src/generated/instructions/assignWithSeed.ts index b67031a..c12deb8 100644 --- a/clients/js/src/generated/instructions/assignWithSeed.ts +++ b/clients/js/src/generated/instructions/assignWithSeed.ts @@ -47,10 +47,7 @@ export function getAssignWithSeedDiscriminatorBytes() { export type AssignWithSeedInstruction< TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, TAccountAccount extends string | AccountMeta = string, - TAccountBaseAccount extends - | string - | AccountMeta - | undefined = undefined, + TAccountBaseAccount extends string | AccountMeta = string, TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & @@ -59,14 +56,10 @@ export type AssignWithSeedInstruction< TAccountAccount extends string ? WritableAccount : TAccountAccount, - ...(TAccountBaseAccount extends undefined - ? [] - : [ - TAccountBaseAccount extends string - ? ReadonlySignerAccount & - AccountSignerMeta - : TAccountBaseAccount, - ]), + TAccountBaseAccount extends string + ? ReadonlySignerAccount & + AccountSignerMeta + : TAccountBaseAccount, ...TRemainingAccounts, ] >; @@ -120,7 +113,7 @@ export type AssignWithSeedInput< TAccountBaseAccount extends string = string, > = { account: Address; - baseAccount?: TransactionSigner; + baseAccount: TransactionSigner; base: AssignWithSeedInstructionDataArgs['base']; seed: AssignWithSeedInstructionDataArgs['seed']; programAddress: AssignWithSeedInstructionDataArgs['programAddress']; @@ -159,7 +152,7 @@ export function getAssignWithSeedInstruction< accounts: [ getAccountMeta(accounts.account), getAccountMeta(accounts.baseAccount), - ].filter((x: T | undefined): x is T => x !== undefined), + ], programAddress, data: getAssignWithSeedInstructionDataEncoder().encode( args as AssignWithSeedInstructionDataArgs @@ -180,7 +173,7 @@ export type ParsedAssignWithSeedInstruction< programAddress: Address; accounts: { account: TAccountMetas[0]; - baseAccount?: TAccountMetas[1] | undefined; + baseAccount: TAccountMetas[1]; }; data: AssignWithSeedInstructionData; }; @@ -193,7 +186,7 @@ export function parseAssignWithSeedInstruction< InstructionWithAccounts & InstructionWithData ): ParsedAssignWithSeedInstruction { - if (instruction.accounts.length < 1) { + if (instruction.accounts.length < 2) { // TODO: Coded error. throw new Error('Not enough accounts'); } @@ -203,17 +196,11 @@ export function parseAssignWithSeedInstruction< accountIndex += 1; return accountMeta; }; - let optionalAccountsRemaining = instruction.accounts.length - 1; - const getNextOptionalAccount = () => { - if (optionalAccountsRemaining === 0) return undefined; - optionalAccountsRemaining -= 1; - return getNextAccount(); - }; return { programAddress: instruction.programAddress, accounts: { account: getNextAccount(), - baseAccount: getNextOptionalAccount(), + baseAccount: getNextAccount(), }, data: getAssignWithSeedInstructionDataDecoder().decode(instruction.data), }; diff --git a/clients/rust/src/generated/instructions/allocate_with_seed.rs b/clients/rust/src/generated/instructions/allocate_with_seed.rs index 78f9d85..71d3220 100644 --- a/clients/rust/src/generated/instructions/allocate_with_seed.rs +++ b/clients/rust/src/generated/instructions/allocate_with_seed.rs @@ -15,7 +15,7 @@ use solana_program::pubkey::Pubkey; pub struct AllocateWithSeed { pub new_account: solana_program::pubkey::Pubkey, - pub base_account: Option, + pub base_account: solana_program::pubkey::Pubkey, } impl AllocateWithSeed { @@ -37,12 +37,10 @@ impl AllocateWithSeed { self.new_account, false, )); - if let Some(base_account) = self.base_account { - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - base_account, - true, - )); - } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.base_account, + true, + )); accounts.extend_from_slice(remaining_accounts); let mut data = borsh::to_vec(&AllocateWithSeedInstructionData::new()).unwrap(); let mut args = borsh::to_vec(&args).unwrap(); @@ -88,7 +86,7 @@ pub struct AllocateWithSeedInstructionArgs { /// ### Accounts: /// /// 0. `[writable]` new_account -/// 1. `[signer, optional]` base_account +/// 1. `[signer]` base_account #[derive(Clone, Debug, Default)] pub struct AllocateWithSeedBuilder { new_account: Option, @@ -109,13 +107,9 @@ impl AllocateWithSeedBuilder { self.new_account = Some(new_account); self } - /// `[optional account]` #[inline(always)] - pub fn base_account( - &mut self, - base_account: Option, - ) -> &mut Self { - self.base_account = base_account; + pub fn base_account(&mut self, base_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.base_account = Some(base_account); self } #[inline(always)] @@ -160,7 +154,7 @@ impl AllocateWithSeedBuilder { pub fn instruction(&self) -> solana_program::instruction::Instruction { let accounts = AllocateWithSeed { new_account: self.new_account.expect("new_account is not set"), - base_account: self.base_account, + base_account: self.base_account.expect("base_account is not set"), }; let args = AllocateWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), @@ -180,7 +174,7 @@ impl AllocateWithSeedBuilder { pub struct AllocateWithSeedCpiAccounts<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + pub base_account: &'b solana_program::account_info::AccountInfo<'a>, } /// `allocate_with_seed` CPI instruction. @@ -190,7 +184,7 @@ pub struct AllocateWithSeedCpi<'a, 'b> { pub new_account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + pub base_account: &'b solana_program::account_info::AccountInfo<'a>, /// The arguments for the instruction. pub __args: AllocateWithSeedInstructionArgs, } @@ -247,12 +241,10 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { *self.new_account.key, false, )); - if let Some(base_account) = self.base_account { - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *base_account.key, - true, - )); - } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.base_account.key, + true, + )); remaining_accounts.iter().for_each(|remaining_account| { accounts.push(solana_program::instruction::AccountMeta { pubkey: *remaining_account.0.key, @@ -272,9 +264,7 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); account_infos.push(self.__program.clone()); account_infos.push(self.new_account.clone()); - if let Some(base_account) = self.base_account { - account_infos.push(base_account.clone()); - } + account_infos.push(self.base_account.clone()); remaining_accounts .iter() .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); @@ -292,7 +282,7 @@ impl<'a, 'b> AllocateWithSeedCpi<'a, 'b> { /// ### Accounts: /// /// 0. `[writable]` new_account -/// 1. `[signer, optional]` base_account +/// 1. `[signer]` base_account #[derive(Clone, Debug)] pub struct AllocateWithSeedCpiBuilder<'a, 'b> { instruction: Box>, @@ -320,13 +310,12 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { self.instruction.new_account = Some(new_account); self } - /// `[optional account]` #[inline(always)] pub fn base_account( &mut self, - base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + base_account: &'b solana_program::account_info::AccountInfo<'a>, ) -> &mut Self { - self.instruction.base_account = base_account; + self.instruction.base_account = Some(base_account); self } #[inline(always)] @@ -408,7 +397,10 @@ impl<'a, 'b> AllocateWithSeedCpiBuilder<'a, 'b> { .new_account .expect("new_account is not set"), - base_account: self.instruction.base_account, + base_account: self + .instruction + .base_account + .expect("base_account is not set"), __args: args, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/clients/rust/src/generated/instructions/assign_with_seed.rs b/clients/rust/src/generated/instructions/assign_with_seed.rs index 683ce3c..4ccbd59 100644 --- a/clients/rust/src/generated/instructions/assign_with_seed.rs +++ b/clients/rust/src/generated/instructions/assign_with_seed.rs @@ -15,7 +15,7 @@ use solana_program::pubkey::Pubkey; pub struct AssignWithSeed { pub account: solana_program::pubkey::Pubkey, - pub base_account: Option, + pub base_account: solana_program::pubkey::Pubkey, } impl AssignWithSeed { @@ -37,12 +37,10 @@ impl AssignWithSeed { self.account, false, )); - if let Some(base_account) = self.base_account { - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - base_account, - true, - )); - } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.base_account, + true, + )); accounts.extend_from_slice(remaining_accounts); let mut data = borsh::to_vec(&AssignWithSeedInstructionData::new()).unwrap(); let mut args = borsh::to_vec(&args).unwrap(); @@ -87,7 +85,7 @@ pub struct AssignWithSeedInstructionArgs { /// ### Accounts: /// /// 0. `[writable]` account -/// 1. `[signer, optional]` base_account +/// 1. `[signer]` base_account #[derive(Clone, Debug, Default)] pub struct AssignWithSeedBuilder { account: Option, @@ -107,13 +105,9 @@ impl AssignWithSeedBuilder { self.account = Some(account); self } - /// `[optional account]` #[inline(always)] - pub fn base_account( - &mut self, - base_account: Option, - ) -> &mut Self { - self.base_account = base_account; + pub fn base_account(&mut self, base_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.base_account = Some(base_account); self } #[inline(always)] @@ -153,7 +147,7 @@ impl AssignWithSeedBuilder { pub fn instruction(&self) -> solana_program::instruction::Instruction { let accounts = AssignWithSeed { account: self.account.expect("account is not set"), - base_account: self.base_account, + base_account: self.base_account.expect("base_account is not set"), }; let args = AssignWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), @@ -172,7 +166,7 @@ impl AssignWithSeedBuilder { pub struct AssignWithSeedCpiAccounts<'a, 'b> { pub account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + pub base_account: &'b solana_program::account_info::AccountInfo<'a>, } /// `assign_with_seed` CPI instruction. @@ -182,7 +176,7 @@ pub struct AssignWithSeedCpi<'a, 'b> { pub account: &'b solana_program::account_info::AccountInfo<'a>, - pub base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + pub base_account: &'b solana_program::account_info::AccountInfo<'a>, /// The arguments for the instruction. pub __args: AssignWithSeedInstructionArgs, } @@ -239,12 +233,10 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { *self.account.key, false, )); - if let Some(base_account) = self.base_account { - accounts.push(solana_program::instruction::AccountMeta::new_readonly( - *base_account.key, - true, - )); - } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.base_account.key, + true, + )); remaining_accounts.iter().for_each(|remaining_account| { accounts.push(solana_program::instruction::AccountMeta { pubkey: *remaining_account.0.key, @@ -264,9 +256,7 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { let mut account_infos = Vec::with_capacity(3 + remaining_accounts.len()); account_infos.push(self.__program.clone()); account_infos.push(self.account.clone()); - if let Some(base_account) = self.base_account { - account_infos.push(base_account.clone()); - } + account_infos.push(self.base_account.clone()); remaining_accounts .iter() .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); @@ -284,7 +274,7 @@ impl<'a, 'b> AssignWithSeedCpi<'a, 'b> { /// ### Accounts: /// /// 0. `[writable]` account -/// 1. `[signer, optional]` base_account +/// 1. `[signer]` base_account #[derive(Clone, Debug)] pub struct AssignWithSeedCpiBuilder<'a, 'b> { instruction: Box>, @@ -311,13 +301,12 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { self.instruction.account = Some(account); self } - /// `[optional account]` #[inline(always)] pub fn base_account( &mut self, - base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + base_account: &'b solana_program::account_info::AccountInfo<'a>, ) -> &mut Self { - self.instruction.base_account = base_account; + self.instruction.base_account = Some(base_account); self } #[inline(always)] @@ -390,7 +379,10 @@ impl<'a, 'b> AssignWithSeedCpiBuilder<'a, 'b> { account: self.instruction.account.expect("account is not set"), - base_account: self.instruction.base_account, + base_account: self + .instruction + .base_account + .expect("base_account is not set"), __args: args, }; instruction.invoke_signed_with_remaining_accounts( diff --git a/program/idl.json b/program/idl.json index ef14793..0f391dc 100644 --- a/program/idl.json +++ b/program/idl.json @@ -12,35 +12,25 @@ { "kind": "structFieldTypeNode", "name": "version", - "type": { - "kind": "definedTypeLinkNode", - "name": "nonceVersion" - }, + "type": { "kind": "definedTypeLinkNode", "name": "nonceVersion" }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "state", - "type": { - "kind": "definedTypeLinkNode", - "name": "nonceState" - }, + "type": { "kind": "definedTypeLinkNode", "name": "nonceState" }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "authority", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] }, { "kind": "structFieldTypeNode", "name": "blockhash", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] }, { @@ -72,9 +62,7 @@ "isSigner": true, "isOptional": false, "docs": [], - "defaultValue": { - "kind": "payerValueNode" - } + "defaultValue": { "kind": "payerValueNode" } }, { "kind": "instructionAccountNode", @@ -95,10 +83,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 0 - }, + "defaultValue": { "kind": "numberValueNode", "number": 0 }, "defaultValueStrategy": "omitted" }, { @@ -124,19 +109,14 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], "byteDeltas": [ { "kind": "instructionByteDeltaNode", - "value": { - "kind": "argumentValueNode", - "name": "space" - }, + "value": { "kind": "argumentValueNode", "name": "space" }, "withHeader": true } ], @@ -174,18 +154,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 1 - }, + "defaultValue": { "kind": "numberValueNode", "number": 1 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -231,10 +206,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 2 - }, + "defaultValue": { "kind": "numberValueNode", "number": 2 }, "defaultValueStrategy": "omitted" }, { @@ -270,9 +242,7 @@ "isSigner": true, "isOptional": false, "docs": [], - "defaultValue": { - "kind": "payerValueNode" - } + "defaultValue": { "kind": "payerValueNode" } }, { "kind": "instructionAccountNode", @@ -301,18 +271,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 3 - }, + "defaultValue": { "kind": "numberValueNode", "number": 3 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] }, { @@ -320,10 +285,7 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { - "kind": "stringTypeNode", - "encoding": "utf8" - }, + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -355,9 +317,7 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -415,10 +375,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 4 - }, + "defaultValue": { "kind": "numberValueNode", "number": 4 }, "defaultValueStrategy": "omitted" } ], @@ -496,10 +453,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 5 - }, + "defaultValue": { "kind": "numberValueNode", "number": 5 }, "defaultValueStrategy": "omitted" }, { @@ -571,18 +525,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 6 - }, + "defaultValue": { "kind": "numberValueNode", "number": 6 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "nonceAuthority", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -628,18 +577,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 7 - }, + "defaultValue": { "kind": "numberValueNode", "number": 7 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "newNonceAuthority", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -677,10 +621,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 8 - }, + "defaultValue": { "kind": "numberValueNode", "number": 8 }, "defaultValueStrategy": "omitted" }, { @@ -722,7 +663,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": true, + "isOptional": false, "docs": [] } ], @@ -736,18 +677,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 9 - }, + "defaultValue": { "kind": "numberValueNode", "number": 9 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] }, { @@ -755,10 +691,7 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { - "kind": "stringTypeNode", - "encoding": "utf8" - }, + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -780,9 +713,7 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -814,7 +745,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": true, + "isOptional": false, "docs": [] } ], @@ -828,18 +759,13 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 10 - }, + "defaultValue": { "kind": "numberValueNode", "number": 10 }, "defaultValueStrategy": "omitted" }, { "kind": "instructionArgumentNode", "name": "base", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] }, { @@ -847,10 +773,7 @@ "name": "seed", "type": { "kind": "sizePrefixTypeNode", - "type": { - "kind": "stringTypeNode", - "encoding": "utf8" - }, + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -862,9 +785,7 @@ { "kind": "instructionArgumentNode", "name": "programAddress", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -918,10 +839,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 11 - }, + "defaultValue": { "kind": "numberValueNode", "number": 11 }, "defaultValueStrategy": "omitted" }, { @@ -939,10 +857,7 @@ "name": "fromSeed", "type": { "kind": "sizePrefixTypeNode", - "type": { - "kind": "stringTypeNode", - "encoding": "utf8" - }, + "type": { "kind": "stringTypeNode", "encoding": "utf8" }, "prefix": { "kind": "numberTypeNode", "format": "u64", @@ -954,9 +869,7 @@ { "kind": "instructionArgumentNode", "name": "fromOwner", - "type": { - "kind": "publicKeyTypeNode" - }, + "type": { "kind": "publicKeyTypeNode" }, "docs": [] } ], @@ -994,10 +907,7 @@ "endian": "le" }, "docs": [], - "defaultValue": { - "kind": "numberValueNode", - "number": 12 - }, + "defaultValue": { "kind": "numberValueNode", "number": 12 }, "defaultValueStrategy": "omitted" } ], @@ -1021,20 +931,10 @@ "type": { "kind": "enumTypeNode", "variants": [ - { - "kind": "enumEmptyVariantTypeNode", - "name": "legacy" - }, - { - "kind": "enumEmptyVariantTypeNode", - "name": "current" - } + { "kind": "enumEmptyVariantTypeNode", "name": "legacy" }, + { "kind": "enumEmptyVariantTypeNode", "name": "current" } ], - "size": { - "kind": "numberTypeNode", - "format": "u32", - "endian": "le" - } + "size": { "kind": "numberTypeNode", "format": "u32", "endian": "le" } }, "idlName": "NonceVersion", "docs": [] @@ -1045,20 +945,10 @@ "type": { "kind": "enumTypeNode", "variants": [ - { - "kind": "enumEmptyVariantTypeNode", - "name": "uninitialized" - }, - { - "kind": "enumEmptyVariantTypeNode", - "name": "initialized" - } + { "kind": "enumEmptyVariantTypeNode", "name": "uninitialized" }, + { "kind": "enumEmptyVariantTypeNode", "name": "initialized" } ], - "size": { - "kind": "numberTypeNode", - "format": "u32", - "endian": "le" - } + "size": { "kind": "numberTypeNode", "format": "u32", "endian": "le" } }, "idlName": "NonceState", "docs": [] @@ -1091,9 +981,7 @@ "idlName": "InvalidProgramId", "code": 2, "message": "cannot assign account to this program id", - "docs": [ - "InvalidProgramId: cannot assign account to this program id" - ] + "docs": ["InvalidProgramId: cannot assign account to this program id"] }, { "kind": "errorNode", @@ -1111,9 +999,7 @@ "idlName": "MaxSeedLengthExceeded", "code": 4, "message": "length of requested seed is too long", - "docs": [ - "MaxSeedLengthExceeded: length of requested seed is too long" - ] + "docs": ["MaxSeedLengthExceeded: length of requested seed is too long"] }, { "kind": "errorNode", @@ -1165,4 +1051,4 @@ "additionalPrograms": [], "standard": "codama", "version": "1.0.0" -} \ No newline at end of file +} From d071ee7d86fa2c31498dad2ec285821038cee01e Mon Sep 17 00:00:00 2001 From: Arrowana Date: Fri, 12 Sep 2025 12:46:53 +1000 Subject: [PATCH 3/8] Add tests --- .../instructions/createAccountWithSeed.ts | 10 +-- clients/js/test/createAccountWithSeed.test.ts | 82 +++++++++++++++++++ .../instructions/create_account_with_seed.rs | 24 +++--- program/idl.json | 2 +- 4 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 clients/js/test/createAccountWithSeed.test.ts diff --git a/clients/js/src/generated/instructions/createAccountWithSeed.ts b/clients/js/src/generated/instructions/createAccountWithSeed.ts index 700088e..e382b7a 100644 --- a/clients/js/src/generated/instructions/createAccountWithSeed.ts +++ b/clients/js/src/generated/instructions/createAccountWithSeed.ts @@ -81,7 +81,7 @@ export type CreateAccountWithSeedInstructionData = { discriminator: number; base: Address; seed: string; - amount: bigint; + lamports: bigint; space: bigint; programAddress: Address; }; @@ -89,7 +89,7 @@ export type CreateAccountWithSeedInstructionData = { export type CreateAccountWithSeedInstructionDataArgs = { base: Address; seed: string; - amount: number | bigint; + lamports: number | bigint; space: number | bigint; programAddress: Address; }; @@ -100,7 +100,7 @@ export function getCreateAccountWithSeedInstructionDataEncoder(): Encoder; base: CreateAccountWithSeedInstructionDataArgs['base']; seed: CreateAccountWithSeedInstructionDataArgs['seed']; - amount: CreateAccountWithSeedInstructionDataArgs['amount']; + lamports: CreateAccountWithSeedInstructionDataArgs['lamports']; space: CreateAccountWithSeedInstructionDataArgs['space']; programAddress: CreateAccountWithSeedInstructionDataArgs['programAddress']; }; diff --git a/clients/js/test/createAccountWithSeed.test.ts b/clients/js/test/createAccountWithSeed.test.ts new file mode 100644 index 0000000..3dd9f90 --- /dev/null +++ b/clients/js/test/createAccountWithSeed.test.ts @@ -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, + 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 } = {}; + 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)); diff --git a/clients/rust/src/generated/instructions/create_account_with_seed.rs b/clients/rust/src/generated/instructions/create_account_with_seed.rs index 73b258c..44cd80a 100644 --- a/clients/rust/src/generated/instructions/create_account_with_seed.rs +++ b/clients/rust/src/generated/instructions/create_account_with_seed.rs @@ -84,7 +84,7 @@ impl Default for CreateAccountWithSeedInstructionData { pub struct CreateAccountWithSeedInstructionArgs { pub base: Pubkey, pub seed: U64PrefixString, - pub amount: u64, + pub lamports: u64, pub space: u64, pub program_address: Pubkey, } @@ -103,7 +103,7 @@ pub struct CreateAccountWithSeedBuilder { base_account: Option, base: Option, seed: Option, - amount: Option, + lamports: Option, space: Option, program_address: Option, __remaining_accounts: Vec, @@ -143,8 +143,8 @@ impl CreateAccountWithSeedBuilder { self } #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.amount = Some(amount); + pub fn lamports(&mut self, lamports: u64) -> &mut Self { + self.lamports = Some(lamports); self } #[inline(always)] @@ -185,7 +185,7 @@ impl CreateAccountWithSeedBuilder { let args = CreateAccountWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), seed: self.seed.clone().expect("seed is not set"), - amount: self.amount.clone().expect("amount is not set"), + lamports: self.lamports.clone().expect("lamports is not set"), space: self.space.clone().expect("space is not set"), program_address: self .program_address @@ -339,7 +339,7 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { base_account: None, base: None, seed: None, - amount: None, + lamports: None, space: None, program_address: None, __remaining_accounts: Vec::new(), @@ -379,8 +379,8 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { self } #[inline(always)] - pub fn amount(&mut self, amount: u64) -> &mut Self { - self.instruction.amount = Some(amount); + pub fn lamports(&mut self, lamports: u64) -> &mut Self { + self.instruction.lamports = Some(lamports); self } #[inline(always)] @@ -437,7 +437,11 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { let args = CreateAccountWithSeedInstructionArgs { base: self.instruction.base.clone().expect("base is not set"), seed: self.instruction.seed.clone().expect("seed is not set"), - amount: self.instruction.amount.clone().expect("amount is not set"), + lamports: self + .instruction + .lamports + .clone() + .expect("lamports is not set"), space: self.instruction.space.clone().expect("space is not set"), program_address: self .instruction @@ -473,7 +477,7 @@ struct CreateAccountWithSeedCpiBuilderInstruction<'a, 'b> { base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, base: Option, seed: Option, - amount: Option, + lamports: Option, space: Option, program_address: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. diff --git a/program/idl.json b/program/idl.json index 0f391dc..732a73e 100644 --- a/program/idl.json +++ b/program/idl.json @@ -296,7 +296,7 @@ }, { "kind": "instructionArgumentNode", - "name": "amount", + "name": "lamports", "type": { "kind": "numberTypeNode", "format": "u64", From b73eb8e05afcb8436f12119821201ad12f568046 Mon Sep 17 00:00:00 2001 From: Arrowana Date: Thu, 2 Oct 2025 11:11:31 +1000 Subject: [PATCH 4/8] Testing without helper and revert lamports to amount --- Cargo.lock | 163 ++---------------- .../instructions/createAccountWithSeed.ts | 10 +- clients/js/test/createAccountWithSeed.test.ts | 74 +++++--- .../instructions/create_account_with_seed.rs | 24 ++- package.json | 2 +- program/idl.json | 2 +- 6 files changed, 80 insertions(+), 195 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 366ae39..45b4b8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,15 +372,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - [[package]] name = "blake3" version = "1.6.1" @@ -1356,12 +1347,6 @@ version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -1704,22 +1689,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "im" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" -dependencies = [ - "bitmaps", - "rand_core 0.6.4", - "rand_xoshiro", - "rayon", - "serde", - "sized-chunks", - "typenum", - "version_check", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -2598,15 +2567,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core 0.6.4", -] - [[package]] name = "raw-cpuid" version = "11.3.0" @@ -3135,16 +3095,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" -[[package]] -name = "sized-chunks" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" -dependencies = [ - "bitmaps", - "typenum", -] - [[package]] name = "slab" version = "0.4.9" @@ -3364,7 +3314,7 @@ dependencies = [ "solana-pubkey", "solana-signature", "solana-signer", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-transaction", "solana-transaction-error", ] @@ -3559,7 +3509,7 @@ dependencies = [ "solana-nonce", "solana-pubkey", "solana-sdk-ids", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "thiserror 2.0.12", ] @@ -3579,7 +3529,7 @@ dependencies = [ "solana-pubkey", "solana-rent", "solana-sdk-ids", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", ] [[package]] @@ -3619,36 +3569,6 @@ dependencies = [ "solana-native-token", ] -[[package]] -name = "solana-frozen-abi" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685197cf2304e5d26973c72286abb8eb503eede4555b05dbe853d236fd74132c" -dependencies = [ - "bs58", - "bv", - "im", - "log", - "memmap2", - "serde", - "serde_derive", - "serde_with", - "sha2 0.10.8", - "solana-frozen-abi-macro", - "thiserror 2.0.12", -] - -[[package]] -name = "solana-frozen-abi-macro" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b83f88a126213cbcb57672c5e70ddb9791eff9b480e9f39fe9285fd2abca66fa" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "solana-genesis-config" version = "2.2.1" @@ -3823,7 +3743,7 @@ dependencies = [ "solana-instruction", "solana-pubkey", "solana-sdk-ids", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", ] [[package]] @@ -3838,7 +3758,7 @@ dependencies = [ "solana-instruction", "solana-pubkey", "solana-sdk-ids", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", ] [[package]] @@ -3878,7 +3798,7 @@ dependencies = [ "solana-sanitize", "solana-sdk-ids", "solana-short-vec", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-transaction-error", "wasm-bindgen", ] @@ -4143,7 +4063,7 @@ dependencies = [ "solana-slot-history", "solana-stable-layout", "solana-stake-interface", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-sysvar", "solana-sysvar-id", "solana-vote-interface", @@ -4226,8 +4146,6 @@ dependencies = [ "solana-atomic-u64", "solana-decode-error", "solana-define-syscall", - "solana-frozen-abi", - "solana-frozen-abi-macro", "solana-sanitize", "solana-sha256-hasher", "wasm-bindgen", @@ -4776,7 +4694,7 @@ dependencies = [ "solana-instruction", "solana-program-error", "solana-pubkey", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-sysvar-id", ] @@ -4849,38 +4767,6 @@ dependencies = [ "thiserror 1.0.69", ] -[[package]] -name = "solana-system-interface" -version = "1.0.0" -dependencies = [ - "anyhow", - "borsh 1.5.5", - "js-sys", - "num-traits", - "serde", - "serde_derive", - "solana-account-info", - "solana-cpi", - "solana-decode-error", - "solana-example-mocks", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-instruction", - "solana-logger", - "solana-msg", - "solana-nonce", - "solana-program-entrypoint", - "solana-program-error", - "solana-pubkey", - "solana-system-interface 1.0.0", - "solana-sysvar", - "solana-sysvar-id", - "static_assertions", - "strum", - "strum_macros", - "wasm-bindgen", -] - [[package]] name = "solana-system-interface" version = "1.0.0" @@ -4908,7 +4794,7 @@ dependencies = [ "solana-message", "solana-pubkey", "solana-signer", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-transaction", ] @@ -4983,7 +4869,7 @@ dependencies = [ "solana-rpc-client-api", "solana-signature", "solana-signer", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-transaction", "solana-transaction-error", ] @@ -5063,7 +4949,7 @@ dependencies = [ "solana-short-vec", "solana-signature", "solana-signer", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", "solana-transaction-error", "wasm-bindgen", ] @@ -5194,7 +5080,7 @@ dependencies = [ "solana-serde-varint", "solana-serialize-utils", "solana-short-vec", - "solana-system-interface 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "solana-system-interface", ] [[package]] @@ -5222,37 +5108,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - [[package]] name = "subtle" version = "2.6.1" diff --git a/clients/js/src/generated/instructions/createAccountWithSeed.ts b/clients/js/src/generated/instructions/createAccountWithSeed.ts index e382b7a..700088e 100644 --- a/clients/js/src/generated/instructions/createAccountWithSeed.ts +++ b/clients/js/src/generated/instructions/createAccountWithSeed.ts @@ -81,7 +81,7 @@ export type CreateAccountWithSeedInstructionData = { discriminator: number; base: Address; seed: string; - lamports: bigint; + amount: bigint; space: bigint; programAddress: Address; }; @@ -89,7 +89,7 @@ export type CreateAccountWithSeedInstructionData = { export type CreateAccountWithSeedInstructionDataArgs = { base: Address; seed: string; - lamports: number | bigint; + amount: number | bigint; space: number | bigint; programAddress: Address; }; @@ -100,7 +100,7 @@ export function getCreateAccountWithSeedInstructionDataEncoder(): Encoder; base: CreateAccountWithSeedInstructionDataArgs['base']; seed: CreateAccountWithSeedInstructionDataArgs['seed']; - lamports: CreateAccountWithSeedInstructionDataArgs['lamports']; + amount: CreateAccountWithSeedInstructionDataArgs['amount']; space: CreateAccountWithSeedInstructionDataArgs['space']; programAddress: CreateAccountWithSeedInstructionDataArgs['programAddress']; }; diff --git a/clients/js/test/createAccountWithSeed.test.ts b/clients/js/test/createAccountWithSeed.test.ts index 3dd9f90..b0d7360 100644 --- a/clients/js/test/createAccountWithSeed.test.ts +++ b/clients/js/test/createAccountWithSeed.test.ts @@ -3,10 +3,9 @@ import { createAddressWithSeed, fetchEncodedAccount, generateKeyPairSigner, - KeyPairSigner, pipe, } from '@solana/kit'; -import test, { ExecutionContext } from 'ava'; +import test from 'ava'; import { getCreateAccountWithSeedInstruction } from '../src'; import { createDefaultSolanaClient, @@ -15,10 +14,7 @@ import { signAndSendTransaction, } from './_setup'; -async function createAccountWithSeedTest( - t: ExecutionContext, - baseIsPayer: boolean -) { +test('it creates a new empty account when base is not payer', async (t) => { const client = createDefaultSolanaClient(); const space = 42n; const [payer, program, lamports] = await Promise.all([ @@ -26,11 +22,7 @@ async function createAccountWithSeedTest( generateKeyPairSigner(), client.rpc.getMinimumBalanceForRentExemption(space).send(), ]); - let baseAccount = await generateKeyPairSigner(); - - if (baseIsPayer) { - baseAccount = payer; - } + const baseAccount = await generateKeyPairSigner(); const programAddress = program.address; const SEED = '123456789'; @@ -40,21 +32,16 @@ async function createAccountWithSeedTest( seed: SEED, }); - let extraArgs: {} | { baseAccount: KeyPairSigner } = {}; - if (!baseIsPayer) { - extraArgs = { baseAccount }; - } - // When we call createAccountWithSeed in a transaction. const createAccount = getCreateAccountWithSeedInstruction({ payer, newAccount, + baseAccount, base: baseAccount.address, seed: SEED, space, - lamports, + amount: lamports, programAddress, - ...extraArgs, }); await pipe( await createDefaultTransaction(client, payer), @@ -73,10 +60,51 @@ async function createAccountWithSeedTest( exists: true, space: 42n, }); -} +}); + +test('it creates a new empty account when base is payer', async (t) => { + const client = createDefaultSolanaClient(); + const space = 42n; + const [payer, program, lamports] = await Promise.all([ + generateKeyPairSignerWithSol(client), + generateKeyPairSigner(), + client.rpc.getMinimumBalanceForRentExemption(space).send(), + ]); + const baseAddress = payer.address; -test('it creates a new empty account when base is not payer', (t) => - createAccountWithSeedTest(t, false)); + const programAddress = program.address; + const SEED = '123456789'; + const newAccount = await createAddressWithSeed({ + baseAddress, + programAddress, + seed: SEED, + }); + + // When we call createAccountWithSeed in a transaction. + const createAccount = getCreateAccountWithSeedInstruction({ + payer, + newAccount, + base: baseAddress, + seed: SEED, + space, + amount: lamports, + programAddress, + }); + await pipe( + await createDefaultTransaction(client, payer), + (tx) => appendTransactionMessageInstruction(createAccount, tx), + (tx) => signAndSendTransaction(client, tx) + ); -test('it creates a new empty account when base is payer', (t) => - createAccountWithSeedTest(t, true)); + // 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, + }); +}); diff --git a/clients/rust/src/generated/instructions/create_account_with_seed.rs b/clients/rust/src/generated/instructions/create_account_with_seed.rs index 44cd80a..73b258c 100644 --- a/clients/rust/src/generated/instructions/create_account_with_seed.rs +++ b/clients/rust/src/generated/instructions/create_account_with_seed.rs @@ -84,7 +84,7 @@ impl Default for CreateAccountWithSeedInstructionData { pub struct CreateAccountWithSeedInstructionArgs { pub base: Pubkey, pub seed: U64PrefixString, - pub lamports: u64, + pub amount: u64, pub space: u64, pub program_address: Pubkey, } @@ -103,7 +103,7 @@ pub struct CreateAccountWithSeedBuilder { base_account: Option, base: Option, seed: Option, - lamports: Option, + amount: Option, space: Option, program_address: Option, __remaining_accounts: Vec, @@ -143,8 +143,8 @@ impl CreateAccountWithSeedBuilder { self } #[inline(always)] - pub fn lamports(&mut self, lamports: u64) -> &mut Self { - self.lamports = Some(lamports); + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); self } #[inline(always)] @@ -185,7 +185,7 @@ impl CreateAccountWithSeedBuilder { let args = CreateAccountWithSeedInstructionArgs { base: self.base.clone().expect("base is not set"), seed: self.seed.clone().expect("seed is not set"), - lamports: self.lamports.clone().expect("lamports is not set"), + amount: self.amount.clone().expect("amount is not set"), space: self.space.clone().expect("space is not set"), program_address: self .program_address @@ -339,7 +339,7 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { base_account: None, base: None, seed: None, - lamports: None, + amount: None, space: None, program_address: None, __remaining_accounts: Vec::new(), @@ -379,8 +379,8 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { self } #[inline(always)] - pub fn lamports(&mut self, lamports: u64) -> &mut Self { - self.instruction.lamports = Some(lamports); + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); self } #[inline(always)] @@ -437,11 +437,7 @@ impl<'a, 'b> CreateAccountWithSeedCpiBuilder<'a, 'b> { let args = CreateAccountWithSeedInstructionArgs { base: self.instruction.base.clone().expect("base is not set"), seed: self.instruction.seed.clone().expect("seed is not set"), - lamports: self - .instruction - .lamports - .clone() - .expect("lamports is not set"), + amount: self.instruction.amount.clone().expect("amount is not set"), space: self.instruction.space.clone().expect("space is not set"), program_address: self .instruction @@ -477,7 +473,7 @@ struct CreateAccountWithSeedCpiBuilderInstruction<'a, 'b> { base_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, base: Option, seed: Option, - lamports: Option, + amount: Option, space: Option, program_address: Option, /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. diff --git a/package.json b/package.json index d45dd56..7c349b4 100644 --- a/package.json +++ b/package.json @@ -13,4 +13,4 @@ "node": ">=v20.0.0" }, "packageManager": "pnpm@9.1.0" -} +} \ No newline at end of file diff --git a/program/idl.json b/program/idl.json index 732a73e..0f391dc 100644 --- a/program/idl.json +++ b/program/idl.json @@ -296,7 +296,7 @@ }, { "kind": "instructionArgumentNode", - "name": "lamports", + "name": "amount", "type": { "kind": "numberTypeNode", "format": "u64", From 32d81e61d468d5458bf02a06118f05c6f5dd816e Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Thu, 2 Oct 2025 14:19:07 +0100 Subject: [PATCH 5/8] Run prettier fix after generating clients --- clients/js/package.json | 2 +- .../js/src/generated/instructions/createAccountWithSeed.ts | 2 +- codama.mjs | 6 +++--- package.json | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clients/js/package.json b/clients/js/package.json index 04a2ea8..77bbbf0 100644 --- a/clients/js/package.json +++ b/clients/js/package.json @@ -53,7 +53,7 @@ "@typescript-eslint/parser": "^7.16.1", "ava": "^6.1.3", "eslint": "^8.57.0", - "prettier": "^3.3.3", + "prettier": "^3.6.2", "rimraf": "^5.0.5", "tsup": "^8.1.2", "typedoc": "^0.25.12", diff --git a/clients/js/src/generated/instructions/createAccountWithSeed.ts b/clients/js/src/generated/instructions/createAccountWithSeed.ts index 700088e..9c148a5 100644 --- a/clients/js/src/generated/instructions/createAccountWithSeed.ts +++ b/clients/js/src/generated/instructions/createAccountWithSeed.ts @@ -188,7 +188,7 @@ export function getCreateAccountWithSeedInstruction< getAccountMeta(accounts.payer), getAccountMeta(accounts.newAccount), getAccountMeta(accounts.baseAccount), - ].filter((x: T | undefined): x is T => x !== undefined), + ].filter((x: T | undefined): x is T => x !== undefined), programAddress, data: getCreateAccountWithSeedInstructionDataEncoder().encode( args as CreateAccountWithSeedInstructionDataArgs diff --git a/codama.mjs b/codama.mjs index 361b539..497cb8f 100644 --- a/codama.mjs +++ b/codama.mjs @@ -1,8 +1,8 @@ import path from 'node:path'; +import fs from 'node:fs'; -const { default: prettierOptions } = await import( - path.resolve('clients', 'js', '.prettierrc.json'), - { with: { type: 'json' } } +const prettierOptions = JSON.parse( + fs.readFileSync(path.join('clients', 'js', '.prettierrc.json'), 'utf-8') ); export default { diff --git a/package.json b/package.json index 7c349b4..194c96f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "scripts": { "generate": "pnpm generate:clients", - "generate:clients": "codama run --all" + "generate:clients": "codama run --all && (cd clients/js && pnpm format:fix)" }, "devDependencies": { "@codama/renderers-js": "^1.3", @@ -13,4 +13,4 @@ "node": ">=v20.0.0" }, "packageManager": "pnpm@9.1.0" -} \ No newline at end of file +} From 28af763e7a5d112f2bcb06e71557119d1f1f5d9a Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Thu, 2 Oct 2025 14:20:52 +0100 Subject: [PATCH 6/8] Update pnpm-lock.yaml --- clients/js/pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clients/js/pnpm-lock.yaml b/clients/js/pnpm-lock.yaml index ce7aae6..09497cb 100644 --- a/clients/js/pnpm-lock.yaml +++ b/clients/js/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: specifier: ^8.57.0 version: 8.57.0 prettier: - specifier: ^3.3.3 - version: 3.3.3 + specifier: ^3.6.2 + version: 3.6.2 rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -1662,8 +1662,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.3.3: - resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} engines: {node: '>=14'} hasBin: true @@ -3696,7 +3696,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.3.3: {} + prettier@3.6.2: {} pretty-ms@9.0.0: dependencies: From b986968b906aa590ce058f777b488c141bf16785 Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Thu, 2 Oct 2025 14:23:51 +0100 Subject: [PATCH 7/8] Add toolchain to Rust client for formatting --- codama.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/codama.mjs b/codama.mjs index 497cb8f..f070f53 100644 --- a/codama.mjs +++ b/codama.mjs @@ -21,6 +21,7 @@ export default { anchorTraits: false, crateFolder: 'clients/rust', formatCode: true, + toolchain: '+1.86.0', }, ], }, From c4aa359dc2869682185a972999f32da44bc9a521 Mon Sep 17 00:00:00 2001 From: Loris Leiva Date: Thu, 2 Oct 2025 14:30:54 +0100 Subject: [PATCH 8/8] Use formatting toolchain instead --- codama.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codama.mjs b/codama.mjs index f070f53..65180c4 100644 --- a/codama.mjs +++ b/codama.mjs @@ -21,7 +21,7 @@ export default { anchorTraits: false, crateFolder: 'clients/rust', formatCode: true, - toolchain: '+1.86.0', + toolchain: '+nightly-2025-02-16', }, ], },