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/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/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: 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..0acbd8b 100644 --- a/clients/js/src/generated/instructions/allocateWithSeed.ts +++ b/clients/js/src/generated/instructions/allocateWithSeed.ts @@ -152,7 +152,7 @@ export function getAllocateWithSeedInstruction< // Original args. const args = { ...input }; - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted'); const instruction = { accounts: [ getAccountMeta(accounts.newAccount), 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..c12deb8 100644 --- a/clients/js/src/generated/instructions/assignWithSeed.ts +++ b/clients/js/src/generated/instructions/assignWithSeed.ts @@ -147,7 +147,7 @@ export function getAssignWithSeedInstruction< // Original args. const args = { ...input }; - const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const getAccountMeta = getAccountMetaFactory(programAddress, 'omitted'); const instruction = { accounts: [ getAccountMeta(accounts.account), 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..9c148a5 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/js/test/createAccountWithSeed.test.ts b/clients/js/test/createAccountWithSeed.test.ts new file mode 100644 index 0000000..b0d7360 --- /dev/null +++ b/clients/js/test/createAccountWithSeed.test.ts @@ -0,0 +1,110 @@ +import { + appendTransactionMessageInstruction, + createAddressWithSeed, + fetchEncodedAccount, + generateKeyPairSigner, + pipe, +} from '@solana/kit'; +import test from 'ava'; +import { getCreateAccountWithSeedInstruction } from '../src'; +import { + createDefaultSolanaClient, + createDefaultTransaction, + generateKeyPairSignerWithSol, + signAndSendTransaction, +} from './_setup'; + +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([ + generateKeyPairSignerWithSol(client), + generateKeyPairSigner(), + client.rpc.getMinimumBalanceForRentExemption(space).send(), + ]); + const baseAccount = await generateKeyPairSigner(); + + const programAddress = program.address; + const SEED = '123456789'; + const newAccount = await createAddressWithSeed({ + baseAddress: baseAccount.address, + programAddress, + seed: SEED, + }); + + // When we call createAccountWithSeed in a transaction. + const createAccount = getCreateAccountWithSeedInstruction({ + payer, + newAccount, + baseAccount, + base: baseAccount.address, + seed: SEED, + space, + amount: lamports, + programAddress, + }); + 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 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; + + 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) + ); + + // 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 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/codama.mjs b/codama.mjs index 361b539..65180c4 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 { @@ -21,6 +21,7 @@ export default { anchorTraits: false, crateFolder: 'clients/rust', formatCode: true, + toolchain: '+nightly-2025-02-16', }, ], }, diff --git a/package.json b/package.json index d45dd56..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", diff --git a/program/idl.json b/program/idl.json index 4464dad..0f391dc 100644 --- a/program/idl.json +++ b/program/idl.json @@ -130,7 +130,7 @@ "name": "createAccount", "idlName": "CreateAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -174,7 +174,7 @@ "name": "assign", "idlName": "Assign", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -230,7 +230,7 @@ "name": "transferSol", "idlName": "TransferSol", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -257,7 +257,7 @@ "name": "baseAccount", "isWritable": false, "isSigner": true, - "isOptional": false, + "isOptional": true, "docs": [] } ], @@ -331,7 +331,7 @@ "name": "createAccountWithSeed", "idlName": "CreateAccountWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -389,7 +389,7 @@ "name": "advanceNonceAccount", "idlName": "AdvanceNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -477,7 +477,7 @@ "name": "withdrawNonceAccount", "idlName": "WithdrawNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -545,7 +545,7 @@ "name": "initializeNonceAccount", "idlName": "InitializeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -597,7 +597,7 @@ "name": "authorizeNonceAccount", "idlName": "AuthorizeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -645,7 +645,7 @@ "name": "allocate", "idlName": "Allocate", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -727,7 +727,7 @@ "name": "allocateWithSeed", "idlName": "AllocateWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -799,7 +799,7 @@ "name": "assignWithSeed", "idlName": "AssignWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -883,7 +883,7 @@ "name": "transferSolWithSeed", "idlName": "TransferSolWithSeed", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" }, { "kind": "instructionNode", @@ -921,7 +921,7 @@ "name": "upgradeNonceAccount", "idlName": "UpgradeNonceAccount", "docs": [], - "optionalAccountStrategy": "programId" + "optionalAccountStrategy": "omitted" } ], "definedTypes": [