diff --git a/clients/js/src/generated/instructions/index.ts b/clients/js/src/generated/instructions/index.ts index 263e35f6..7ffc9bb3 100644 --- a/clients/js/src/generated/instructions/index.ts +++ b/clients/js/src/generated/instructions/index.ts @@ -34,3 +34,5 @@ export * from './updateCollectionV1'; export * from './updateExternalPluginV1'; export * from './updatePluginV1'; export * from './updateV1'; +export * from './writeCollectionExternalPluginDataV1'; +export * from './writeExternalPluginDataV1'; diff --git a/clients/js/src/generated/instructions/writeCollectionExternalPluginDataV1.ts b/clients/js/src/generated/instructions/writeCollectionExternalPluginDataV1.ts new file mode 100644 index 00000000..8e2bad38 --- /dev/null +++ b/clients/js/src/generated/instructions/writeCollectionExternalPluginDataV1.ts @@ -0,0 +1,172 @@ +/** + * 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, + bytes, + mapSerializer, + struct, + u32, + u8, +} from '@metaplex-foundation/umi/serializers'; +import { + ResolvedAccount, + ResolvedAccountsWithIndices, + getAccountMetasAndSigners, +} from '../shared'; +import { + ExternalPluginKey, + ExternalPluginKeyArgs, + getExternalPluginKeySerializer, +} from '../types'; + +// Accounts. +export type WriteCollectionExternalPluginDataV1InstructionAccounts = { + /** The address of the asset */ + collection: PublicKey | Pda; + /** The account paying for the storage fees */ + payer?: Signer; + /** The Data Authority of the External Plugin */ + authority?: Signer; + /** The system program */ + systemProgram?: PublicKey | Pda; + /** The SPL Noop Program */ + logWrapper?: PublicKey | Pda; +}; + +// Data. +export type WriteCollectionExternalPluginDataV1InstructionData = { + discriminator: number; + key: ExternalPluginKey; + data: Uint8Array; +}; + +export type WriteCollectionExternalPluginDataV1InstructionDataArgs = { + key: ExternalPluginKeyArgs; + data: Uint8Array; +}; + +export function getWriteCollectionExternalPluginDataV1InstructionDataSerializer(): Serializer< + WriteCollectionExternalPluginDataV1InstructionDataArgs, + WriteCollectionExternalPluginDataV1InstructionData +> { + return mapSerializer< + WriteCollectionExternalPluginDataV1InstructionDataArgs, + any, + WriteCollectionExternalPluginDataV1InstructionData + >( + struct( + [ + ['discriminator', u8()], + ['key', getExternalPluginKeySerializer()], + ['data', bytes({ size: u32() })], + ], + { description: 'WriteCollectionExternalPluginDataV1InstructionData' } + ), + (value) => ({ ...value, discriminator: 29 }) + ) as Serializer< + WriteCollectionExternalPluginDataV1InstructionDataArgs, + WriteCollectionExternalPluginDataV1InstructionData + >; +} + +// Args. +export type WriteCollectionExternalPluginDataV1InstructionArgs = + WriteCollectionExternalPluginDataV1InstructionDataArgs; + +// Instruction. +export function writeCollectionExternalPluginDataV1( + context: Pick, + input: WriteCollectionExternalPluginDataV1InstructionAccounts & + WriteCollectionExternalPluginDataV1InstructionArgs +): TransactionBuilder { + // Program ID. + const programId = context.programs.getPublicKey( + 'mplCore', + 'CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d' + ); + + // Accounts. + const resolvedAccounts = { + collection: { + index: 0, + isWritable: true as boolean, + value: input.collection ?? null, + }, + payer: { + index: 1, + isWritable: true as boolean, + value: input.payer ?? null, + }, + authority: { + index: 2, + isWritable: false as boolean, + value: input.authority ?? null, + }, + systemProgram: { + index: 3, + isWritable: false as boolean, + value: input.systemProgram ?? null, + }, + logWrapper: { + index: 4, + isWritable: false as boolean, + value: input.logWrapper ?? null, + }, + } satisfies ResolvedAccountsWithIndices; + + // Arguments. + const resolvedArgs: WriteCollectionExternalPluginDataV1InstructionArgs = { + ...input, + }; + + // Default values. + if (!resolvedAccounts.payer.value) { + resolvedAccounts.payer.value = context.payer; + } + if (!resolvedAccounts.systemProgram.value) { + resolvedAccounts.systemProgram.value = context.programs.getPublicKey( + 'splSystem', + '11111111111111111111111111111111' + ); + resolvedAccounts.systemProgram.isWritable = false; + } + + // 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 = + getWriteCollectionExternalPluginDataV1InstructionDataSerializer().serialize( + resolvedArgs as WriteCollectionExternalPluginDataV1InstructionDataArgs + ); + + // Bytes Created On Chain. + const bytesCreatedOnChain = 0; + + return transactionBuilder([ + { instruction: { keys, programId, data }, signers, bytesCreatedOnChain }, + ]); +} diff --git a/clients/js/src/generated/instructions/writeExternalPluginDataV1.ts b/clients/js/src/generated/instructions/writeExternalPluginDataV1.ts new file mode 100644 index 00000000..ba8781a1 --- /dev/null +++ b/clients/js/src/generated/instructions/writeExternalPluginDataV1.ts @@ -0,0 +1,177 @@ +/** + * 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, + bytes, + mapSerializer, + struct, + u32, + u8, +} from '@metaplex-foundation/umi/serializers'; +import { + ResolvedAccount, + ResolvedAccountsWithIndices, + getAccountMetasAndSigners, +} from '../shared'; +import { + ExternalPluginKey, + ExternalPluginKeyArgs, + getExternalPluginKeySerializer, +} from '../types'; + +// Accounts. +export type WriteExternalPluginDataV1InstructionAccounts = { + /** The address of the asset */ + asset: PublicKey | Pda; + /** The collection to which the asset belongs */ + collection?: PublicKey | Pda; + /** The account paying for the storage fees */ + payer?: Signer; + /** The Data Authority of the External Plugin */ + authority?: Signer; + /** The system program */ + systemProgram?: PublicKey | Pda; + /** The SPL Noop Program */ + logWrapper?: PublicKey | Pda; +}; + +// Data. +export type WriteExternalPluginDataV1InstructionData = { + discriminator: number; + key: ExternalPluginKey; + data: Uint8Array; +}; + +export type WriteExternalPluginDataV1InstructionDataArgs = { + key: ExternalPluginKeyArgs; + data: Uint8Array; +}; + +export function getWriteExternalPluginDataV1InstructionDataSerializer(): Serializer< + WriteExternalPluginDataV1InstructionDataArgs, + WriteExternalPluginDataV1InstructionData +> { + return mapSerializer< + WriteExternalPluginDataV1InstructionDataArgs, + any, + WriteExternalPluginDataV1InstructionData + >( + struct( + [ + ['discriminator', u8()], + ['key', getExternalPluginKeySerializer()], + ['data', bytes({ size: u32() })], + ], + { description: 'WriteExternalPluginDataV1InstructionData' } + ), + (value) => ({ ...value, discriminator: 28 }) + ) as Serializer< + WriteExternalPluginDataV1InstructionDataArgs, + WriteExternalPluginDataV1InstructionData + >; +} + +// Args. +export type WriteExternalPluginDataV1InstructionArgs = + WriteExternalPluginDataV1InstructionDataArgs; + +// Instruction. +export function writeExternalPluginDataV1( + context: Pick, + input: WriteExternalPluginDataV1InstructionAccounts & + WriteExternalPluginDataV1InstructionArgs +): TransactionBuilder { + // Program ID. + const programId = context.programs.getPublicKey( + 'mplCore', + 'CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d' + ); + + // Accounts. + const resolvedAccounts = { + asset: { + index: 0, + isWritable: true as boolean, + value: input.asset ?? null, + }, + collection: { + index: 1, + isWritable: true as boolean, + value: input.collection ?? null, + }, + payer: { + index: 2, + isWritable: true as boolean, + value: input.payer ?? null, + }, + authority: { + index: 3, + isWritable: false as boolean, + value: input.authority ?? null, + }, + systemProgram: { + index: 4, + isWritable: false as boolean, + value: input.systemProgram ?? null, + }, + logWrapper: { + index: 5, + isWritable: false as boolean, + value: input.logWrapper ?? null, + }, + } satisfies ResolvedAccountsWithIndices; + + // Arguments. + const resolvedArgs: WriteExternalPluginDataV1InstructionArgs = { ...input }; + + // Default values. + if (!resolvedAccounts.payer.value) { + resolvedAccounts.payer.value = context.payer; + } + if (!resolvedAccounts.systemProgram.value) { + resolvedAccounts.systemProgram.value = context.programs.getPublicKey( + 'splSystem', + '11111111111111111111111111111111' + ); + resolvedAccounts.systemProgram.isWritable = false; + } + + // 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 = + getWriteExternalPluginDataV1InstructionDataSerializer().serialize( + resolvedArgs as WriteExternalPluginDataV1InstructionDataArgs + ); + + // Bytes Created On Chain. + const bytesCreatedOnChain = 0; + + return transactionBuilder([ + { instruction: { keys, programId, data }, signers, bytesCreatedOnChain }, + ]); +} diff --git a/clients/js/src/generated/types/externalPluginInitInfo.ts b/clients/js/src/generated/types/externalPluginInitInfo.ts index c41d8803..194ccfee 100644 --- a/clients/js/src/generated/types/externalPluginInitInfo.ts +++ b/clients/js/src/generated/types/externalPluginInitInfo.ts @@ -85,14 +85,14 @@ export function externalPluginInitInfo( >['fields'] ): GetDataEnumKind; export function externalPluginInitInfo< - K extends ExternalPluginInitInfoArgs['__kind'] + K extends ExternalPluginInitInfoArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } : { __kind: kind, ...(data ?? {}) }; } export function isExternalPluginInitInfo< - K extends ExternalPluginInitInfo['__kind'] + K extends ExternalPluginInitInfo['__kind'], >( kind: K, value: ExternalPluginInitInfo diff --git a/clients/js/src/generated/types/externalPluginUpdateInfo.ts b/clients/js/src/generated/types/externalPluginUpdateInfo.ts index 4e232e8e..93848277 100644 --- a/clients/js/src/generated/types/externalPluginUpdateInfo.ts +++ b/clients/js/src/generated/types/externalPluginUpdateInfo.ts @@ -85,14 +85,14 @@ export function externalPluginUpdateInfo( >['fields'] ): GetDataEnumKind; export function externalPluginUpdateInfo< - K extends ExternalPluginUpdateInfoArgs['__kind'] + K extends ExternalPluginUpdateInfoArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } : { __kind: kind, ...(data ?? {}) }; } export function isExternalPluginUpdateInfo< - K extends ExternalPluginUpdateInfo['__kind'] + K extends ExternalPluginUpdateInfo['__kind'], >( kind: K, value: ExternalPluginUpdateInfo diff --git a/clients/js/src/generated/types/lifecycleHook.ts b/clients/js/src/generated/types/lifecycleHook.ts index 8d444400..3689a806 100644 --- a/clients/js/src/generated/types/lifecycleHook.ts +++ b/clients/js/src/generated/types/lifecycleHook.ts @@ -20,13 +20,17 @@ import { ExternalPluginSchemaArgs, ExtraAccount, ExtraAccountArgs, + PluginAuthority, + PluginAuthorityArgs, getExternalPluginSchemaSerializer, getExtraAccountSerializer, + getPluginAuthoritySerializer, } from '.'; export type LifecycleHook = { hookedProgram: PublicKey; extraAccounts: Option>; + dataAuthority: Option; schema: ExternalPluginSchema; dataOffset: bigint; dataLen: bigint; @@ -35,6 +39,7 @@ export type LifecycleHook = { export type LifecycleHookArgs = { hookedProgram: PublicKey; extraAccounts: OptionOrNullable>; + dataAuthority: OptionOrNullable; schema: ExternalPluginSchemaArgs; dataOffset: number | bigint; dataLen: number | bigint; @@ -48,6 +53,7 @@ export function getLifecycleHookSerializer(): Serializer< [ ['hookedProgram', publicKeySerializer()], ['extraAccounts', option(array(getExtraAccountSerializer()))], + ['dataAuthority', option(getPluginAuthoritySerializer())], ['schema', getExternalPluginSchemaSerializer()], ['dataOffset', u64()], ['dataLen', u64()], diff --git a/clients/js/src/generated/types/lifecycleHookInitInfo.ts b/clients/js/src/generated/types/lifecycleHookInitInfo.ts index 789aa1ec..25b54483 100644 --- a/clients/js/src/generated/types/lifecycleHookInitInfo.ts +++ b/clients/js/src/generated/types/lifecycleHookInitInfo.ts @@ -38,6 +38,7 @@ export type LifecycleHookInitInfo = { initPluginAuthority: Option; lifecycleChecks: Option>; extraAccounts: Option>; + dataAuthority: Option; schema: Option; }; @@ -48,6 +49,7 @@ export type LifecycleHookInitInfoArgs = { Array<[HookableLifecycleEventArgs, ExternalCheckResultArgs]> >; extraAccounts: OptionOrNullable>; + dataAuthority: OptionOrNullable; schema: OptionOrNullable; }; @@ -71,6 +73,7 @@ export function getLifecycleHookInitInfoSerializer(): Serializer< ), ], ['extraAccounts', option(array(getExtraAccountSerializer()))], + ['dataAuthority', option(getPluginAuthoritySerializer())], ['schema', option(getExternalPluginSchemaSerializer())], ], { description: 'LifecycleHookInitInfo' } diff --git a/clients/rust/src/generated/instructions/mod.rs b/clients/rust/src/generated/instructions/mod.rs index 73ca2983..8f936d43 100644 --- a/clients/rust/src/generated/instructions/mod.rs +++ b/clients/rust/src/generated/instructions/mod.rs @@ -33,6 +33,8 @@ pub(crate) mod r#update_collection_v1; pub(crate) mod r#update_external_plugin_v1; pub(crate) mod r#update_plugin_v1; pub(crate) mod r#update_v1; +pub(crate) mod r#write_collection_external_plugin_data_v1; +pub(crate) mod r#write_external_plugin_data_v1; pub use self::r#add_collection_external_plugin_v1::*; pub use self::r#add_collection_plugin_v1::*; @@ -62,3 +64,5 @@ pub use self::r#update_collection_v1::*; pub use self::r#update_external_plugin_v1::*; pub use self::r#update_plugin_v1::*; pub use self::r#update_v1::*; +pub use self::r#write_collection_external_plugin_data_v1::*; +pub use self::r#write_external_plugin_data_v1::*; diff --git a/clients/rust/src/generated/instructions/write_collection_external_plugin_data_v1.rs b/clients/rust/src/generated/instructions/write_collection_external_plugin_data_v1.rs new file mode 100644 index 00000000..5dcee063 --- /dev/null +++ b/clients/rust/src/generated/instructions/write_collection_external_plugin_data_v1.rs @@ -0,0 +1,537 @@ +//! 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 crate::generated::types::ExternalPluginKey; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct WriteCollectionExternalPluginDataV1 { + /// The address of the asset + pub collection: solana_program::pubkey::Pubkey, + /// The account paying for the storage fees + pub payer: solana_program::pubkey::Pubkey, + /// The Data Authority of the External Plugin + pub authority: Option, + /// The system program + pub system_program: solana_program::pubkey::Pubkey, + /// The SPL Noop Program + pub log_wrapper: Option, +} + +impl WriteCollectionExternalPluginDataV1 { + pub fn instruction( + &self, + args: WriteCollectionExternalPluginDataV1InstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: WriteCollectionExternalPluginDataV1InstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.collection, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + if let Some(authority) = self.authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + authority, true, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + if let Some(log_wrapper) = self.log_wrapper { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + log_wrapper, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = WriteCollectionExternalPluginDataV1InstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::MPL_CORE_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +struct WriteCollectionExternalPluginDataV1InstructionData { + discriminator: u8, +} + +impl WriteCollectionExternalPluginDataV1InstructionData { + fn new() -> Self { + Self { discriminator: 29 } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WriteCollectionExternalPluginDataV1InstructionArgs { + pub key: ExternalPluginKey, + pub data: Vec, +} + +/// Instruction builder for `WriteCollectionExternalPluginDataV1`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` collection +/// 1. `[writable, signer]` payer +/// 2. `[signer, optional]` authority +/// 3. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 4. `[optional]` log_wrapper +#[derive(Default)] +pub struct WriteCollectionExternalPluginDataV1Builder { + collection: Option, + payer: Option, + authority: Option, + system_program: Option, + log_wrapper: Option, + key: Option, + data: Option>, + __remaining_accounts: Vec, +} + +impl WriteCollectionExternalPluginDataV1Builder { + pub fn new() -> Self { + Self::default() + } + /// The address of the asset + #[inline(always)] + pub fn collection(&mut self, collection: solana_program::pubkey::Pubkey) -> &mut Self { + self.collection = Some(collection); + self + } + /// The account paying for the storage fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account]` + /// The Data Authority of the External Plugin + #[inline(always)] + pub fn authority(&mut self, authority: Option) -> &mut Self { + self.authority = authority; + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// The system program + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account]` + /// The SPL Noop Program + #[inline(always)] + pub fn log_wrapper( + &mut self, + log_wrapper: Option, + ) -> &mut Self { + self.log_wrapper = log_wrapper; + self + } + #[inline(always)] + pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self { + self.key = Some(key); + self + } + #[inline(always)] + pub fn data(&mut self, data: Vec) -> &mut Self { + self.data = Some(data); + 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 = WriteCollectionExternalPluginDataV1 { + collection: self.collection.expect("collection is not set"), + payer: self.payer.expect("payer is not set"), + authority: self.authority, + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + log_wrapper: self.log_wrapper, + }; + let args = WriteCollectionExternalPluginDataV1InstructionArgs { + key: self.key.clone().expect("key is not set"), + data: self.data.clone().expect("data is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `write_collection_external_plugin_data_v1` CPI accounts. +pub struct WriteCollectionExternalPluginDataV1CpiAccounts<'a, 'b> { + /// The address of the asset + pub collection: &'b solana_program::account_info::AccountInfo<'a>, + /// The account paying for the storage fees + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + /// The Data Authority of the External Plugin + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The system program + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The SPL Noop Program + pub log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, +} + +/// `write_collection_external_plugin_data_v1` CPI instruction. +pub struct WriteCollectionExternalPluginDataV1Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + /// The address of the asset + pub collection: &'b solana_program::account_info::AccountInfo<'a>, + /// The account paying for the storage fees + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + /// The Data Authority of the External Plugin + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The system program + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The SPL Noop Program + pub log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: WriteCollectionExternalPluginDataV1InstructionArgs, +} + +impl<'a, 'b> WriteCollectionExternalPluginDataV1Cpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: WriteCollectionExternalPluginDataV1CpiAccounts<'a, 'b>, + args: WriteCollectionExternalPluginDataV1InstructionArgs, + ) -> Self { + Self { + __program: program, + collection: accounts.collection, + payer: accounts.payer, + authority: accounts.authority, + system_program: accounts.system_program, + log_wrapper: accounts.log_wrapper, + __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(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.collection.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + if let Some(authority) = self.authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *authority.key, + true, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + if let Some(log_wrapper) = self.log_wrapper { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *log_wrapper.key, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + 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 = WriteCollectionExternalPluginDataV1InstructionData::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::MPL_CORE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.collection.clone()); + account_infos.push(self.payer.clone()); + if let Some(authority) = self.authority { + account_infos.push(authority.clone()); + } + account_infos.push(self.system_program.clone()); + if let Some(log_wrapper) = self.log_wrapper { + account_infos.push(log_wrapper.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) + } + } +} + +/// Instruction builder for `WriteCollectionExternalPluginDataV1` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` collection +/// 1. `[writable, signer]` payer +/// 2. `[signer, optional]` authority +/// 3. `[]` system_program +/// 4. `[optional]` log_wrapper +pub struct WriteCollectionExternalPluginDataV1CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> WriteCollectionExternalPluginDataV1CpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(WriteCollectionExternalPluginDataV1CpiBuilderInstruction { + __program: program, + collection: None, + payer: None, + authority: None, + system_program: None, + log_wrapper: None, + key: None, + data: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The address of the asset + #[inline(always)] + pub fn collection( + &mut self, + collection: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.collection = Some(collection); + self + } + /// The account paying for the storage fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// `[optional account]` + /// The Data Authority of the External Plugin + #[inline(always)] + pub fn authority( + &mut self, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.authority = authority; + self + } + /// The system program + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// `[optional account]` + /// The SPL Noop Program + #[inline(always)] + pub fn log_wrapper( + &mut self, + log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.log_wrapper = log_wrapper; + self + } + #[inline(always)] + pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self { + self.instruction.key = Some(key); + self + } + #[inline(always)] + pub fn data(&mut self, data: Vec) -> &mut Self { + self.instruction.data = Some(data); + 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 = WriteCollectionExternalPluginDataV1InstructionArgs { + key: self.instruction.key.clone().expect("key is not set"), + data: self.instruction.data.clone().expect("data is not set"), + }; + let instruction = WriteCollectionExternalPluginDataV1Cpi { + __program: self.instruction.__program, + + collection: self.instruction.collection.expect("collection is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority, + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + log_wrapper: self.instruction.log_wrapper, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +struct WriteCollectionExternalPluginDataV1CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + key: Option, + data: 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/write_external_plugin_data_v1.rs b/clients/rust/src/generated/instructions/write_external_plugin_data_v1.rs new file mode 100644 index 00000000..541d9b25 --- /dev/null +++ b/clients/rust/src/generated/instructions/write_external_plugin_data_v1.rs @@ -0,0 +1,589 @@ +//! 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 crate::generated::types::ExternalPluginKey; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct WriteExternalPluginDataV1 { + /// The address of the asset + pub asset: solana_program::pubkey::Pubkey, + /// The collection to which the asset belongs + pub collection: Option, + /// The account paying for the storage fees + pub payer: solana_program::pubkey::Pubkey, + /// The Data Authority of the External Plugin + pub authority: Option, + /// The system program + pub system_program: solana_program::pubkey::Pubkey, + /// The SPL Noop Program + pub log_wrapper: Option, +} + +impl WriteExternalPluginDataV1 { + pub fn instruction( + &self, + args: WriteExternalPluginDataV1InstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: WriteExternalPluginDataV1InstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.asset, false, + )); + if let Some(collection) = self.collection { + accounts.push(solana_program::instruction::AccountMeta::new( + collection, false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + if let Some(authority) = self.authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + authority, true, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + if let Some(log_wrapper) = self.log_wrapper { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + log_wrapper, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.extend_from_slice(remaining_accounts); + let mut data = WriteExternalPluginDataV1InstructionData::new() + .try_to_vec() + .unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::MPL_CORE_ID, + accounts, + data, + } + } +} + +#[derive(BorshDeserialize, BorshSerialize)] +struct WriteExternalPluginDataV1InstructionData { + discriminator: u8, +} + +impl WriteExternalPluginDataV1InstructionData { + fn new() -> Self { + Self { discriminator: 28 } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WriteExternalPluginDataV1InstructionArgs { + pub key: ExternalPluginKey, + pub data: Vec, +} + +/// Instruction builder for `WriteExternalPluginDataV1`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` asset +/// 1. `[writable, optional]` collection +/// 2. `[writable, signer]` payer +/// 3. `[signer, optional]` authority +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +/// 5. `[optional]` log_wrapper +#[derive(Default)] +pub struct WriteExternalPluginDataV1Builder { + asset: Option, + collection: Option, + payer: Option, + authority: Option, + system_program: Option, + log_wrapper: Option, + key: Option, + data: Option>, + __remaining_accounts: Vec, +} + +impl WriteExternalPluginDataV1Builder { + pub fn new() -> Self { + Self::default() + } + /// The address of the asset + #[inline(always)] + pub fn asset(&mut self, asset: solana_program::pubkey::Pubkey) -> &mut Self { + self.asset = Some(asset); + self + } + /// `[optional account]` + /// The collection to which the asset belongs + #[inline(always)] + pub fn collection(&mut self, collection: Option) -> &mut Self { + self.collection = collection; + self + } + /// The account paying for the storage fees + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account]` + /// The Data Authority of the External Plugin + #[inline(always)] + pub fn authority(&mut self, authority: Option) -> &mut Self { + self.authority = authority; + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + /// The system program + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// `[optional account]` + /// The SPL Noop Program + #[inline(always)] + pub fn log_wrapper( + &mut self, + log_wrapper: Option, + ) -> &mut Self { + self.log_wrapper = log_wrapper; + self + } + #[inline(always)] + pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self { + self.key = Some(key); + self + } + #[inline(always)] + pub fn data(&mut self, data: Vec) -> &mut Self { + self.data = Some(data); + 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 = WriteExternalPluginDataV1 { + asset: self.asset.expect("asset is not set"), + collection: self.collection, + payer: self.payer.expect("payer is not set"), + authority: self.authority, + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + log_wrapper: self.log_wrapper, + }; + let args = WriteExternalPluginDataV1InstructionArgs { + key: self.key.clone().expect("key is not set"), + data: self.data.clone().expect("data is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `write_external_plugin_data_v1` CPI accounts. +pub struct WriteExternalPluginDataV1CpiAccounts<'a, 'b> { + /// The address of the asset + pub asset: &'b solana_program::account_info::AccountInfo<'a>, + /// The collection to which the asset belongs + pub collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The account paying for the storage fees + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + /// The Data Authority of the External Plugin + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The system program + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The SPL Noop Program + pub log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, +} + +/// `write_external_plugin_data_v1` CPI instruction. +pub struct WriteExternalPluginDataV1Cpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + /// The address of the asset + pub asset: &'b solana_program::account_info::AccountInfo<'a>, + /// The collection to which the asset belongs + pub collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The account paying for the storage fees + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + /// The Data Authority of the External Plugin + pub authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The system program + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The SPL Noop Program + pub log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// The arguments for the instruction. + pub __args: WriteExternalPluginDataV1InstructionArgs, +} + +impl<'a, 'b> WriteExternalPluginDataV1Cpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: WriteExternalPluginDataV1CpiAccounts<'a, 'b>, + args: WriteExternalPluginDataV1InstructionArgs, + ) -> Self { + Self { + __program: program, + asset: accounts.asset, + collection: accounts.collection, + payer: accounts.payer, + authority: accounts.authority, + system_program: accounts.system_program, + log_wrapper: accounts.log_wrapper, + __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(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.asset.key, + false, + )); + if let Some(collection) = self.collection { + accounts.push(solana_program::instruction::AccountMeta::new( + *collection.key, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + if let Some(authority) = self.authority { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *authority.key, + true, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + false, + )); + } + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + if let Some(log_wrapper) = self.log_wrapper { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *log_wrapper.key, + false, + )); + } else { + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + crate::MPL_CORE_ID, + 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 = WriteExternalPluginDataV1InstructionData::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::MPL_CORE_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + 1 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.asset.clone()); + if let Some(collection) = self.collection { + account_infos.push(collection.clone()); + } + account_infos.push(self.payer.clone()); + if let Some(authority) = self.authority { + account_infos.push(authority.clone()); + } + account_infos.push(self.system_program.clone()); + if let Some(log_wrapper) = self.log_wrapper { + account_infos.push(log_wrapper.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) + } + } +} + +/// Instruction builder for `WriteExternalPluginDataV1` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` asset +/// 1. `[writable, optional]` collection +/// 2. `[writable, signer]` payer +/// 3. `[signer, optional]` authority +/// 4. `[]` system_program +/// 5. `[optional]` log_wrapper +pub struct WriteExternalPluginDataV1CpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> WriteExternalPluginDataV1CpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(WriteExternalPluginDataV1CpiBuilderInstruction { + __program: program, + asset: None, + collection: None, + payer: None, + authority: None, + system_program: None, + log_wrapper: None, + key: None, + data: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + /// The address of the asset + #[inline(always)] + pub fn asset(&mut self, asset: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.asset = Some(asset); + self + } + /// `[optional account]` + /// The collection to which the asset belongs + #[inline(always)] + pub fn collection( + &mut self, + collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.collection = collection; + self + } + /// The account paying for the storage fees + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// `[optional account]` + /// The Data Authority of the External Plugin + #[inline(always)] + pub fn authority( + &mut self, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.authority = authority; + self + } + /// The system program + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// `[optional account]` + /// The SPL Noop Program + #[inline(always)] + pub fn log_wrapper( + &mut self, + log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + ) -> &mut Self { + self.instruction.log_wrapper = log_wrapper; + self + } + #[inline(always)] + pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self { + self.instruction.key = Some(key); + self + } + #[inline(always)] + pub fn data(&mut self, data: Vec) -> &mut Self { + self.instruction.data = Some(data); + 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 = WriteExternalPluginDataV1InstructionArgs { + key: self.instruction.key.clone().expect("key is not set"), + data: self.instruction.data.clone().expect("data is not set"), + }; + let instruction = WriteExternalPluginDataV1Cpi { + __program: self.instruction.__program, + + asset: self.instruction.asset.expect("asset is not set"), + + collection: self.instruction.collection, + + payer: self.instruction.payer.expect("payer is not set"), + + authority: self.instruction.authority, + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + + log_wrapper: self.instruction.log_wrapper, + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +struct WriteExternalPluginDataV1CpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + asset: Option<&'b solana_program::account_info::AccountInfo<'a>>, + collection: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>, + key: Option, + data: 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/external_plugin_schema.rs b/clients/rust/src/generated/types/external_plugin_schema.rs index 3d54f031..c75e7616 100644 --- a/clients/rust/src/generated/types/external_plugin_schema.rs +++ b/clients/rust/src/generated/types/external_plugin_schema.rs @@ -7,8 +7,11 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use num_derive::FromPrimitive; -#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, FromPrimitive, +)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExternalPluginSchema { Binary, diff --git a/clients/rust/src/generated/types/external_plugin_type.rs b/clients/rust/src/generated/types/external_plugin_type.rs index cfdc4fda..8f3795c6 100644 --- a/clients/rust/src/generated/types/external_plugin_type.rs +++ b/clients/rust/src/generated/types/external_plugin_type.rs @@ -7,8 +7,11 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use num_derive::FromPrimitive; -#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, FromPrimitive, +)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExternalPluginType { LifecycleHook, diff --git a/clients/rust/src/generated/types/hookable_lifecycle_event.rs b/clients/rust/src/generated/types/hookable_lifecycle_event.rs index b0a4a6b3..2fcfe611 100644 --- a/clients/rust/src/generated/types/hookable_lifecycle_event.rs +++ b/clients/rust/src/generated/types/hookable_lifecycle_event.rs @@ -7,8 +7,11 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use num_derive::FromPrimitive; -#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, FromPrimitive, +)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum HookableLifecycleEvent { Create, diff --git a/clients/rust/src/generated/types/lifecycle_hook.rs b/clients/rust/src/generated/types/lifecycle_hook.rs index 64b4c1a8..44f9c95f 100644 --- a/clients/rust/src/generated/types/lifecycle_hook.rs +++ b/clients/rust/src/generated/types/lifecycle_hook.rs @@ -7,6 +7,7 @@ use crate::generated::types::ExternalPluginSchema; use crate::generated::types::ExtraAccount; +use crate::generated::types::PluginAuthority; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_program::pubkey::Pubkey; @@ -20,6 +21,7 @@ pub struct LifecycleHook { )] pub hooked_program: Pubkey, pub extra_accounts: Option>, + pub data_authority: Option, pub schema: ExternalPluginSchema, pub data_offset: u64, pub data_len: u64, diff --git a/clients/rust/src/generated/types/lifecycle_hook_init_info.rs b/clients/rust/src/generated/types/lifecycle_hook_init_info.rs index 1c333f80..4a032a1f 100644 --- a/clients/rust/src/generated/types/lifecycle_hook_init_info.rs +++ b/clients/rust/src/generated/types/lifecycle_hook_init_info.rs @@ -25,5 +25,6 @@ pub struct LifecycleHookInitInfo { pub init_plugin_authority: Option, pub lifecycle_checks: Option>, pub extra_accounts: Option>, + pub data_authority: Option, pub schema: Option, } diff --git a/clients/rust/src/generated/types/validation_result.rs b/clients/rust/src/generated/types/validation_result.rs index 4ecdb3ab..2a4a59d5 100644 --- a/clients/rust/src/generated/types/validation_result.rs +++ b/clients/rust/src/generated/types/validation_result.rs @@ -7,8 +7,11 @@ use borsh::BorshDeserialize; use borsh::BorshSerialize; +use num_derive::FromPrimitive; -#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash)] +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, FromPrimitive, +)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ValidationResult { Approved, diff --git a/idls/mpl_core.json b/idls/mpl_core.json index f997a93d..b5d4a870 100644 --- a/idls/mpl_core.json +++ b/idls/mpl_core.json @@ -1784,6 +1784,133 @@ "type": "u8", "value": 27 } + }, + { + "name": "WriteExternalPluginDataV1", + "accounts": [ + { + "name": "asset", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the asset" + ] + }, + { + "name": "collection", + "isMut": true, + "isSigner": false, + "isOptional": true, + "docs": [ + "The collection to which the asset belongs" + ] + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "docs": [ + "The account paying for the storage fees" + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "isOptional": true, + "docs": [ + "The Data Authority of the External Plugin" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "The system program" + ] + }, + { + "name": "logWrapper", + "isMut": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "The SPL Noop Program" + ] + } + ], + "args": [ + { + "name": "writeExternalPluginDataV1Args", + "type": { + "defined": "WriteExternalPluginDataV1Args" + } + } + ], + "discriminant": { + "type": "u8", + "value": 28 + } + }, + { + "name": "WriteCollectionExternalPluginDataV1", + "accounts": [ + { + "name": "collection", + "isMut": true, + "isSigner": false, + "docs": [ + "The address of the asset" + ] + }, + { + "name": "payer", + "isMut": true, + "isSigner": true, + "docs": [ + "The account paying for the storage fees" + ] + }, + { + "name": "authority", + "isMut": false, + "isSigner": true, + "isOptional": true, + "docs": [ + "The Data Authority of the External Plugin" + ] + }, + { + "name": "systemProgram", + "isMut": false, + "isSigner": false, + "docs": [ + "The system program" + ] + }, + { + "name": "logWrapper", + "isMut": false, + "isSigner": false, + "isOptional": true, + "docs": [ + "The SPL Noop Program" + ] + } + ], + "args": [ + { + "name": "writeCollectionExternalPluginDataV1Args", + "type": { + "defined": "WriteCollectionExternalPluginDataV1Args" + } + } + ], + "discriminant": { + "type": "u8", + "value": 29 + } } ], "accounts": [ @@ -2122,6 +2249,14 @@ } } }, + { + "name": "dataAuthority", + "type": { + "option": { + "defined": "Authority" + } + } + }, { "name": "schema", "type": { @@ -2183,6 +2318,14 @@ } } }, + { + "name": "dataAuthority", + "type": { + "option": { + "defined": "Authority" + } + } + }, { "name": "schema", "type": { @@ -3006,6 +3149,42 @@ ] } }, + { + "name": "WriteExternalPluginDataV1Args", + "type": { + "kind": "struct", + "fields": [ + { + "name": "key", + "type": { + "defined": "ExternalPluginKey" + } + }, + { + "name": "data", + "type": "bytes" + } + ] + } + }, + { + "name": "WriteCollectionExternalPluginDataV1Args", + "type": { + "kind": "struct", + "fields": [ + { + "name": "key", + "type": { + "defined": "ExternalPluginKey" + } + }, + { + "name": "data", + "type": "bytes" + } + ] + } + }, { "name": "CompressionProof", "type": { diff --git a/programs/mpl-core/src/instruction.rs b/programs/mpl-core/src/instruction.rs index ac669c39..4ab37ac1 100644 --- a/programs/mpl-core/src/instruction.rs +++ b/programs/mpl-core/src/instruction.rs @@ -11,6 +11,7 @@ use crate::processor::{ RemovePluginV1Args, RevokeCollectionPluginAuthorityV1Args, RevokePluginAuthorityV1Args, TransferV1Args, UpdateCollectionExternalPluginV1Args, UpdateCollectionPluginV1Args, UpdateCollectionV1Args, UpdateExternalPluginV1Args, UpdatePluginV1Args, UpdateV1Args, + WriteCollectionExternalPluginDataV1Args, WriteExternalPluginDataV1Args, }; /// Instructions supported by the mpl-core program. @@ -261,4 +262,21 @@ pub(crate) enum MplAssetInstruction { #[account(3, name="system_program", desc = "The system program")] #[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")] UpdateCollectionExternalPluginV1(UpdateCollectionExternalPluginV1Args), + + /// Add an external plugin to an mpl-core. + #[account(0, writable, name="asset", desc = "The address of the asset")] + #[account(1, optional, writable, name="collection", desc = "The collection to which the asset belongs")] + #[account(2, writable, signer, name="payer", desc = "The account paying for the storage fees")] + #[account(3, optional, signer, name="authority", desc = "The Data Authority of the External Plugin")] + #[account(4, name="system_program", desc = "The system program")] + #[account(5, optional, name="log_wrapper", desc = "The SPL Noop Program")] + WriteExternalPluginDataV1(WriteExternalPluginDataV1Args), + + /// Add an external plugin to an mpl-core. + #[account(0, writable, name="collection", desc = "The address of the asset")] + #[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")] + #[account(2, optional, signer, name="authority", desc = "The Data Authority of the External Plugin")] + #[account(3, name="system_program", desc = "The system program")] + #[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")] + WriteCollectionExternalPluginDataV1(WriteCollectionExternalPluginDataV1Args), } diff --git a/programs/mpl-core/src/plugins/data_store.rs b/programs/mpl-core/src/plugins/data_store.rs index 214a2c81..01b4edf1 100644 --- a/programs/mpl-core/src/plugins/data_store.rs +++ b/programs/mpl-core/src/plugins/data_store.rs @@ -23,8 +23,8 @@ pub struct DataStore { /// Data store initialization info. #[derive(Clone, Debug, BorshSerialize, BorshDeserialize, Eq, PartialEq)] pub struct DataStoreInitInfo { - /// Data authority who can update the data store. Cannot be changed after plugin is - /// added. + /// Data authority who can update the data store. This field cannot be + /// changed after the plugin is added. pub data_authority: Authority, /// Initial plugin authority who can update plugin properties. pub init_plugin_authority: Option, diff --git a/programs/mpl-core/src/plugins/lifecycle_hook.rs b/programs/mpl-core/src/plugins/lifecycle_hook.rs index c3a079b3..2adddba6 100644 --- a/programs/mpl-core/src/plugins/lifecycle_hook.rs +++ b/programs/mpl-core/src/plugins/lifecycle_hook.rs @@ -17,6 +17,10 @@ pub struct LifecycleHook { pub hooked_program: Pubkey, /// The extra accounts to use for the lifecycle hook. pub extra_accounts: Option>, + /// The authority of who can update the Lifecycle Hook data. This can be for the purposes + /// of initialization of data, or schema migration. This field cannot be changed after + /// the plugin is added. + pub data_authority: Option, /// Schema for the data used by the plugin. pub schema: ExternalPluginSchema, /// The offset to the plugin data in the account. @@ -36,6 +40,10 @@ pub struct LifecycleHookInitInfo { pub lifecycle_checks: Option>, /// The extra accounts to use for the lifecycle hook. pub extra_accounts: Option>, + /// The authority of who can update the Lifecycle Hook data. This can be for the purposes + /// of initialization of data, or schema migration. This field cannot be changed after + /// the plugin is added. + pub data_authority: Option, /// Schema for the data used by the plugin. pub schema: Option, } diff --git a/programs/mpl-core/src/processor/mod.rs b/programs/mpl-core/src/processor/mod.rs index 13546a6e..bae3dae3 100644 --- a/programs/mpl-core/src/processor/mod.rs +++ b/programs/mpl-core/src/processor/mod.rs @@ -14,6 +14,7 @@ mod transfer; mod update; mod update_external_plugin; mod update_plugin; +mod write_external_plugin_data; pub(crate) use add_external_plugin::*; pub(crate) use add_plugin::*; @@ -31,6 +32,7 @@ pub(crate) use transfer::*; pub(crate) use update::*; pub(crate) use update_external_plugin::*; pub(crate) use update_plugin::*; +pub(crate) use write_external_plugin_data::*; use borsh::BorshDeserialize; use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey}; @@ -154,5 +156,13 @@ pub fn process_instruction<'a>( msg!("Instruction: UpdateCollectionExternalPlugin"); update_collection_external_plugin(accounts, args) } + MplAssetInstruction::WriteExternalPluginDataV1(args) => { + msg!("Instruction: WriteExternalPluginDataV1"); + write_external_plugin_data(accounts, args) + } + MplAssetInstruction::WriteCollectionExternalPluginDataV1(args) => { + msg!("Instruction: WriteCollectionExternalPluginDataV1"); + write_collection_external_plugin_data(accounts, args) + } } } diff --git a/programs/mpl-core/src/processor/write_external_plugin_data.rs b/programs/mpl-core/src/processor/write_external_plugin_data.rs new file mode 100644 index 00000000..081c30ca --- /dev/null +++ b/programs/mpl-core/src/processor/write_external_plugin_data.rs @@ -0,0 +1,36 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult}; + +use crate::{error::MplCoreError, plugins::ExternalPluginKey}; + +#[repr(C)] +#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] +pub(crate) struct WriteExternalPluginDataV1Args { + /// External plugin key. + pub key: ExternalPluginKey, + /// The data to write. + pub data: Vec, +} + +pub(crate) fn write_external_plugin_data<'a>( + _accounts: &'a [AccountInfo<'a>], + _args: WriteExternalPluginDataV1Args, +) -> ProgramResult { + Err(MplCoreError::NotAvailable.into()) +} + +#[repr(C)] +#[derive(BorshSerialize, BorshDeserialize, PartialEq, Eq, Debug, Clone)] +pub(crate) struct WriteCollectionExternalPluginDataV1Args { + /// External plugin key. + pub key: ExternalPluginKey, + /// The data to write. + pub data: Vec, +} + +pub(crate) fn write_collection_external_plugin_data<'a>( + _accounts: &'a [AccountInfo<'a>], + _args: WriteCollectionExternalPluginDataV1Args, +) -> ProgramResult { + Err(MplCoreError::NotAvailable.into()) +}