From 6464c2a2fcf49a658359ec7b0066fc42ee870c01 Mon Sep 17 00:00:00 2001 From: Michael Danenberg <56533526+danenbm@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:44:41 -0700 Subject: [PATCH] Oracle account type (#82) * Regenerate IDL and clients * Add Oracle validation type * Regenerate IDL and clients * Update JS SDK for ValidationResultsOffset * fix minor type issues --------- Co-authored-by: Nhan Phan --- .../types/baseExternalPluginInitInfo.ts | 4 +- .../generated/types/baseExternalPluginKey.ts | 4 +- .../types/baseExternalPluginUpdateInfo.ts | 4 +- clients/js/src/generated/types/baseOracle.ts | 6 ++ .../src/generated/types/baseOracleInitInfo.ts | 6 ++ .../generated/types/baseOracleUpdateInfo.ts | 6 ++ .../generated/types/basePluginAuthority.ts | 2 +- .../generated/types/baseUpdateAuthority.ts | 2 +- .../types/baseValidationResultsOffset.ts | 80 ++++++++++++++++ .../types/externalValidationResult.ts | 26 +++++ clients/js/src/generated/types/index.ts | 3 + .../src/generated/types/oracleValidation.ts | 76 +++++++++++++++ clients/js/src/instructions/create.ts | 1 + clients/js/src/plugins/oracle.ts | 24 ++++- .../js/src/plugins/validationResultsOffset.ts | 36 +++++++ .../types/external_validation_result.rs | 20 ++++ clients/rust/src/generated/types/mod.rs | 6 ++ clients/rust/src/generated/types/oracle.rs | 2 + .../src/generated/types/oracle_init_info.rs | 2 + .../src/generated/types/oracle_update_info.rs | 2 + .../src/generated/types/oracle_validation.rs | 21 ++++ .../types/validation_results_offset.rs | 17 ++++ clients/rust/tests/add_external_plugins.rs | 1 + .../tests/create_with_external_plugins.rs | 1 + configs/kinobi.cjs | 3 + idls/mpl_core.json | 96 +++++++++++++++++++ programs/mpl-core/src/plugins/lifecycle.rs | 14 ++- programs/mpl-core/src/plugins/oracle.rs | 44 ++++++++- 28 files changed, 493 insertions(+), 16 deletions(-) create mode 100644 clients/js/src/generated/types/baseValidationResultsOffset.ts create mode 100644 clients/js/src/generated/types/externalValidationResult.ts create mode 100644 clients/js/src/generated/types/oracleValidation.ts create mode 100644 clients/js/src/plugins/validationResultsOffset.ts create mode 100644 clients/rust/src/generated/types/external_validation_result.rs create mode 100644 clients/rust/src/generated/types/oracle_validation.rs create mode 100644 clients/rust/src/generated/types/validation_results_offset.rs diff --git a/clients/js/src/generated/types/baseExternalPluginInitInfo.ts b/clients/js/src/generated/types/baseExternalPluginInitInfo.ts index 6d93b748..c739845e 100644 --- a/clients/js/src/generated/types/baseExternalPluginInitInfo.ts +++ b/clients/js/src/generated/types/baseExternalPluginInitInfo.ts @@ -88,14 +88,14 @@ export function baseExternalPluginInitInfo( >['fields'] ): GetDataEnumKind; export function baseExternalPluginInitInfo< - K extends BaseExternalPluginInitInfoArgs['__kind'] + K extends BaseExternalPluginInitInfoArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } : { __kind: kind, ...(data ?? {}) }; } export function isBaseExternalPluginInitInfo< - K extends BaseExternalPluginInitInfo['__kind'] + K extends BaseExternalPluginInitInfo['__kind'], >( kind: K, value: BaseExternalPluginInitInfo diff --git a/clients/js/src/generated/types/baseExternalPluginKey.ts b/clients/js/src/generated/types/baseExternalPluginKey.ts index a9f34c10..294d0052 100644 --- a/clients/js/src/generated/types/baseExternalPluginKey.ts +++ b/clients/js/src/generated/types/baseExternalPluginKey.ts @@ -78,14 +78,14 @@ export function baseExternalPluginKey( data: GetDataEnumKindContent['fields'] ): GetDataEnumKind; export function baseExternalPluginKey< - K extends BaseExternalPluginKeyArgs['__kind'] + K extends BaseExternalPluginKeyArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } : { __kind: kind, ...(data ?? {}) }; } export function isBaseExternalPluginKey< - K extends BaseExternalPluginKey['__kind'] + K extends BaseExternalPluginKey['__kind'], >( kind: K, value: BaseExternalPluginKey diff --git a/clients/js/src/generated/types/baseExternalPluginUpdateInfo.ts b/clients/js/src/generated/types/baseExternalPluginUpdateInfo.ts index c97eefbb..6cd1e7d7 100644 --- a/clients/js/src/generated/types/baseExternalPluginUpdateInfo.ts +++ b/clients/js/src/generated/types/baseExternalPluginUpdateInfo.ts @@ -91,7 +91,7 @@ export function baseExternalPluginUpdateInfo( >['fields'] ): GetDataEnumKind; export function baseExternalPluginUpdateInfo< - K extends BaseExternalPluginUpdateInfoArgs['__kind'] + K extends BaseExternalPluginUpdateInfoArgs['__kind'], >( kind: K, data?: any @@ -101,7 +101,7 @@ export function baseExternalPluginUpdateInfo< : { __kind: kind, ...(data ?? {}) }; } export function isBaseExternalPluginUpdateInfo< - K extends BaseExternalPluginUpdateInfo['__kind'] + K extends BaseExternalPluginUpdateInfo['__kind'], >( kind: K, value: BaseExternalPluginUpdateInfo diff --git a/clients/js/src/generated/types/baseOracle.ts b/clients/js/src/generated/types/baseOracle.ts index f426a8b2..933c4df4 100644 --- a/clients/js/src/generated/types/baseOracle.ts +++ b/clients/js/src/generated/types/baseOracle.ts @@ -16,17 +16,22 @@ import { import { BaseExtraAccount, BaseExtraAccountArgs, + BaseValidationResultsOffset, + BaseValidationResultsOffsetArgs, getBaseExtraAccountSerializer, + getBaseValidationResultsOffsetSerializer, } from '.'; export type BaseOracle = { baseAddress: PublicKey; pda: Option; + resultsOffset: BaseValidationResultsOffset; }; export type BaseOracleArgs = { baseAddress: PublicKey; pda: OptionOrNullable; + resultsOffset: BaseValidationResultsOffsetArgs; }; export function getBaseOracleSerializer(): Serializer< @@ -37,6 +42,7 @@ export function getBaseOracleSerializer(): Serializer< [ ['baseAddress', publicKeySerializer()], ['pda', option(getBaseExtraAccountSerializer())], + ['resultsOffset', getBaseValidationResultsOffsetSerializer()], ], { description: 'BaseOracle' } ) as Serializer; diff --git a/clients/js/src/generated/types/baseOracleInitInfo.ts b/clients/js/src/generated/types/baseOracleInitInfo.ts index cd852958..bdb8e30d 100644 --- a/clients/js/src/generated/types/baseOracleInitInfo.ts +++ b/clients/js/src/generated/types/baseOracleInitInfo.ts @@ -20,12 +20,15 @@ import { BaseExtraAccountArgs, BasePluginAuthority, BasePluginAuthorityArgs, + BaseValidationResultsOffset, + BaseValidationResultsOffsetArgs, ExternalCheckResult, ExternalCheckResultArgs, HookableLifecycleEvent, HookableLifecycleEventArgs, getBaseExtraAccountSerializer, getBasePluginAuthoritySerializer, + getBaseValidationResultsOffsetSerializer, getExternalCheckResultSerializer, getHookableLifecycleEventSerializer, } from '.'; @@ -35,6 +38,7 @@ export type BaseOracleInitInfo = { initPluginAuthority: Option; lifecycleChecks: Option>; pda: Option; + resultsOffset: Option; }; export type BaseOracleInitInfoArgs = { @@ -44,6 +48,7 @@ export type BaseOracleInitInfoArgs = { Array<[HookableLifecycleEventArgs, ExternalCheckResultArgs]> >; pda: OptionOrNullable; + resultsOffset: OptionOrNullable; }; export function getBaseOracleInitInfoSerializer(): Serializer< @@ -66,6 +71,7 @@ export function getBaseOracleInitInfoSerializer(): Serializer< ), ], ['pda', option(getBaseExtraAccountSerializer())], + ['resultsOffset', option(getBaseValidationResultsOffsetSerializer())], ], { description: 'BaseOracleInitInfo' } ) as Serializer; diff --git a/clients/js/src/generated/types/baseOracleUpdateInfo.ts b/clients/js/src/generated/types/baseOracleUpdateInfo.ts index 1a1276bd..ae97c039 100644 --- a/clients/js/src/generated/types/baseOracleUpdateInfo.ts +++ b/clients/js/src/generated/types/baseOracleUpdateInfo.ts @@ -17,11 +17,14 @@ import { import { BaseExtraAccount, BaseExtraAccountArgs, + BaseValidationResultsOffset, + BaseValidationResultsOffsetArgs, ExternalCheckResult, ExternalCheckResultArgs, HookableLifecycleEvent, HookableLifecycleEventArgs, getBaseExtraAccountSerializer, + getBaseValidationResultsOffsetSerializer, getExternalCheckResultSerializer, getHookableLifecycleEventSerializer, } from '.'; @@ -29,6 +32,7 @@ import { export type BaseOracleUpdateInfo = { lifecycleChecks: Option>; pda: Option; + resultsOffset: Option; }; export type BaseOracleUpdateInfoArgs = { @@ -36,6 +40,7 @@ export type BaseOracleUpdateInfoArgs = { Array<[HookableLifecycleEventArgs, ExternalCheckResultArgs]> >; pda: OptionOrNullable; + resultsOffset: OptionOrNullable; }; export function getBaseOracleUpdateInfoSerializer(): Serializer< @@ -56,6 +61,7 @@ export function getBaseOracleUpdateInfoSerializer(): Serializer< ), ], ['pda', option(getBaseExtraAccountSerializer())], + ['resultsOffset', option(getBaseValidationResultsOffsetSerializer())], ], { description: 'BaseOracleUpdateInfo' } ) as Serializer; diff --git a/clients/js/src/generated/types/basePluginAuthority.ts b/clients/js/src/generated/types/basePluginAuthority.ts index c9916538..8a6a7002 100644 --- a/clients/js/src/generated/types/basePluginAuthority.ts +++ b/clients/js/src/generated/types/basePluginAuthority.ts @@ -60,7 +60,7 @@ export function basePluginAuthority( data: GetDataEnumKindContent ): GetDataEnumKind; export function basePluginAuthority< - K extends BasePluginAuthorityArgs['__kind'] + K extends BasePluginAuthorityArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } diff --git a/clients/js/src/generated/types/baseUpdateAuthority.ts b/clients/js/src/generated/types/baseUpdateAuthority.ts index f32f22a3..de8818f2 100644 --- a/clients/js/src/generated/types/baseUpdateAuthority.ts +++ b/clients/js/src/generated/types/baseUpdateAuthority.ts @@ -62,7 +62,7 @@ export function baseUpdateAuthority( data: GetDataEnumKindContent['fields'] ): GetDataEnumKind; export function baseUpdateAuthority< - K extends BaseUpdateAuthorityArgs['__kind'] + K extends BaseUpdateAuthorityArgs['__kind'], >(kind: K, data?: any): Extract { return Array.isArray(data) ? { __kind: kind, fields: data } diff --git a/clients/js/src/generated/types/baseValidationResultsOffset.ts b/clients/js/src/generated/types/baseValidationResultsOffset.ts new file mode 100644 index 00000000..0d960574 --- /dev/null +++ b/clients/js/src/generated/types/baseValidationResultsOffset.ts @@ -0,0 +1,80 @@ +/** + * 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 { + GetDataEnumKind, + GetDataEnumKindContent, + Serializer, + dataEnum, + struct, + tuple, + u64, + unit, +} from '@metaplex-foundation/umi/serializers'; + +export type BaseValidationResultsOffset = + | { __kind: 'NoOffset' } + | { __kind: 'Anchor' } + | { __kind: 'Custom'; fields: [bigint] }; + +export type BaseValidationResultsOffsetArgs = + | { __kind: 'NoOffset' } + | { __kind: 'Anchor' } + | { __kind: 'Custom'; fields: [number | bigint] }; + +export function getBaseValidationResultsOffsetSerializer(): Serializer< + BaseValidationResultsOffsetArgs, + BaseValidationResultsOffset +> { + return dataEnum( + [ + ['NoOffset', unit()], + ['Anchor', unit()], + [ + 'Custom', + struct>([ + ['fields', tuple([u64()])], + ]), + ], + ], + { description: 'BaseValidationResultsOffset' } + ) as Serializer; +} + +// Data Enum Helpers. +export function baseValidationResultsOffset( + kind: 'NoOffset' +): GetDataEnumKind; +export function baseValidationResultsOffset( + kind: 'Anchor' +): GetDataEnumKind; +export function baseValidationResultsOffset( + kind: 'Custom', + data: GetDataEnumKindContent< + BaseValidationResultsOffsetArgs, + 'Custom' + >['fields'] +): GetDataEnumKind; +export function baseValidationResultsOffset< + K extends BaseValidationResultsOffsetArgs['__kind'], +>( + kind: K, + data?: any +): Extract { + return Array.isArray(data) + ? { __kind: kind, fields: data } + : { __kind: kind, ...(data ?? {}) }; +} +export function isBaseValidationResultsOffset< + K extends BaseValidationResultsOffset['__kind'], +>( + kind: K, + value: BaseValidationResultsOffset +): value is BaseValidationResultsOffset & { __kind: K } { + return value.__kind === kind; +} diff --git a/clients/js/src/generated/types/externalValidationResult.ts b/clients/js/src/generated/types/externalValidationResult.ts new file mode 100644 index 00000000..f60f5189 --- /dev/null +++ b/clients/js/src/generated/types/externalValidationResult.ts @@ -0,0 +1,26 @@ +/** + * 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 { Serializer, scalarEnum } from '@metaplex-foundation/umi/serializers'; + +export enum ExternalValidationResult { + Approved, + Rejected, + Pass, +} + +export type ExternalValidationResultArgs = ExternalValidationResult; + +export function getExternalValidationResultSerializer(): Serializer< + ExternalValidationResultArgs, + ExternalValidationResult +> { + return scalarEnum(ExternalValidationResult, { + description: 'ExternalValidationResult', + }) as Serializer; +} diff --git a/clients/js/src/generated/types/index.ts b/clients/js/src/generated/types/index.ts index 996a3755..c9917c5e 100644 --- a/clients/js/src/generated/types/index.ts +++ b/clients/js/src/generated/types/index.ts @@ -26,6 +26,7 @@ export * from './baseRoyalties'; export * from './baseRuleSet'; export * from './baseSeed'; export * from './baseUpdateAuthority'; +export * from './baseValidationResultsOffset'; export * from './burnDelegate'; export * from './compressionProof'; export * from './creator'; @@ -36,11 +37,13 @@ export * from './externalPlugin'; export * from './externalPluginSchema'; export * from './externalPluginType'; export * from './externalRegistryRecord'; +export * from './externalValidationResult'; export * from './freezeDelegate'; export * from './hashablePluginSchema'; export * from './hashedAssetSchema'; export * from './hookableLifecycleEvent'; export * from './key'; +export * from './oracleValidation'; export * from './permanentBurnDelegate'; export * from './permanentFreezeDelegate'; export * from './permanentTransferDelegate'; diff --git a/clients/js/src/generated/types/oracleValidation.ts b/clients/js/src/generated/types/oracleValidation.ts new file mode 100644 index 00000000..16984db5 --- /dev/null +++ b/clients/js/src/generated/types/oracleValidation.ts @@ -0,0 +1,76 @@ +/** + * 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 { + GetDataEnumKind, + GetDataEnumKindContent, + Serializer, + dataEnum, + struct, +} from '@metaplex-foundation/umi/serializers'; +import { + ExternalValidationResult, + ExternalValidationResultArgs, + getExternalValidationResultSerializer, +} from '.'; + +export type OracleValidation = { + __kind: 'V1'; + create: ExternalValidationResult; + transfer: ExternalValidationResult; + burn: ExternalValidationResult; + update: ExternalValidationResult; +}; + +export type OracleValidationArgs = { + __kind: 'V1'; + create: ExternalValidationResultArgs; + transfer: ExternalValidationResultArgs; + burn: ExternalValidationResultArgs; + update: ExternalValidationResultArgs; +}; + +export function getOracleValidationSerializer(): Serializer< + OracleValidationArgs, + OracleValidation +> { + return dataEnum( + [ + [ + 'V1', + struct>([ + ['create', getExternalValidationResultSerializer()], + ['transfer', getExternalValidationResultSerializer()], + ['burn', getExternalValidationResultSerializer()], + ['update', getExternalValidationResultSerializer()], + ]), + ], + ], + { description: 'OracleValidation' } + ) as Serializer; +} + +// Data Enum Helpers. +export function oracleValidation( + kind: 'V1', + data: GetDataEnumKindContent +): GetDataEnumKind; +export function oracleValidation( + kind: K, + data?: any +): Extract { + return Array.isArray(data) + ? { __kind: kind, fields: data } + : { __kind: kind, ...(data ?? {}) }; +} +export function isOracleValidation( + kind: K, + value: OracleValidation +): value is OracleValidation & { __kind: K } { + return value.__kind === kind; +} diff --git a/clients/js/src/instructions/create.ts b/clients/js/src/instructions/create.ts index b6f9a24e..a72602dc 100644 --- a/clients/js/src/instructions/create.ts +++ b/clients/js/src/instructions/create.ts @@ -43,6 +43,7 @@ export const create = ( case 'Oracle': assetExternalPlugins.oracles?.push({ ...plugin, + resultsOffset: plugin.resultsOffset || { type: 'NoOffset' }, baseAddress: plugin.baseAddress, authority: plugin.initPluginAuthority || { type: 'UpdateAuthority', diff --git a/clients/js/src/plugins/oracle.ts b/clients/js/src/plugins/oracle.ts index 12720a3d..1c75a816 100644 --- a/clients/js/src/plugins/oracle.ts +++ b/clients/js/src/plugins/oracle.ts @@ -13,9 +13,15 @@ import { PluginAuthority, pluginAuthorityToBase } from './pluginAuthority'; import { ExternalPluginManifest } from './externalPluginManifest'; import { BaseExternalPlugin } from './externalPlugins'; import { ExternalPluginKey } from './externalPluginKey'; +import { + ValidationResultsOffset, + validationResultsOffsetFromBase, + validationResultsOffsetToBase, +} from './validationResultsOffset'; -export type Oracle = Omit & { +export type Oracle = Omit & { pda?: ExtraAccount; + resultsOffset: ValidationResultsOffset; }; export type OraclePlugin = BaseExternalPlugin & @@ -25,21 +31,23 @@ export type OraclePlugin = BaseExternalPlugin & export type OracleInitInfoArgs = Omit< BaseOracleInitInfoArgs, - 'initPluginAuthority' | 'lifecycleChecks' + 'initPluginAuthority' | 'lifecycleChecks' | 'pda' | 'resultsOffset' > & { type: 'Oracle'; initPluginAuthority?: PluginAuthority; lifecycleChecks?: LifecycleChecks; pda?: ExtraAccount; + resultsOffset?: ValidationResultsOffset; }; export type OracleUpdateInfoArgs = Omit< BaseOracleUpdateInfoArgs, - 'lifecycleChecks' | 'pda' + 'lifecycleChecks' | 'pda' | 'resultsOffset' > & { key: ExternalPluginKey; lifecycleChecks?: LifecycleChecks; pda?: ExtraAccount; + resultsOffset?: ValidationResultsOffset; }; export function oracleInitInfoArgsToBase( @@ -54,6 +62,9 @@ export function oracleInitInfoArgsToBase( initPluginAuthority: o.initPluginAuthority ? pluginAuthorityToBase(o.initPluginAuthority) : null, + resultsOffset: o.resultsOffset + ? validationResultsOffsetToBase(o.resultsOffset) + : null, }; } @@ -65,14 +76,17 @@ export function oracleUpdateInfoArgsToBase( lifecycleChecks: o.lifecycleChecks ? lifecycleChecksToBase(o.lifecycleChecks) : null, + resultsOffset: o.resultsOffset + ? validationResultsOffsetToBase(o.resultsOffset) + : null, }; } export function oracleFromBase(s: BaseOracle, account: Uint8Array): Oracle { return { ...s, - pda: - s.pda.__option === 'Some' ? extraAccountFromBase(s.pda.value) : undefined, + pda: s.pda.__option === 'Some' ? extraAccountFromBase(s.pda.value) : undefined, + resultsOffset: validationResultsOffsetFromBase(s.resultsOffset), }; } diff --git a/clients/js/src/plugins/validationResultsOffset.ts b/clients/js/src/plugins/validationResultsOffset.ts new file mode 100644 index 00000000..b955eb14 --- /dev/null +++ b/clients/js/src/plugins/validationResultsOffset.ts @@ -0,0 +1,36 @@ +import { BaseValidationResultsOffset } from '../generated'; + +export type ValidationResultsOffset = + | { type: 'NoOffset' } + | { type: 'Anchor' } + | { type: 'Custom'; offset: bigint }; + +export function validationResultsOffsetToBase( + e: ValidationResultsOffset +): BaseValidationResultsOffset { + if (e.type === 'Custom') { + return { + __kind: 'Custom', + fields: [e.offset], + }; + } + + return { + __kind: e.type, + } +} + +export function validationResultsOffsetFromBase( + e: BaseValidationResultsOffset +): ValidationResultsOffset { + if (e.__kind === 'Custom') { + return { + type: 'Custom', + offset: e.fields[0], + }; + } + + return { + type: e.__kind, + } +} diff --git a/clients/rust/src/generated/types/external_validation_result.rs b/clients/rust/src/generated/types/external_validation_result.rs new file mode 100644 index 00000000..d24f011d --- /dev/null +++ b/clients/rust/src/generated/types/external_validation_result.rs @@ -0,0 +1,20 @@ +//! 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; +use num_derive::FromPrimitive; + +#[derive( + BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, FromPrimitive, +)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ExternalValidationResult { + Approved, + Rejected, + Pass, +} diff --git a/clients/rust/src/generated/types/mod.rs b/clients/rust/src/generated/types/mod.rs index d6c13756..d5503d6c 100644 --- a/clients/rust/src/generated/types/mod.rs +++ b/clients/rust/src/generated/types/mod.rs @@ -23,6 +23,7 @@ pub(crate) mod r#external_plugin_schema; pub(crate) mod r#external_plugin_type; pub(crate) mod r#external_plugin_update_info; pub(crate) mod r#external_registry_record; +pub(crate) mod r#external_validation_result; pub(crate) mod r#extra_account; pub(crate) mod r#freeze_delegate; pub(crate) mod r#hashable_plugin_schema; @@ -35,6 +36,7 @@ pub(crate) mod r#lifecycle_hook_update_info; pub(crate) mod r#oracle; pub(crate) mod r#oracle_init_info; pub(crate) mod r#oracle_update_info; +pub(crate) mod r#oracle_validation; pub(crate) mod r#permanent_burn_delegate; pub(crate) mod r#permanent_freeze_delegate; pub(crate) mod r#permanent_transfer_delegate; @@ -50,6 +52,7 @@ pub(crate) mod r#transfer_delegate; pub(crate) mod r#update_authority; pub(crate) mod r#update_delegate; pub(crate) mod r#validation_result; +pub(crate) mod r#validation_results_offset; pub use self::r#attribute::*; pub use self::r#attributes::*; @@ -69,6 +72,7 @@ pub use self::r#external_plugin_schema::*; pub use self::r#external_plugin_type::*; pub use self::r#external_plugin_update_info::*; pub use self::r#external_registry_record::*; +pub use self::r#external_validation_result::*; pub use self::r#extra_account::*; pub use self::r#freeze_delegate::*; pub use self::r#hashable_plugin_schema::*; @@ -81,6 +85,7 @@ pub use self::r#lifecycle_hook_update_info::*; pub use self::r#oracle::*; pub use self::r#oracle_init_info::*; pub use self::r#oracle_update_info::*; +pub use self::r#oracle_validation::*; pub use self::r#permanent_burn_delegate::*; pub use self::r#permanent_freeze_delegate::*; pub use self::r#permanent_transfer_delegate::*; @@ -96,3 +101,4 @@ pub use self::r#transfer_delegate::*; pub use self::r#update_authority::*; pub use self::r#update_delegate::*; pub use self::r#validation_result::*; +pub use self::r#validation_results_offset::*; diff --git a/clients/rust/src/generated/types/oracle.rs b/clients/rust/src/generated/types/oracle.rs index e14745b0..2a95fa48 100644 --- a/clients/rust/src/generated/types/oracle.rs +++ b/clients/rust/src/generated/types/oracle.rs @@ -6,6 +6,7 @@ //! use crate::generated::types::ExtraAccount; +use crate::generated::types::ValidationResultsOffset; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_program::pubkey::Pubkey; @@ -19,4 +20,5 @@ pub struct Oracle { )] pub base_address: Pubkey, pub pda: Option, + pub results_offset: ValidationResultsOffset, } diff --git a/clients/rust/src/generated/types/oracle_init_info.rs b/clients/rust/src/generated/types/oracle_init_info.rs index 20b3b287..f96c00e1 100644 --- a/clients/rust/src/generated/types/oracle_init_info.rs +++ b/clients/rust/src/generated/types/oracle_init_info.rs @@ -9,6 +9,7 @@ use crate::generated::types::ExternalCheckResult; use crate::generated::types::ExtraAccount; use crate::generated::types::HookableLifecycleEvent; use crate::generated::types::PluginAuthority; +use crate::generated::types::ValidationResultsOffset; use borsh::BorshDeserialize; use borsh::BorshSerialize; use solana_program::pubkey::Pubkey; @@ -24,4 +25,5 @@ pub struct OracleInitInfo { pub init_plugin_authority: Option, pub lifecycle_checks: Option>, pub pda: Option, + pub results_offset: Option, } diff --git a/clients/rust/src/generated/types/oracle_update_info.rs b/clients/rust/src/generated/types/oracle_update_info.rs index 3cb3437a..9813f5a0 100644 --- a/clients/rust/src/generated/types/oracle_update_info.rs +++ b/clients/rust/src/generated/types/oracle_update_info.rs @@ -8,6 +8,7 @@ use crate::generated::types::ExternalCheckResult; use crate::generated::types::ExtraAccount; use crate::generated::types::HookableLifecycleEvent; +use crate::generated::types::ValidationResultsOffset; use borsh::BorshDeserialize; use borsh::BorshSerialize; @@ -16,4 +17,5 @@ use borsh::BorshSerialize; pub struct OracleUpdateInfo { pub lifecycle_checks: Option>, pub pda: Option, + pub results_offset: Option, } diff --git a/clients/rust/src/generated/types/oracle_validation.rs b/clients/rust/src/generated/types/oracle_validation.rs new file mode 100644 index 00000000..c971c96c --- /dev/null +++ b/clients/rust/src/generated/types/oracle_validation.rs @@ -0,0 +1,21 @@ +//! 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::ExternalValidationResult; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum OracleValidation { + V1 { + create: ExternalValidationResult, + transfer: ExternalValidationResult, + burn: ExternalValidationResult, + update: ExternalValidationResult, + }, +} diff --git a/clients/rust/src/generated/types/validation_results_offset.rs b/clients/rust/src/generated/types/validation_results_offset.rs new file mode 100644 index 00000000..15de75cb --- /dev/null +++ b/clients/rust/src/generated/types/validation_results_offset.rs @@ -0,0 +1,17 @@ +//! 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; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ValidationResultsOffset { + NoOffset, + Anchor, + Custom(u64), +} diff --git a/clients/rust/tests/add_external_plugins.rs b/clients/rust/tests/add_external_plugins.rs index e10e8851..3d2eb5a8 100644 --- a/clients/rust/tests/add_external_plugins.rs +++ b/clients/rust/tests/add_external_plugins.rs @@ -141,6 +141,7 @@ async fn test_add_oracle() { ExternalCheckResult { flags: 1 }, )]), pda: None, + results_offset: None, })) .instruction(); diff --git a/clients/rust/tests/create_with_external_plugins.rs b/clients/rust/tests/create_with_external_plugins.rs index f720dc01..e4fa6bed 100644 --- a/clients/rust/tests/create_with_external_plugins.rs +++ b/clients/rust/tests/create_with_external_plugins.rs @@ -101,6 +101,7 @@ async fn test_add_oracle() { ExternalCheckResult { flags: 1 }, )]), pda: None, + results_offset: None, })], }, ) diff --git a/configs/kinobi.cjs b/configs/kinobi.cjs index 06cecd59..99c8bd04 100755 --- a/configs/kinobi.cjs +++ b/configs/kinobi.cjs @@ -231,6 +231,9 @@ kinobi.update( dataStoreUpdateInfo: { name: "baseDataStoreUpdateInfo" }, + validationResultsOffset: { + name: "baseValidationResultsOffset" + }, }) ) diff --git a/idls/mpl_core.json b/idls/mpl_core.json index b5d4a870..fb26b598 100644 --- a/idls/mpl_core.json +++ b/idls/mpl_core.json @@ -2396,6 +2396,12 @@ "defined": "ExtraAccount" } } + }, + { + "name": "resultsOffset", + "type": { + "defined": "ValidationResultsOffset" + } } ] } @@ -2441,6 +2447,14 @@ "defined": "ExtraAccount" } } + }, + { + "name": "resultsOffset", + "type": { + "option": { + "defined": "ValidationResultsOffset" + } + } } ] } @@ -2474,6 +2488,14 @@ "defined": "ExtraAccount" } } + }, + { + "name": "resultsOffset", + "type": { + "option": { + "defined": "ValidationResultsOffset" + } + } } ] } @@ -3739,6 +3761,80 @@ ] } }, + { + "name": "ExternalValidationResult", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Approved" + }, + { + "name": "Rejected" + }, + { + "name": "Pass" + } + ] + } + }, + { + "name": "ValidationResultsOffset", + "type": { + "kind": "enum", + "variants": [ + { + "name": "NoOffset" + }, + { + "name": "Anchor" + }, + { + "name": "Custom", + "fields": [ + "u64" + ] + } + ] + } + }, + { + "name": "OracleValidation", + "type": { + "kind": "enum", + "variants": [ + { + "name": "V1", + "fields": [ + { + "name": "create", + "type": { + "defined": "ExternalValidationResult" + } + }, + { + "name": "transfer", + "type": { + "defined": "ExternalValidationResult" + } + }, + { + "name": "burn", + "type": { + "defined": "ExternalValidationResult" + } + }, + { + "name": "update", + "type": { + "defined": "ExternalValidationResult" + } + } + ] + } + ] + } + }, { "name": "RuleSet", "type": { diff --git a/programs/mpl-core/src/plugins/lifecycle.rs b/programs/mpl-core/src/plugins/lifecycle.rs index 4a7ab1a0..67d8bbdb 100644 --- a/programs/mpl-core/src/plugins/lifecycle.rs +++ b/programs/mpl-core/src/plugins/lifecycle.rs @@ -31,7 +31,7 @@ pub enum CheckResult { #[derive(BorshDeserialize, BorshSerialize, Eq, PartialEq, Copy, Clone, Debug)] pub struct ExternalCheckResult { /// Bitfield for external check results. - flags: u8, + pub flags: u8, } impl ExternalCheckResult { @@ -640,6 +640,18 @@ pub enum ValidationResult { ForceApproved, } +/// External plugins lifecycle validations +/// External plugins utilize this to indicate whether they approve or reject a lifecycle action. +#[derive(Eq, PartialEq, Debug, Clone, BorshDeserialize, BorshSerialize)] +pub enum ExternalValidationResult { + /// The plugin approves the lifecycle action. + Approved, + /// The plugin rejects the lifecycle action. + Rejected, + /// The plugin abstains from approving or rejecting the lifecycle action. + Pass, +} + /// The required context for a plugin validation. #[allow(dead_code)] pub(crate) struct PluginValidationContext<'a, 'b> { diff --git a/programs/mpl-core/src/plugins/oracle.rs b/programs/mpl-core/src/plugins/oracle.rs index 8fed1205..4896ee86 100644 --- a/programs/mpl-core/src/plugins/oracle.rs +++ b/programs/mpl-core/src/plugins/oracle.rs @@ -2,8 +2,8 @@ use borsh::{BorshDeserialize, BorshSerialize}; use solana_program::{program_error::ProgramError, pubkey::Pubkey}; use super::{ - Authority, ExternalCheckResult, ExtraAccount, HookableLifecycleEvent, PluginValidation, - PluginValidationContext, ValidationResult, + Authority, ExternalCheckResult, ExternalValidationResult, ExtraAccount, HookableLifecycleEvent, + PluginValidation, PluginValidationContext, ValidationResult, }; /// Oracle plugin that allows getting a `ValidationResult` for a lifecycle event from an arbitrary @@ -16,6 +16,8 @@ pub struct Oracle { pub base_address: Pubkey, /// Optional PDA (derived from Pubkey attached to `ExternalPluginKey`). pub pda: Option, + /// Validation results offset in the Oracle account. Default is `ValidationResultsOffset::NoOffset`. + pub results_offset: ValidationResultsOffset, } impl From<&OracleInitInfo> for Oracle { @@ -23,6 +25,10 @@ impl From<&OracleInitInfo> for Oracle { Self { base_address: init_info.base_address, pda: init_info.pda.clone(), + results_offset: init_info + .results_offset + .clone() + .unwrap_or(ValidationResultsOffset::NoOffset), } } } @@ -39,6 +45,9 @@ pub struct OracleInitInfo { pub lifecycle_checks: Option>, /// Optional PDA (derived from Pubkey attached to `ExternalPluginKey`). pub pda: Option, + /// Optional offset for validation results struct used in Oracle account. Default + /// is `ValidationResultsOffset::NoOffset`. + pub results_offset: Option, } impl PluginValidation for OracleInitInfo { @@ -57,4 +66,35 @@ pub struct OracleUpdateInfo { pub lifecycle_checks: Option>, /// Optional PDA (derived from Pubkey attached to `ExternalPluginKey`). pub pda: Option, + /// Optional offset for validation results struct used in Oracle account. Default + /// is `ValidationResultsOffset::NoOffset`. + pub results_offset: Option, +} + +/// Offset to where the validation results struct is located in an Oracle account. +#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, Eq, PartialEq)] +pub enum ValidationResultsOffset { + /// The validation struct is located at the beginning of the account. + NoOffset, + /// The Oracle is an Anchor account so the validation struct is located after an 8-byte + /// account discriminator. + Anchor, + /// The validation struct is located at the specified offset within the account. + Custom(usize), +} + +/// Validation results struct for an Oracle account. +#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, Eq, PartialEq)] +pub enum OracleValidation { + /// Version 1 of the format. + V1 { + /// Validation for the the create lifecycle action. + create: ExternalValidationResult, + /// Validation for the transfer lifecycle action. + transfer: ExternalValidationResult, + /// Validation for the burn lifecycle action. + burn: ExternalValidationResult, + /// Validation for the update lifecycle action. + update: ExternalValidationResult, + }, }