From d352e0563e4d3a3f09066ecd79babef3bcb36528 Mon Sep 17 00:00:00 2001 From: Stanislav Cherviakov Date: Tue, 24 Sep 2024 19:25:15 +0100 Subject: [PATCH] regenerated clients --- .../generated/errors/splAccountCompression.ts | 80 ++++ .../instructions/appendCanopyNodes.ts | 137 ++++++ .../js/src/generated/instructions/index.ts | 3 + .../instructions/initPreparedTreeWithRoot.ts | 141 ++++++ .../instructions/prepareBatchMerkleTree.ts | 137 ++++++ .../types/concurrentMerkleTreeHeaderData.ts | 16 +- .../errors/spl_account_compression.rs | 15 + .../instructions/append_canopy_nodes.rs | 416 +++++++++++++++++ .../init_prepared_tree_with_root.rs | 438 ++++++++++++++++++ .../rust/src/generated/instructions/mod.rs | 6 + .../instructions/prepare_batch_merkle_tree.rs | 419 +++++++++++++++++ .../concurrent_merkle_tree_header_data.rs | 6 +- 12 files changed, 1812 insertions(+), 2 deletions(-) create mode 100644 clients/js/src/generated/instructions/appendCanopyNodes.ts create mode 100644 clients/js/src/generated/instructions/initPreparedTreeWithRoot.ts create mode 100644 clients/js/src/generated/instructions/prepareBatchMerkleTree.ts create mode 100644 clients/rust/src/generated/instructions/append_canopy_nodes.rs create mode 100644 clients/rust/src/generated/instructions/init_prepared_tree_with_root.rs create mode 100644 clients/rust/src/generated/instructions/prepare_batch_merkle_tree.rs diff --git a/clients/js/src/generated/errors/splAccountCompression.ts b/clients/js/src/generated/errors/splAccountCompression.ts index 08409465..88e1ecfd 100644 --- a/clients/js/src/generated/errors/splAccountCompression.ts +++ b/clients/js/src/generated/errors/splAccountCompression.ts @@ -155,6 +155,86 @@ export class LeafIndexOutOfBoundsError extends ProgramError { codeToErrorMap.set(0x1778, LeafIndexOutOfBoundsError); nameToErrorMap.set('LeafIndexOutOfBounds', LeafIndexOutOfBoundsError); +/** CanopyNotAllocated: Tree was initialized without allocating space for the canopy */ +export class CanopyNotAllocatedError extends ProgramError { + readonly name: string = 'CanopyNotAllocated'; + + readonly code: number = 0x1779; // 6009 + + constructor(program: Program, cause?: Error) { + super( + 'Tree was initialized without allocating space for the canopy', + program, + cause + ); + } +} +codeToErrorMap.set(0x1779, CanopyNotAllocatedError); +nameToErrorMap.set('CanopyNotAllocated', CanopyNotAllocatedError); + +/** TreeAlreadyInitialized: Tree was already initialized */ +export class TreeAlreadyInitializedError extends ProgramError { + readonly name: string = 'TreeAlreadyInitialized'; + + readonly code: number = 0x177a; // 6010 + + constructor(program: Program, cause?: Error) { + super('Tree was already initialized', program, cause); + } +} +codeToErrorMap.set(0x177a, TreeAlreadyInitializedError); +nameToErrorMap.set('TreeAlreadyInitialized', TreeAlreadyInitializedError); + +/** BatchNotInitialized: Tree header was not initialized for batch processing */ +export class BatchNotInitializedError extends ProgramError { + readonly name: string = 'BatchNotInitialized'; + + readonly code: number = 0x177b; // 6011 + + constructor(program: Program, cause?: Error) { + super( + 'Tree header was not initialized for batch processing', + program, + cause + ); + } +} +codeToErrorMap.set(0x177b, BatchNotInitializedError); +nameToErrorMap.set('BatchNotInitialized', BatchNotInitializedError); + +/** CanopyRootMismatch: Canopy root does not match the root of the tree */ +export class CanopyRootMismatchError extends ProgramError { + readonly name: string = 'CanopyRootMismatch'; + + readonly code: number = 0x177c; // 6012 + + constructor(program: Program, cause?: Error) { + super('Canopy root does not match the root of the tree', program, cause); + } +} +codeToErrorMap.set(0x177c, CanopyRootMismatchError); +nameToErrorMap.set('CanopyRootMismatch', CanopyRootMismatchError); + +/** CanopyRightmostLeafMismatch: Canopy contains nodes to the right of the rightmost leaf of the tree */ +export class CanopyRightmostLeafMismatchError extends ProgramError { + readonly name: string = 'CanopyRightmostLeafMismatch'; + + readonly code: number = 0x177d; // 6013 + + constructor(program: Program, cause?: Error) { + super( + 'Canopy contains nodes to the right of the rightmost leaf of the tree', + program, + cause + ); + } +} +codeToErrorMap.set(0x177d, CanopyRightmostLeafMismatchError); +nameToErrorMap.set( + 'CanopyRightmostLeafMismatch', + CanopyRightmostLeafMismatchError +); + /** * Attempts to resolve a custom program error from the provided error code. * @category Errors diff --git a/clients/js/src/generated/instructions/appendCanopyNodes.ts b/clients/js/src/generated/instructions/appendCanopyNodes.ts new file mode 100644 index 00000000..7ae0e274 --- /dev/null +++ b/clients/js/src/generated/instructions/appendCanopyNodes.ts @@ -0,0 +1,137 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/metaplex-foundation/kinobi + */ + +import { + Context, + Pda, + PublicKey, + Signer, + TransactionBuilder, + transactionBuilder, +} from '@metaplex-foundation/umi'; +import { + Serializer, + array, + bytes, + mapSerializer, + struct, + u32, + u8, +} from '@metaplex-foundation/umi/serializers'; +import { + ResolvedAccount, + ResolvedAccountsWithIndices, + getAccountMetasAndSigners, +} from '../shared'; + +// Accounts. +export type AppendCanopyNodesInstructionAccounts = { + merkleTree: PublicKey | Pda; + /** + * Authority that controls write-access to the tree + * Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + */ + + authority?: Signer; + /** Program used to emit changelogs as cpi instruction data. */ + noop: PublicKey | Pda; +}; + +// Data. +export type AppendCanopyNodesInstructionData = { + discriminator: Array; + startIndex: number; + canopyNodes: Array; +}; + +export type AppendCanopyNodesInstructionDataArgs = { + startIndex: number; + canopyNodes: Array; +}; + +export function getAppendCanopyNodesInstructionDataSerializer(): Serializer< + AppendCanopyNodesInstructionDataArgs, + AppendCanopyNodesInstructionData +> { + return mapSerializer< + AppendCanopyNodesInstructionDataArgs, + any, + AppendCanopyNodesInstructionData + >( + struct( + [ + ['discriminator', array(u8(), { size: 8 })], + ['startIndex', u32()], + ['canopyNodes', array(bytes({ size: 32 }))], + ], + { description: 'AppendCanopyNodesInstructionData' } + ), + (value) => ({ + ...value, + discriminator: [139, 155, 238, 167, 11, 243, 132, 205], + }) + ) as Serializer< + AppendCanopyNodesInstructionDataArgs, + AppendCanopyNodesInstructionData + >; +} + +// Args. +export type AppendCanopyNodesInstructionArgs = + AppendCanopyNodesInstructionDataArgs; + +// Instruction. +export function appendCanopyNodes( + context: Pick, + input: AppendCanopyNodesInstructionAccounts & AppendCanopyNodesInstructionArgs +): TransactionBuilder { + // Program ID. + const programId = context.programs.getPublicKey( + 'splAccountCompression', + 'cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK' + ); + + // Accounts. + const resolvedAccounts: ResolvedAccountsWithIndices = { + merkleTree: { index: 0, isWritable: true, value: input.merkleTree ?? null }, + authority: { index: 1, isWritable: false, value: input.authority ?? null }, + noop: { index: 2, isWritable: false, value: input.noop ?? null }, + }; + + // Arguments. + const resolvedArgs: AppendCanopyNodesInstructionArgs = { ...input }; + + // Default values. + if (!resolvedAccounts.authority.value) { + resolvedAccounts.authority.value = context.identity; + } + + // Accounts in order. + const orderedAccounts: ResolvedAccount[] = Object.values( + resolvedAccounts + ).sort((a, b) => a.index - b.index); + + // Keys and Signers. + const [keys, signers] = getAccountMetasAndSigners( + orderedAccounts, + 'programId', + programId + ); + + // Data. + const data = getAppendCanopyNodesInstructionDataSerializer().serialize( + resolvedArgs as AppendCanopyNodesInstructionDataArgs + ); + + // Bytes Created On Chain. + const bytesCreatedOnChain = 0; + + return transactionBuilder([ + { instruction: { keys, programId, data }, signers, bytesCreatedOnChain }, + ]); +} diff --git a/clients/js/src/generated/instructions/index.ts b/clients/js/src/generated/instructions/index.ts index 13483a36..153551b2 100644 --- a/clients/js/src/generated/instructions/index.ts +++ b/clients/js/src/generated/instructions/index.ts @@ -7,6 +7,7 @@ */ export * from './addCanopy'; +export * from './appendCanopyNodes'; export * from './burn'; export * from './cancelRedeem'; export * from './createTreeConfig'; @@ -14,8 +15,10 @@ export * from './decompressV1'; export * from './delegate'; export * from './finalizeTreeWithRoot'; export * from './finalizeTreeWithRootAndCollection'; +export * from './initPreparedTreeWithRoot'; export * from './mintToCollectionV1'; export * from './mintV1'; +export * from './prepareBatchMerkleTree'; export * from './prepareTree'; export * from './redeem'; export * from './setAndVerifyCollection'; diff --git a/clients/js/src/generated/instructions/initPreparedTreeWithRoot.ts b/clients/js/src/generated/instructions/initPreparedTreeWithRoot.ts new file mode 100644 index 00000000..b86baf27 --- /dev/null +++ b/clients/js/src/generated/instructions/initPreparedTreeWithRoot.ts @@ -0,0 +1,141 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/metaplex-foundation/kinobi + */ + +import { + Context, + Pda, + PublicKey, + Signer, + TransactionBuilder, + transactionBuilder, +} from '@metaplex-foundation/umi'; +import { + Serializer, + array, + bytes, + mapSerializer, + struct, + u32, + u8, +} from '@metaplex-foundation/umi/serializers'; +import { + ResolvedAccount, + ResolvedAccountsWithIndices, + getAccountMetasAndSigners, +} from '../shared'; + +// Accounts. +export type InitPreparedTreeWithRootInstructionAccounts = { + merkleTree: PublicKey | Pda; + /** + * Authority that controls write-access to the tree + * Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + */ + + authority?: Signer; + /** Program used to emit changelogs as cpi instruction data. */ + noop: PublicKey | Pda; +}; + +// Data. +export type InitPreparedTreeWithRootInstructionData = { + discriminator: Array; + root: Uint8Array; + rightmostLeaf: Uint8Array; + rightmostIndex: number; +}; + +export type InitPreparedTreeWithRootInstructionDataArgs = { + root: Uint8Array; + rightmostLeaf: Uint8Array; + rightmostIndex: number; +}; + +export function getInitPreparedTreeWithRootInstructionDataSerializer(): Serializer< + InitPreparedTreeWithRootInstructionDataArgs, + InitPreparedTreeWithRootInstructionData +> { + return mapSerializer< + InitPreparedTreeWithRootInstructionDataArgs, + any, + InitPreparedTreeWithRootInstructionData + >( + struct( + [ + ['discriminator', array(u8(), { size: 8 })], + ['root', bytes({ size: 32 })], + ['rightmostLeaf', bytes({ size: 32 })], + ['rightmostIndex', u32()], + ], + { description: 'InitPreparedTreeWithRootInstructionData' } + ), + (value) => ({ + ...value, + discriminator: [218, 248, 192, 55, 91, 205, 122, 10], + }) + ) as Serializer< + InitPreparedTreeWithRootInstructionDataArgs, + InitPreparedTreeWithRootInstructionData + >; +} + +// Args. +export type InitPreparedTreeWithRootInstructionArgs = + InitPreparedTreeWithRootInstructionDataArgs; + +// Instruction. +export function initPreparedTreeWithRoot( + context: Pick, + input: InitPreparedTreeWithRootInstructionAccounts & + InitPreparedTreeWithRootInstructionArgs +): TransactionBuilder { + // Program ID. + const programId = context.programs.getPublicKey( + 'splAccountCompression', + 'cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK' + ); + + // Accounts. + const resolvedAccounts: ResolvedAccountsWithIndices = { + merkleTree: { index: 0, isWritable: true, value: input.merkleTree ?? null }, + authority: { index: 1, isWritable: false, value: input.authority ?? null }, + noop: { index: 2, isWritable: false, value: input.noop ?? null }, + }; + + // Arguments. + const resolvedArgs: InitPreparedTreeWithRootInstructionArgs = { ...input }; + + // Default values. + if (!resolvedAccounts.authority.value) { + resolvedAccounts.authority.value = context.identity; + } + + // Accounts in order. + const orderedAccounts: ResolvedAccount[] = Object.values( + resolvedAccounts + ).sort((a, b) => a.index - b.index); + + // Keys and Signers. + const [keys, signers] = getAccountMetasAndSigners( + orderedAccounts, + 'programId', + programId + ); + + // Data. + const data = getInitPreparedTreeWithRootInstructionDataSerializer().serialize( + resolvedArgs as InitPreparedTreeWithRootInstructionDataArgs + ); + + // Bytes Created On Chain. + const bytesCreatedOnChain = 0; + + return transactionBuilder([ + { instruction: { keys, programId, data }, signers, bytesCreatedOnChain }, + ]); +} diff --git a/clients/js/src/generated/instructions/prepareBatchMerkleTree.ts b/clients/js/src/generated/instructions/prepareBatchMerkleTree.ts new file mode 100644 index 00000000..6696a0c5 --- /dev/null +++ b/clients/js/src/generated/instructions/prepareBatchMerkleTree.ts @@ -0,0 +1,137 @@ +/** + * This code was AUTOGENERATED using the kinobi library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun kinobi to update it. + * + * @see https://github.com/metaplex-foundation/kinobi + */ + +import { + Context, + Pda, + PublicKey, + Signer, + TransactionBuilder, + transactionBuilder, +} from '@metaplex-foundation/umi'; +import { + Serializer, + array, + mapSerializer, + struct, + u32, + u8, +} from '@metaplex-foundation/umi/serializers'; +import { + ResolvedAccount, + ResolvedAccountsWithIndices, + getAccountMetasAndSigners, +} from '../shared'; + +// Accounts. +export type PrepareBatchMerkleTreeInstructionAccounts = { + merkleTree: PublicKey | Pda; + /** + * Authority that controls write-access to the tree + * Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + */ + + authority?: Signer; + /** Program used to emit changelogs as cpi instruction data. */ + noop: PublicKey | Pda; +}; + +// Data. +export type PrepareBatchMerkleTreeInstructionData = { + discriminator: Array; + maxDepth: number; + maxBufferSize: number; +}; + +export type PrepareBatchMerkleTreeInstructionDataArgs = { + maxDepth: number; + maxBufferSize: number; +}; + +export function getPrepareBatchMerkleTreeInstructionDataSerializer(): Serializer< + PrepareBatchMerkleTreeInstructionDataArgs, + PrepareBatchMerkleTreeInstructionData +> { + return mapSerializer< + PrepareBatchMerkleTreeInstructionDataArgs, + any, + PrepareBatchMerkleTreeInstructionData + >( + struct( + [ + ['discriminator', array(u8(), { size: 8 })], + ['maxDepth', u32()], + ['maxBufferSize', u32()], + ], + { description: 'PrepareBatchMerkleTreeInstructionData' } + ), + (value) => ({ + ...value, + discriminator: [230, 124, 120, 196, 249, 134, 199, 128], + }) + ) as Serializer< + PrepareBatchMerkleTreeInstructionDataArgs, + PrepareBatchMerkleTreeInstructionData + >; +} + +// Args. +export type PrepareBatchMerkleTreeInstructionArgs = + PrepareBatchMerkleTreeInstructionDataArgs; + +// Instruction. +export function prepareBatchMerkleTree( + context: Pick, + input: PrepareBatchMerkleTreeInstructionAccounts & + PrepareBatchMerkleTreeInstructionArgs +): TransactionBuilder { + // Program ID. + const programId = context.programs.getPublicKey( + 'splAccountCompression', + 'cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK' + ); + + // Accounts. + const resolvedAccounts: ResolvedAccountsWithIndices = { + merkleTree: { index: 0, isWritable: true, value: input.merkleTree ?? null }, + authority: { index: 1, isWritable: false, value: input.authority ?? null }, + noop: { index: 2, isWritable: false, value: input.noop ?? null }, + }; + + // Arguments. + const resolvedArgs: PrepareBatchMerkleTreeInstructionArgs = { ...input }; + + // Default values. + if (!resolvedAccounts.authority.value) { + resolvedAccounts.authority.value = context.identity; + } + + // Accounts in order. + const orderedAccounts: ResolvedAccount[] = Object.values( + resolvedAccounts + ).sort((a, b) => a.index - b.index); + + // Keys and Signers. + const [keys, signers] = getAccountMetasAndSigners( + orderedAccounts, + 'programId', + programId + ); + + // Data. + const data = getPrepareBatchMerkleTreeInstructionDataSerializer().serialize( + resolvedArgs as PrepareBatchMerkleTreeInstructionDataArgs + ); + + // Bytes Created On Chain. + const bytesCreatedOnChain = 0; + + return transactionBuilder([ + { instruction: { keys, programId, data }, signers, bytesCreatedOnChain }, + ]); +} diff --git a/clients/js/src/generated/types/concurrentMerkleTreeHeaderData.ts b/clients/js/src/generated/types/concurrentMerkleTreeHeaderData.ts index 5de85eee..10faa9d4 100644 --- a/clients/js/src/generated/types/concurrentMerkleTreeHeaderData.ts +++ b/clients/js/src/generated/types/concurrentMerkleTreeHeaderData.ts @@ -12,6 +12,7 @@ import { GetDataEnumKindContent, Serializer, array, + bool, dataEnum, publicKey as publicKeySerializer, struct, @@ -43,6 +44,12 @@ export type ConcurrentMerkleTreeHeaderData = { * Provides a lower-bound on what slot to start (re-)building a tree from. */ creationSlot: bigint; + /** + * A flag indicating whether the tree has been initialized with a root. + * This field was added together with the `finalize_tree_with_root` instruction. + * It takes 1 byte of space taken from the previous padding for existing accounts. + */ + isBatchInitialized: boolean; /** * Needs padding for the account to be 8-byte aligned * 8-byte alignment is necessary to zero-copy the SPL ConcurrentMerkleTree @@ -73,6 +80,12 @@ export type ConcurrentMerkleTreeHeaderDataArgs = { * Provides a lower-bound on what slot to start (re-)building a tree from. */ creationSlot: number | bigint; + /** + * A flag indicating whether the tree has been initialized with a root. + * This field was added together with the `finalize_tree_with_root` instruction. + * It takes 1 byte of space taken from the previous padding for existing accounts. + */ + isBatchInitialized: boolean; /** * Needs padding for the account to be 8-byte aligned * 8-byte alignment is necessary to zero-copy the SPL ConcurrentMerkleTree @@ -93,7 +106,8 @@ export function getConcurrentMerkleTreeHeaderDataSerializer(): Serializer< ['maxDepth', u32()], ['authority', publicKeySerializer()], ['creationSlot', u64()], - ['padding', array(u8(), { size: 6 })], + ['isBatchInitialized', bool()], + ['padding', array(u8(), { size: 5 })], ]), ], ], diff --git a/clients/rust/src/generated/errors/spl_account_compression.rs b/clients/rust/src/generated/errors/spl_account_compression.rs index 9c8c7da8..494234ff 100644 --- a/clients/rust/src/generated/errors/spl_account_compression.rs +++ b/clients/rust/src/generated/errors/spl_account_compression.rs @@ -37,6 +37,21 @@ pub enum SplAccountCompressionError { /// 6008 (0x1778) - Leaf index of concurrent merkle tree is out of bounds #[error("Leaf index of concurrent merkle tree is out of bounds")] LeafIndexOutOfBounds, + /// 6009 (0x1779) - Tree was initialized without allocating space for the canopy + #[error("Tree was initialized without allocating space for the canopy")] + CanopyNotAllocated, + /// 6010 (0x177A) - Tree was already initialized + #[error("Tree was already initialized")] + TreeAlreadyInitialized, + /// 6011 (0x177B) - Tree header was not initialized for batch processing + #[error("Tree header was not initialized for batch processing")] + BatchNotInitialized, + /// 6012 (0x177C) - Canopy root does not match the root of the tree + #[error("Canopy root does not match the root of the tree")] + CanopyRootMismatch, + /// 6013 (0x177D) - Canopy contains nodes to the right of the rightmost leaf of the tree + #[error("Canopy contains nodes to the right of the rightmost leaf of the tree")] + CanopyRightmostLeafMismatch, } impl solana_program::program_error::PrintProgramError for SplAccountCompressionError { diff --git a/clients/rust/src/generated/instructions/append_canopy_nodes.rs b/clients/rust/src/generated/instructions/append_canopy_nodes.rs new file mode 100644 index 00000000..a0061b5a --- /dev/null +++ b/clients/rust/src/generated/instructions/append_canopy_nodes.rs @@ -0,0 +1,416 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! [https://github.com/metaplex-foundation/kinobi] +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct AppendCanopyNodes { + pub merkle_tree: solana_program::pubkey::Pubkey, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: solana_program::pubkey::Pubkey, + /// Program used to emit changelogs as cpi instruction data. + pub noop: solana_program::pubkey::Pubkey, +} + +impl AppendCanopyNodes { + pub fn instruction( + &self, + args: AppendCanopyNodesInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: AppendCanopyNodesInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.merkle_tree, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.noop, false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = AppendCanopyNodesInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +struct AppendCanopyNodesInstructionData { + discriminator: [u8; 8], +} + +impl AppendCanopyNodesInstructionData { + fn new() -> Self { + Self { + discriminator: [139, 155, 238, 167, 11, 243, 132, 205], + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AppendCanopyNodesInstructionArgs { + pub start_index: u32, + pub canopy_nodes: Vec<[u8; 32]>, +} + +/// Instruction builder. +#[derive(Default)] +pub struct AppendCanopyNodesBuilder { + merkle_tree: Option, + authority: Option, + noop: Option, + start_index: Option, + canopy_nodes: Option>, + __remaining_accounts: Vec, +} + +impl AppendCanopyNodesBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn merkle_tree(&mut self, merkle_tree: solana_program::pubkey::Pubkey) -> &mut Self { + self.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: solana_program::pubkey::Pubkey) -> &mut Self { + self.noop = Some(noop); + self + } + #[inline(always)] + pub fn start_index(&mut self, start_index: u32) -> &mut Self { + self.start_index = Some(start_index); + self + } + #[inline(always)] + pub fn canopy_nodes(&mut self, canopy_nodes: Vec<[u8; 32]>) -> &mut Self { + self.canopy_nodes = Some(canopy_nodes); + self + } + /// Add an aditional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = AppendCanopyNodes { + merkle_tree: self.merkle_tree.expect("merkle_tree is not set"), + authority: self.authority.expect("authority is not set"), + noop: self.noop.expect("noop is not set"), + }; + let args = AppendCanopyNodesInstructionArgs { + start_index: self.start_index.clone().expect("start_index is not set"), + canopy_nodes: self.canopy_nodes.clone().expect("canopy_nodes is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `append_canopy_nodes` CPI accounts. +pub struct AppendCanopyNodesCpiAccounts<'a, 'b> { + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `append_canopy_nodes` CPI instruction. +pub struct AppendCanopyNodesCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: AppendCanopyNodesInstructionArgs, +} + +impl<'a, 'b> AppendCanopyNodesCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: AppendCanopyNodesCpiAccounts<'a, 'b>, + args: AppendCanopyNodesInstructionArgs, + ) -> Self { + Self { + __program: program, + merkle_tree: accounts.merkle_tree, + authority: accounts.authority, + noop: accounts.noop, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.merkle_tree.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.noop.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = AppendCanopyNodesInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.merkle_tree.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.noop.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// `append_canopy_nodes` CPI instruction builder. +pub struct AppendCanopyNodesCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> AppendCanopyNodesCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(AppendCanopyNodesCpiBuilderInstruction { + __program: program, + merkle_tree: None, + authority: None, + noop: None, + start_index: None, + canopy_nodes: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn merkle_tree( + &mut self, + merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.noop = Some(noop); + self + } + #[inline(always)] + pub fn start_index(&mut self, start_index: u32) -> &mut Self { + self.instruction.start_index = Some(start_index); + self + } + #[inline(always)] + pub fn canopy_nodes(&mut self, canopy_nodes: Vec<[u8; 32]>) -> &mut Self { + self.instruction.canopy_nodes = Some(canopy_nodes); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = AppendCanopyNodesInstructionArgs { + start_index: self + .instruction + .start_index + .clone() + .expect("start_index is not set"), + canopy_nodes: self + .instruction + .canopy_nodes + .clone() + .expect("canopy_nodes is not set"), + }; + let instruction = AppendCanopyNodesCpi { + __program: self.instruction.__program, + + merkle_tree: self + .instruction + .merkle_tree + .expect("merkle_tree is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + noop: self.instruction.noop.expect("noop is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +struct AppendCanopyNodesCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + merkle_tree: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + noop: Option<&'b solana_program::account_info::AccountInfo<'a>>, + start_index: Option, + canopy_nodes: Option>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/src/generated/instructions/init_prepared_tree_with_root.rs b/clients/rust/src/generated/instructions/init_prepared_tree_with_root.rs new file mode 100644 index 00000000..4479bef0 --- /dev/null +++ b/clients/rust/src/generated/instructions/init_prepared_tree_with_root.rs @@ -0,0 +1,438 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! [https://github.com/metaplex-foundation/kinobi] +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct InitPreparedTreeWithRoot { + pub merkle_tree: solana_program::pubkey::Pubkey, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: solana_program::pubkey::Pubkey, + /// Program used to emit changelogs as cpi instruction data. + pub noop: solana_program::pubkey::Pubkey, +} + +impl InitPreparedTreeWithRoot { + pub fn instruction( + &self, + args: InitPreparedTreeWithRootInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: InitPreparedTreeWithRootInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.merkle_tree, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.noop, false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = InitPreparedTreeWithRootInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +struct InitPreparedTreeWithRootInstructionData { + discriminator: [u8; 8], +} + +impl InitPreparedTreeWithRootInstructionData { + fn new() -> Self { + Self { + discriminator: [218, 248, 192, 55, 91, 205, 122, 10], + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InitPreparedTreeWithRootInstructionArgs { + pub root: [u8; 32], + pub rightmost_leaf: [u8; 32], + pub rightmost_index: u32, +} + +/// Instruction builder. +#[derive(Default)] +pub struct InitPreparedTreeWithRootBuilder { + merkle_tree: Option, + authority: Option, + noop: Option, + root: Option<[u8; 32]>, + rightmost_leaf: Option<[u8; 32]>, + rightmost_index: Option, + __remaining_accounts: Vec, +} + +impl InitPreparedTreeWithRootBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn merkle_tree(&mut self, merkle_tree: solana_program::pubkey::Pubkey) -> &mut Self { + self.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: solana_program::pubkey::Pubkey) -> &mut Self { + self.noop = Some(noop); + self + } + #[inline(always)] + pub fn root(&mut self, root: [u8; 32]) -> &mut Self { + self.root = Some(root); + self + } + #[inline(always)] + pub fn rightmost_leaf(&mut self, rightmost_leaf: [u8; 32]) -> &mut Self { + self.rightmost_leaf = Some(rightmost_leaf); + self + } + #[inline(always)] + pub fn rightmost_index(&mut self, rightmost_index: u32) -> &mut Self { + self.rightmost_index = Some(rightmost_index); + self + } + /// Add an aditional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = InitPreparedTreeWithRoot { + merkle_tree: self.merkle_tree.expect("merkle_tree is not set"), + authority: self.authority.expect("authority is not set"), + noop: self.noop.expect("noop is not set"), + }; + let args = InitPreparedTreeWithRootInstructionArgs { + root: self.root.clone().expect("root is not set"), + rightmost_leaf: self + .rightmost_leaf + .clone() + .expect("rightmost_leaf is not set"), + rightmost_index: self + .rightmost_index + .clone() + .expect("rightmost_index is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `init_prepared_tree_with_root` CPI accounts. +pub struct InitPreparedTreeWithRootCpiAccounts<'a, 'b> { + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `init_prepared_tree_with_root` CPI instruction. +pub struct InitPreparedTreeWithRootCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: InitPreparedTreeWithRootInstructionArgs, +} + +impl<'a, 'b> InitPreparedTreeWithRootCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: InitPreparedTreeWithRootCpiAccounts<'a, 'b>, + args: InitPreparedTreeWithRootInstructionArgs, + ) -> Self { + Self { + __program: program, + merkle_tree: accounts.merkle_tree, + authority: accounts.authority, + noop: accounts.noop, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.merkle_tree.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.noop.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = InitPreparedTreeWithRootInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.merkle_tree.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.noop.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// `init_prepared_tree_with_root` CPI instruction builder. +pub struct InitPreparedTreeWithRootCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitPreparedTreeWithRootCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitPreparedTreeWithRootCpiBuilderInstruction { + __program: program, + merkle_tree: None, + authority: None, + noop: None, + root: None, + rightmost_leaf: None, + rightmost_index: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn merkle_tree( + &mut self, + merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.noop = Some(noop); + self + } + #[inline(always)] + pub fn root(&mut self, root: [u8; 32]) -> &mut Self { + self.instruction.root = Some(root); + self + } + #[inline(always)] + pub fn rightmost_leaf(&mut self, rightmost_leaf: [u8; 32]) -> &mut Self { + self.instruction.rightmost_leaf = Some(rightmost_leaf); + self + } + #[inline(always)] + pub fn rightmost_index(&mut self, rightmost_index: u32) -> &mut Self { + self.instruction.rightmost_index = Some(rightmost_index); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = InitPreparedTreeWithRootInstructionArgs { + root: self.instruction.root.clone().expect("root is not set"), + rightmost_leaf: self + .instruction + .rightmost_leaf + .clone() + .expect("rightmost_leaf is not set"), + rightmost_index: self + .instruction + .rightmost_index + .clone() + .expect("rightmost_index is not set"), + }; + let instruction = InitPreparedTreeWithRootCpi { + __program: self.instruction.__program, + + merkle_tree: self + .instruction + .merkle_tree + .expect("merkle_tree is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + noop: self.instruction.noop.expect("noop is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +struct InitPreparedTreeWithRootCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + merkle_tree: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + noop: Option<&'b solana_program::account_info::AccountInfo<'a>>, + root: Option<[u8; 32]>, + rightmost_leaf: Option<[u8; 32]>, + rightmost_index: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/src/generated/instructions/mod.rs b/clients/rust/src/generated/instructions/mod.rs index ab3f9e80..9e7c778a 100644 --- a/clients/rust/src/generated/instructions/mod.rs +++ b/clients/rust/src/generated/instructions/mod.rs @@ -6,6 +6,7 @@ //! pub(crate) mod add_canopy; +pub(crate) mod append_canopy_nodes; pub(crate) mod burn; pub(crate) mod cancel_redeem; pub(crate) mod create_tree_config; @@ -13,8 +14,10 @@ pub(crate) mod decompress_v1; pub(crate) mod delegate; pub(crate) mod finalize_tree_with_root; pub(crate) mod finalize_tree_with_root_and_collection; +pub(crate) mod init_prepared_tree_with_root; pub(crate) mod mint_to_collection_v1; pub(crate) mod mint_v1; +pub(crate) mod prepare_batch_merkle_tree; pub(crate) mod prepare_tree; pub(crate) mod redeem; pub(crate) mod set_and_verify_collection; @@ -29,6 +32,7 @@ pub(crate) mod verify_creator; pub(crate) mod verify_leaf; pub use self::add_canopy::*; +pub use self::append_canopy_nodes::*; pub use self::burn::*; pub use self::cancel_redeem::*; pub use self::create_tree_config::*; @@ -36,8 +40,10 @@ pub use self::decompress_v1::*; pub use self::delegate::*; pub use self::finalize_tree_with_root::*; pub use self::finalize_tree_with_root_and_collection::*; +pub use self::init_prepared_tree_with_root::*; pub use self::mint_to_collection_v1::*; pub use self::mint_v1::*; +pub use self::prepare_batch_merkle_tree::*; pub use self::prepare_tree::*; pub use self::redeem::*; pub use self::set_and_verify_collection::*; diff --git a/clients/rust/src/generated/instructions/prepare_batch_merkle_tree.rs b/clients/rust/src/generated/instructions/prepare_batch_merkle_tree.rs new file mode 100644 index 00000000..389df4ec --- /dev/null +++ b/clients/rust/src/generated/instructions/prepare_batch_merkle_tree.rs @@ -0,0 +1,419 @@ +//! This code was AUTOGENERATED using the kinobi library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun kinobi to update it. +//! +//! [https://github.com/metaplex-foundation/kinobi] +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct PrepareBatchMerkleTree { + pub merkle_tree: solana_program::pubkey::Pubkey, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: solana_program::pubkey::Pubkey, + /// Program used to emit changelogs as cpi instruction data. + pub noop: solana_program::pubkey::Pubkey, +} + +impl PrepareBatchMerkleTree { + pub fn instruction( + &self, + args: PrepareBatchMerkleTreeInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: PrepareBatchMerkleTreeInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.merkle_tree, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.noop, false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = PrepareBatchMerkleTreeInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +struct PrepareBatchMerkleTreeInstructionData { + discriminator: [u8; 8], +} + +impl PrepareBatchMerkleTreeInstructionData { + fn new() -> Self { + Self { + discriminator: [230, 124, 120, 196, 249, 134, 199, 128], + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct PrepareBatchMerkleTreeInstructionArgs { + pub max_depth: u32, + pub max_buffer_size: u32, +} + +/// Instruction builder. +#[derive(Default)] +pub struct PrepareBatchMerkleTreeBuilder { + merkle_tree: Option, + authority: Option, + noop: Option, + max_depth: Option, + max_buffer_size: Option, + __remaining_accounts: Vec, +} + +impl PrepareBatchMerkleTreeBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn merkle_tree(&mut self, merkle_tree: solana_program::pubkey::Pubkey) -> &mut Self { + self.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: solana_program::pubkey::Pubkey) -> &mut Self { + self.noop = Some(noop); + self + } + #[inline(always)] + pub fn max_depth(&mut self, max_depth: u32) -> &mut Self { + self.max_depth = Some(max_depth); + self + } + #[inline(always)] + pub fn max_buffer_size(&mut self, max_buffer_size: u32) -> &mut Self { + self.max_buffer_size = Some(max_buffer_size); + self + } + /// Add an aditional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = PrepareBatchMerkleTree { + merkle_tree: self.merkle_tree.expect("merkle_tree is not set"), + authority: self.authority.expect("authority is not set"), + noop: self.noop.expect("noop is not set"), + }; + let args = PrepareBatchMerkleTreeInstructionArgs { + max_depth: self.max_depth.clone().expect("max_depth is not set"), + max_buffer_size: self + .max_buffer_size + .clone() + .expect("max_buffer_size is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `prepare_batch_merkle_tree` CPI accounts. +pub struct PrepareBatchMerkleTreeCpiAccounts<'a, 'b> { + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `prepare_batch_merkle_tree` CPI instruction. +pub struct PrepareBatchMerkleTreeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + /// Program used to emit changelogs as cpi instruction data. + pub noop: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: PrepareBatchMerkleTreeInstructionArgs, +} + +impl<'a, 'b> PrepareBatchMerkleTreeCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: PrepareBatchMerkleTreeCpiAccounts<'a, 'b>, + args: PrepareBatchMerkleTreeInstructionArgs, + ) -> Self { + Self { + __program: program, + merkle_tree: accounts.merkle_tree, + authority: accounts.authority, + noop: accounts.noop, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(3 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.merkle_tree.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.noop.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = PrepareBatchMerkleTreeInstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::SPL_ACCOUNT_COMPRESSION_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(3 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.merkle_tree.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.noop.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// `prepare_batch_merkle_tree` CPI instruction builder. +pub struct PrepareBatchMerkleTreeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> PrepareBatchMerkleTreeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(PrepareBatchMerkleTreeCpiBuilderInstruction { + __program: program, + merkle_tree: None, + authority: None, + noop: None, + max_depth: None, + max_buffer_size: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn merkle_tree( + &mut self, + merkle_tree: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.merkle_tree = Some(merkle_tree); + self + } + /// Authority that controls write-access to the tree + /// Typically a program, e.g., the Bubblegum contract validates that leaves are valid NFTs. + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + /// Program used to emit changelogs as cpi instruction data. + #[inline(always)] + pub fn noop(&mut self, noop: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.noop = Some(noop); + self + } + #[inline(always)] + pub fn max_depth(&mut self, max_depth: u32) -> &mut Self { + self.instruction.max_depth = Some(max_depth); + self + } + #[inline(always)] + pub fn max_buffer_size(&mut self, max_buffer_size: u32) -> &mut Self { + self.instruction.max_buffer_size = Some(max_buffer_size); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = PrepareBatchMerkleTreeInstructionArgs { + max_depth: self + .instruction + .max_depth + .clone() + .expect("max_depth is not set"), + max_buffer_size: self + .instruction + .max_buffer_size + .clone() + .expect("max_buffer_size is not set"), + }; + let instruction = PrepareBatchMerkleTreeCpi { + __program: self.instruction.__program, + + merkle_tree: self + .instruction + .merkle_tree + .expect("merkle_tree is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + noop: self.instruction.noop.expect("noop is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +struct PrepareBatchMerkleTreeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + merkle_tree: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + noop: Option<&'b solana_program::account_info::AccountInfo<'a>>, + max_depth: Option, + max_buffer_size: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/clients/rust/src/generated/types/concurrent_merkle_tree_header_data.rs b/clients/rust/src/generated/types/concurrent_merkle_tree_header_data.rs index d1eb41fd..61a0a577 100644 --- a/clients/rust/src/generated/types/concurrent_merkle_tree_header_data.rs +++ b/clients/rust/src/generated/types/concurrent_merkle_tree_header_data.rs @@ -30,8 +30,12 @@ pub enum ConcurrentMerkleTreeHeaderData { /// Slot corresponding to when the Merkle tree was created. /// Provides a lower-bound on what slot to start (re-)building a tree from. creation_slot: u64, + /// A flag indicating whether the tree has been initialized with a root. + /// This field was added together with the `finalize_tree_with_root` instruction. + /// It takes 1 byte of space taken from the previous padding for existing accounts. + is_batch_initialized: bool, /// Needs padding for the account to be 8-byte aligned /// 8-byte alignment is necessary to zero-copy the SPL ConcurrentMerkleTree - padding: [u8; 6], + padding: [u8; 5], }, }