diff --git a/Cargo.toml b/Cargo.toml index e0845d2..cd50bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ # file: Cargo.toml -# version: 11 +# version: 12 [workspace] resolver = "3" @@ -18,7 +18,7 @@ members = [ ] [workspace.package] -version = "0.4.7-pre.4" +version = "0.4.7-pre.5" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3" diff --git a/docs/plans/V0_4_7_METAPLEX_TOKEN_METADATA_COMPLETION_PLAN.md b/docs/plans/V0_4_7_METAPLEX_TOKEN_METADATA_COMPLETION_PLAN.md index 4e1abd5..25908b0 100644 --- a/docs/plans/V0_4_7_METAPLEX_TOKEN_METADATA_COMPLETION_PLAN.md +++ b/docs/plans/V0_4_7_METAPLEX_TOKEN_METADATA_COMPLETION_PLAN.md @@ -1,5 +1,5 @@ - + # Plan `0.4.7` — achèvement de Metaplex Token Metadata @@ -377,7 +377,7 @@ La numérotation ci-dessous est un plan fermé initial. Elle peut être regroup - transitions de vérification prouvées ; - mauvais owners, PDA, authority et collection rejetés. -### `0.4.7-pre.005` — programmable NFTs et délégations +### `0.4.7-pre.005` — programmable NFTs et délégations — réalisée **Travaux** diff --git a/kb-lib/CHANGELOG.md b/kb-lib/CHANGELOG.md index 8b591d1..53432ce 100644 --- a/kb-lib/CHANGELOG.md +++ b/kb-lib/CHANGELOG.md @@ -1,8 +1,16 @@ - + # CHANGELOG — kb-lib +## 0.4.7-pre.005 — programmable NFTs et délégations + +- ajout des wrappers officiels `Burn`, `Delegate`, `Revoke`, `Lock`, `Unlock`, `Transfer` et `CloseAccounts` ; +- validation du couplage des comptes Token Authorization Rules et maintien de la simulation obligatoire ; +- exposition des codes d’opération, bindings TS-RS et capacités exactes correspondantes ; +- ajout de tests unitaires dans `intent.rs`, `builder.rs` et `executor.rs` ; +- maintien des versions remplacées en decode-only avec renvoi vers leur wrapper canonique. + ## 0.4.7-pre.004 — collections, créateurs et autorités - ajout des wrappers courants `Verify` et `Unverify` pour les créateurs et collections ; diff --git a/kb-lib/README.md b/kb-lib/README.md index 6d1827e..776f522 100644 --- a/kb-lib/README.md +++ b/kb-lib/README.md @@ -1,5 +1,5 @@ - + # kb-lib @@ -58,7 +58,7 @@ Les matrices actives sont maintenues sous [`../test-fixtures/contract-matrices/` ## Statut et limites -La migration des surfaces historiques jusqu’à un périmètre proche de bot2 `0.4.6` est largement réalisée. Le décodeur Metaplex Token Metadata couvre les 58 discriminants et les matérialisations possèdent désormais un contrat fermé de propriété des faits. L’exécuteur Metaplex possède désormais ses fondations typées et les wrappers courants `Create`/`Update` et `Verify`/`Unverify`, ainsi que les opérations dépréciées `PuffMetadata`, `SetTokenStandard` et `SetCollectionSize`; les autres opérations courantes restent à achever jusqu’à `pre.006`. Le registre ElGamal n’est pas déclaré validé sur Devnet ou Mainnet. +La migration des surfaces historiques jusqu’à un périmètre proche de bot2 `0.4.6` est largement réalisée. Le décodeur Metaplex Token Metadata couvre les 58 discriminants et les matérialisations possèdent désormais un contrat fermé de propriété des faits. L’exécuteur Metaplex possède désormais ses fondations typées et les wrappers courants `Create`/`Update`, `Verify`/`Unverify`, `Burn`, `Delegate`/`Revoke`, `Lock`/`Unlock`, `Transfer` et `CloseAccounts`, ainsi que les opérations dépréciées `PuffMetadata`, `SetTokenStandard` et `SetCollectionSize`; les éditions, uses, escrow et opérations restantes doivent être fermés en `pre.006`. Le registre ElGamal n’est pas déclaré validé sur Devnet ou Mainnet. ## Documents diff --git a/kb-lib/TODO.md b/kb-lib/TODO.md index ed884e3..6c5987a 100644 --- a/kb-lib/TODO.md +++ b/kb-lib/TODO.md @@ -1,5 +1,5 @@ - + # TODO — kb-lib @@ -8,7 +8,8 @@ - [x] établir le contrat fermé de couverture et de propriété des faits ; - [x] introduire les intents et builders courants `Create`/`Update` ; - [x] achever les wrappers courants Verify/Unverify et l’opération dépréciée SetCollectionSize ; -- [ ] achever délégations, pNFT, éditions, use, escrow et opérations courantes restantes avant `pre.006` ; +- [x] achever délégations et opérations pNFT `Burn`/`Lock`/`Unlock`/`Transfer`/`CloseAccounts` ; +- [ ] achever éditions, use, escrow et opérations courantes restantes en `pre.006` ; ## Entre `0.4.6` et `0.4.7` — Metaplex Token Metadata diff --git a/kb-lib/src/executor.rs b/kb-lib/src/executor.rs index a10f625..e494d5e 100644 --- a/kb-lib/src/executor.rs +++ b/kb-lib/src/executor.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/executor.rs -// version: 12 +// version: 13 //! Consolidated executor modules. @@ -208,18 +208,32 @@ pub use self::lending::ExLendingKaminoExecutor; pub use self::lending::ExLendingMarginfiV2Executor; /// Exposes the reserved `lock/raydium_lp` executor. pub use self::lock::ExLockRaydiumLpExecutor; +/// Stable operation code for Metaplex Burn. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION; +/// Stable operation code for Metaplex Close Accounts. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION; /// Stable operation code for the current Metaplex Create wrapper. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION; +/// Stable operation code for Metaplex Delegate. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION; /// Deprecated Metaplex operation codes requiring explicit approval. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_DEPRECATED_OPERATION_CODES; +/// Stable operation code for Metaplex Lock. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION; /// Stable deprecated Metaplex PuffMetadata operation code. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_PUFF_METADATA_OPERATION; +/// Stable operation code for Metaplex Revoke. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION; /// Stable deprecated Metaplex SetCollectionSize operation code. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION; /// Stable deprecated Metaplex SetTokenStandard operation code. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_SET_TOKEN_STANDARD_OPERATION; /// Current and deprecated Metaplex Token Metadata operations. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES; +/// Stable operation code for Metaplex Transfer. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION; +/// Stable operation code for Metaplex Unlock. +pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION; /// Stable operation code for the current Metaplex Unverify wrapper. pub use self::metadata::EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION; /// Stable operation code for the current Metaplex Update wrapper. diff --git a/kb-lib/src/executor/metadata.rs b/kb-lib/src/executor/metadata.rs index 849de0a..32e7ce7 100644 --- a/kb-lib/src/executor/metadata.rs +++ b/kb-lib/src/executor/metadata.rs @@ -1,18 +1,25 @@ // file: kb-lib/src/executor/metadata.rs -// version: 6 +// version: 7 //! `metadata` executor family. mod metaplex_token_metadata; mod solana_program_metadata; mod spl_name_service; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION; /// Exposes the Metaplex Token Metadata execution surface. pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_DEPRECATED_OPERATION_CODES; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_PUFF_METADATA_OPERATION; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_SET_TOKEN_STANDARD_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION; +pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION; pub use self::metaplex_token_metadata::EX_METAPLEX_TOKEN_METADATA_VERIFY_OPERATION; diff --git a/kb-lib/src/executor/metadata/metaplex_token_metadata.rs b/kb-lib/src/executor/metadata/metaplex_token_metadata.rs index 8206a27..a557470 100644 --- a/kb-lib/src/executor/metadata/metaplex_token_metadata.rs +++ b/kb-lib/src/executor/metadata/metaplex_token_metadata.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/executor/metadata/metaplex_token_metadata.rs -// version: 8 +// version: 9 //! Metaplex Token Metadata typed execution surface. @@ -9,18 +9,32 @@ mod intent; /// Exposes the Metaplex Token Metadata executor. pub use self::executor::ExMetadataMetaplexTokenMetadataExecutor; +/// Stable operation code for Metaplex Burn. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION; +/// Stable operation code for Metaplex Close Accounts. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION; /// Stable operation code for the current Create wrapper. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION; +/// Stable operation code for Metaplex Delegate. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION; /// Deprecated operation codes requiring explicit operator approval. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_DEPRECATED_OPERATION_CODES; +/// Stable operation code for Metaplex Lock. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION; /// Stable deprecated operation code for PuffMetadata. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_PUFF_METADATA_OPERATION; +/// Stable operation code for Metaplex Revoke. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION; /// Stable deprecated operation code for SetCollectionSize. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION; /// Stable deprecated operation code for SetTokenStandard. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_SET_TOKEN_STANDARD_OPERATION; /// Current and deprecated operations implemented by this prerelease. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES; +/// Stable operation code for Metaplex Transfer. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION; +/// Stable operation code for Metaplex Unlock. +pub use self::intent::EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION; /// Stable operation code for the current Unverify wrapper. pub use self::intent::EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION; /// Stable operation code for the current Update wrapper. diff --git a/kb-lib/src/executor/metadata/metaplex_token_metadata/builder.rs b/kb-lib/src/executor/metadata/metaplex_token_metadata/builder.rs index 4aa3901..b46a6d4 100644 --- a/kb-lib/src/executor/metadata/metaplex_token_metadata/builder.rs +++ b/kb-lib/src/executor/metadata/metaplex_token_metadata/builder.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/executor/metadata/metaplex_token_metadata/builder.rs -// version: 5 +// version: 6 //! Official Metaplex builders and conservative plan validation. @@ -19,6 +19,17 @@ macro_rules! parse_official_pubkey { }}; } +macro_rules! parse_optional_official_pubkey { + ($value:expr, $field:expr) => {{ + match $value { + std::option::Option::Some(value) => { + std::option::Option::Some(parse_official_pubkey!(&value.0, $field)) + }, + std::option::Option::None => std::option::Option::None, + } + }}; +} + macro_rules! convert_official_instruction { ($instruction:expr) => {{ let instruction = $instruction; @@ -151,6 +162,178 @@ pub(crate) fn executor_metaplex_token_metadata_build_prepared_plan( collection_authority_record.as_ref(), *size, ), + crate::ExMetaplexTokenMetadataOperation::Burn { + authority, + collection_metadata, + metadata, + edition, + mint, + token, + master_edition, + master_edition_mint, + master_edition_token, + edition_marker, + token_record, + burn_args, + } => build_burn( + authority, + collection_metadata.as_ref(), + metadata, + edition.as_ref(), + mint, + token, + master_edition.as_ref(), + master_edition_mint.as_ref(), + master_edition_token.as_ref(), + edition_marker.as_ref(), + token_record.as_ref(), + burn_args, + ), + crate::ExMetaplexTokenMetadataOperation::Delegate { + delegate_record, + delegate, + metadata, + master_edition, + token_record, + mint, + token, + authority, + spl_token_program, + authorization_rules_program, + authorization_rules, + delegate_args, + } => build_delegate( + intent, + delegate_record.as_ref(), + delegate, + metadata, + master_edition.as_ref(), + token_record.as_ref(), + mint, + token.as_ref(), + authority, + spl_token_program.as_ref(), + authorization_rules_program.as_ref(), + authorization_rules.as_ref(), + delegate_args, + ), + crate::ExMetaplexTokenMetadataOperation::Revoke { + delegate_record, + delegate, + metadata, + master_edition, + token_record, + mint, + token, + authority, + spl_token_program, + authorization_rules_program, + authorization_rules, + revoke_args, + } => build_revoke( + intent, + delegate_record.as_ref(), + delegate, + metadata, + master_edition.as_ref(), + token_record.as_ref(), + mint, + token.as_ref(), + authority, + spl_token_program.as_ref(), + authorization_rules_program.as_ref(), + authorization_rules.as_ref(), + revoke_args, + ), + crate::ExMetaplexTokenMetadataOperation::Lock { + authority, + token_owner, + token, + mint, + metadata, + edition, + token_record, + spl_token_program, + authorization_rules_program, + authorization_rules, + lock_args, + } => build_lock( + intent, + authority, + token_owner.as_ref(), + token, + mint, + metadata, + edition.as_ref(), + token_record.as_ref(), + spl_token_program.as_ref(), + authorization_rules_program.as_ref(), + authorization_rules.as_ref(), + lock_args, + ), + crate::ExMetaplexTokenMetadataOperation::Unlock { + authority, + token_owner, + token, + mint, + metadata, + edition, + token_record, + spl_token_program, + authorization_rules_program, + authorization_rules, + unlock_args, + } => build_unlock( + intent, + authority, + token_owner.as_ref(), + token, + mint, + metadata, + edition.as_ref(), + token_record.as_ref(), + spl_token_program.as_ref(), + authorization_rules_program.as_ref(), + authorization_rules.as_ref(), + unlock_args, + ), + crate::ExMetaplexTokenMetadataOperation::Transfer { + token, + token_owner, + destination_token, + destination_owner, + mint, + metadata, + edition, + token_record, + destination_token_record, + authority, + authorization_rules_program, + authorization_rules, + transfer_args, + } => build_transfer( + intent, + token, + token_owner, + destination_token, + destination_owner, + mint, + metadata, + edition.as_ref(), + token_record.as_ref(), + destination_token_record.as_ref(), + authority, + authorization_rules_program.as_ref(), + authorization_rules.as_ref(), + transfer_args, + ), + crate::ExMetaplexTokenMetadataOperation::CloseAccounts { + metadata, + edition, + mint, + authority, + destination, + } => build_close_accounts(metadata, edition, mint, authority, destination), }; let instruction = match instruction_result { std::result::Result::Ok(value) => value, @@ -197,7 +380,7 @@ fn validate_intent(intent: &crate::ExMetaplexTokenMetadataExecutionIntent) -> kb if !intent.policy.dry_run { return std::result::Result::Err(kb_core::Error::new( "execution_metaplex_dry_run_required", - "Metaplex Token Metadata pre.004 intents are simulation-only", + "Metaplex Token Metadata pre.005 intents are simulation-only", )); } match intent.policy.cost_limit.max_fee_lamports { @@ -787,6 +970,393 @@ fn required_signers( return required; } +fn validate_rule_accounts( + program: std::option::Option<&crate::MdProgramId>, + rules: std::option::Option<&crate::MdPubkey>, +) -> kb_core::Result<()> { + if program.is_some() != rules.is_some() { + return std::result::Result::Err(kb_core::Error::new( + "execution_metaplex_rule_set_accounts_incomplete", + "authorization rules program and account must be supplied together", + )); + } + return std::result::Result::Ok(()); +} + +#[allow(clippy::too_many_arguments)] +fn build_delegate( + intent: &crate::ExMetaplexTokenMetadataExecutionIntent, + delegate_record: std::option::Option<&crate::MdPubkey>, + delegate: &crate::MdPubkey, + metadata: &crate::MdPubkey, + master_edition: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + mint: &crate::MdPubkey, + token: std::option::Option<&crate::MdPubkey>, + authority: &crate::MdPubkey, + spl_token_program: std::option::Option<&crate::MdProgramId>, + authorization_rules_program: std::option::Option<&crate::MdProgramId>, + authorization_rules: std::option::Option<&crate::MdPubkey>, + delegate_args: &mpl_token_metadata::types::DelegateArgs, +) -> kb_core::Result { + if let std::result::Result::Err(error) = + validate_rule_accounts(authorization_rules_program, authorization_rules) + { + return std::result::Result::Err(error); + } + let official = mpl_token_metadata::instructions::Delegate { + delegate_record: parse_optional_official_pubkey!(delegate_record, "delegate_record"), + delegate: parse_official_pubkey!(&delegate.0, "delegate"), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + master_edition: parse_optional_official_pubkey!(master_edition, "master_edition"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + mint: parse_official_pubkey!(&mint.0, "mint"), + token: parse_optional_official_pubkey!(token, "token"), + authority: parse_official_pubkey!(&authority.0, "authority"), + payer: parse_official_pubkey!(&intent.fee_payer.0, "fee_payer"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: match spl_token_program { + std::option::Option::Some(v) => { + std::option::Option::Some(parse_official_pubkey!(&v.0, "spl_token_program")) + }, + std::option::Option::None => std::option::Option::None, + }, + authorization_rules_program: match authorization_rules_program { + std::option::Option::Some(v) => std::option::Option::Some(parse_official_pubkey!( + &v.0, + "authorization_rules_program" + )), + std::option::Option::None => std::option::Option::None, + }, + authorization_rules: parse_optional_official_pubkey!( + authorization_rules, + "authorization_rules" + ), + } + .instruction(mpl_token_metadata::instructions::DelegateInstructionArgs { + delegate_args: delegate_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +#[allow(clippy::too_many_arguments)] +fn build_revoke( + intent: &crate::ExMetaplexTokenMetadataExecutionIntent, + delegate_record: std::option::Option<&crate::MdPubkey>, + delegate: &crate::MdPubkey, + metadata: &crate::MdPubkey, + master_edition: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + mint: &crate::MdPubkey, + token: std::option::Option<&crate::MdPubkey>, + authority: &crate::MdPubkey, + spl_token_program: std::option::Option<&crate::MdProgramId>, + authorization_rules_program: std::option::Option<&crate::MdProgramId>, + authorization_rules: std::option::Option<&crate::MdPubkey>, + revoke_args: &mpl_token_metadata::types::RevokeArgs, +) -> kb_core::Result { + if let std::result::Result::Err(error) = + validate_rule_accounts(authorization_rules_program, authorization_rules) + { + return std::result::Result::Err(error); + } + let official = mpl_token_metadata::instructions::Revoke { + delegate_record: parse_optional_official_pubkey!(delegate_record, "delegate_record"), + delegate: parse_official_pubkey!(&delegate.0, "delegate"), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + master_edition: parse_optional_official_pubkey!(master_edition, "master_edition"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + mint: parse_official_pubkey!(&mint.0, "mint"), + token: parse_optional_official_pubkey!(token, "token"), + authority: parse_official_pubkey!(&authority.0, "authority"), + payer: parse_official_pubkey!(&intent.fee_payer.0, "fee_payer"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: match spl_token_program { + std::option::Option::Some(v) => { + std::option::Option::Some(parse_official_pubkey!(&v.0, "spl_token_program")) + }, + std::option::Option::None => std::option::Option::None, + }, + authorization_rules_program: match authorization_rules_program { + std::option::Option::Some(v) => std::option::Option::Some(parse_official_pubkey!( + &v.0, + "authorization_rules_program" + )), + std::option::Option::None => std::option::Option::None, + }, + authorization_rules: parse_optional_official_pubkey!( + authorization_rules, + "authorization_rules" + ), + } + .instruction(mpl_token_metadata::instructions::RevokeInstructionArgs { + revoke_args: revoke_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +#[allow(clippy::too_many_arguments)] +fn build_lock( + intent: &crate::ExMetaplexTokenMetadataExecutionIntent, + authority: &crate::MdPubkey, + token_owner: std::option::Option<&crate::MdPubkey>, + token: &crate::MdPubkey, + mint: &crate::MdPubkey, + metadata: &crate::MdPubkey, + edition: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + spl_token_program: std::option::Option<&crate::MdProgramId>, + authorization_rules_program: std::option::Option<&crate::MdProgramId>, + authorization_rules: std::option::Option<&crate::MdPubkey>, + lock_args: &mpl_token_metadata::types::LockArgs, +) -> kb_core::Result { + if let std::result::Result::Err(error) = + validate_rule_accounts(authorization_rules_program, authorization_rules) + { + return std::result::Result::Err(error); + } + let official = mpl_token_metadata::instructions::Lock { + authority: parse_official_pubkey!(&authority.0, "authority"), + token_owner: parse_optional_official_pubkey!(token_owner, "token_owner"), + token: parse_official_pubkey!(&token.0, "token"), + mint: parse_official_pubkey!(&mint.0, "mint"), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + edition: parse_optional_official_pubkey!(edition, "edition"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + payer: parse_official_pubkey!(&intent.fee_payer.0, "fee_payer"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: match spl_token_program { + std::option::Option::Some(v) => { + std::option::Option::Some(parse_official_pubkey!(&v.0, "spl_token_program")) + }, + std::option::Option::None => std::option::Option::None, + }, + authorization_rules_program: match authorization_rules_program { + std::option::Option::Some(v) => std::option::Option::Some(parse_official_pubkey!( + &v.0, + "authorization_rules_program" + )), + std::option::Option::None => std::option::Option::None, + }, + authorization_rules: parse_optional_official_pubkey!( + authorization_rules, + "authorization_rules" + ), + } + .instruction(mpl_token_metadata::instructions::LockInstructionArgs { + lock_args: lock_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +#[allow(clippy::too_many_arguments)] +fn build_unlock( + intent: &crate::ExMetaplexTokenMetadataExecutionIntent, + authority: &crate::MdPubkey, + token_owner: std::option::Option<&crate::MdPubkey>, + token: &crate::MdPubkey, + mint: &crate::MdPubkey, + metadata: &crate::MdPubkey, + edition: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + spl_token_program: std::option::Option<&crate::MdProgramId>, + authorization_rules_program: std::option::Option<&crate::MdProgramId>, + authorization_rules: std::option::Option<&crate::MdPubkey>, + unlock_args: &mpl_token_metadata::types::UnlockArgs, +) -> kb_core::Result { + if let std::result::Result::Err(error) = + validate_rule_accounts(authorization_rules_program, authorization_rules) + { + return std::result::Result::Err(error); + } + let official = mpl_token_metadata::instructions::Unlock { + authority: parse_official_pubkey!(&authority.0, "authority"), + token_owner: parse_optional_official_pubkey!(token_owner, "token_owner"), + token: parse_official_pubkey!(&token.0, "token"), + mint: parse_official_pubkey!(&mint.0, "mint"), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + edition: parse_optional_official_pubkey!(edition, "edition"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + payer: parse_official_pubkey!(&intent.fee_payer.0, "fee_payer"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: match spl_token_program { + std::option::Option::Some(v) => { + std::option::Option::Some(parse_official_pubkey!(&v.0, "spl_token_program")) + }, + std::option::Option::None => std::option::Option::None, + }, + authorization_rules_program: match authorization_rules_program { + std::option::Option::Some(v) => std::option::Option::Some(parse_official_pubkey!( + &v.0, + "authorization_rules_program" + )), + std::option::Option::None => std::option::Option::None, + }, + authorization_rules: parse_optional_official_pubkey!( + authorization_rules, + "authorization_rules" + ), + } + .instruction(mpl_token_metadata::instructions::UnlockInstructionArgs { + unlock_args: unlock_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +#[allow(clippy::too_many_arguments)] +fn build_transfer( + intent: &crate::ExMetaplexTokenMetadataExecutionIntent, + token: &crate::MdPubkey, + token_owner: &crate::MdPubkey, + destination_token: &crate::MdPubkey, + destination_owner: &crate::MdPubkey, + mint: &crate::MdPubkey, + metadata: &crate::MdPubkey, + edition: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + destination_token_record: std::option::Option<&crate::MdPubkey>, + authority: &crate::MdPubkey, + authorization_rules_program: std::option::Option<&crate::MdProgramId>, + authorization_rules: std::option::Option<&crate::MdPubkey>, + transfer_args: &mpl_token_metadata::types::TransferArgs, +) -> kb_core::Result { + if let std::result::Result::Err(error) = + validate_rule_accounts(authorization_rules_program, authorization_rules) + { + return std::result::Result::Err(error); + } + let official = mpl_token_metadata::instructions::Transfer { + token: parse_official_pubkey!(&token.0, "token"), + token_owner: parse_official_pubkey!(&token_owner.0, "token_owner"), + destination_token: parse_official_pubkey!(&destination_token.0, "destination_token"), + destination_owner: parse_official_pubkey!(&destination_owner.0, "destination_owner"), + mint: parse_official_pubkey!(&mint.0, "mint"), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + edition: parse_optional_official_pubkey!(edition, "edition"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + destination_token_record: parse_optional_official_pubkey!( + destination_token_record, + "destination_token_record" + ), + authority: parse_official_pubkey!(&authority.0, "authority"), + payer: parse_official_pubkey!(&intent.fee_payer.0, "fee_payer"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: parse_official_pubkey!( + kb_program_ids::SPL_TOKEN_PROGRAM_ID, + "spl_token_program" + ), + spl_ata_program: parse_official_pubkey!( + kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID, + "spl_ata_program" + ), + authorization_rules_program: match authorization_rules_program { + std::option::Option::Some(v) => std::option::Option::Some(parse_official_pubkey!( + &v.0, + "authorization_rules_program" + )), + std::option::Option::None => std::option::Option::None, + }, + authorization_rules: parse_optional_official_pubkey!( + authorization_rules, + "authorization_rules" + ), + } + .instruction(mpl_token_metadata::instructions::TransferInstructionArgs { + transfer_args: transfer_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +#[allow(clippy::too_many_arguments)] +fn build_burn( + authority: &crate::MdPubkey, + collection_metadata: std::option::Option<&crate::MdPubkey>, + metadata: &crate::MdPubkey, + edition: std::option::Option<&crate::MdPubkey>, + mint: &crate::MdPubkey, + token: &crate::MdPubkey, + master_edition: std::option::Option<&crate::MdPubkey>, + master_edition_mint: std::option::Option<&crate::MdPubkey>, + master_edition_token: std::option::Option<&crate::MdPubkey>, + edition_marker: std::option::Option<&crate::MdPubkey>, + token_record: std::option::Option<&crate::MdPubkey>, + burn_args: &mpl_token_metadata::types::BurnArgs, +) -> kb_core::Result { + let official = mpl_token_metadata::instructions::Burn { + authority: parse_official_pubkey!(&authority.0, "authority"), + collection_metadata: parse_optional_official_pubkey!( + collection_metadata, + "collection_metadata" + ), + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + edition: parse_optional_official_pubkey!(edition, "edition"), + mint: parse_official_pubkey!(&mint.0, "mint"), + token: parse_official_pubkey!(&token.0, "token"), + master_edition: parse_optional_official_pubkey!(master_edition, "master_edition"), + master_edition_mint: parse_optional_official_pubkey!( + master_edition_mint, + "master_edition_mint" + ), + master_edition_token: parse_optional_official_pubkey!( + master_edition_token, + "master_edition_token" + ), + edition_marker: parse_optional_official_pubkey!(edition_marker, "edition_marker"), + token_record: parse_optional_official_pubkey!(token_record, "token_record"), + system_program: parse_official_pubkey!(kb_program_ids::SYSTEM_PROGRAM_ID, "system_program"), + sysvar_instructions: parse_official_pubkey!( + kb_program_ids::SYSVAR_INSTRUCTIONS_PROGRAM_ID, + "sysvar_instructions" + ), + spl_token_program: parse_official_pubkey!( + kb_program_ids::SPL_TOKEN_PROGRAM_ID, + "spl_token_program" + ), + } + .instruction(mpl_token_metadata::instructions::BurnInstructionArgs { + burn_args: burn_args.clone(), + }); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + +fn build_close_accounts( + metadata: &crate::MdPubkey, + edition: &crate::MdPubkey, + mint: &crate::MdPubkey, + authority: &crate::MdPubkey, + destination: &crate::MdPubkey, +) -> kb_core::Result { + let official = mpl_token_metadata::instructions::CloseAccounts { + metadata: parse_official_pubkey!(&metadata.0, "metadata"), + edition: parse_official_pubkey!(&edition.0, "edition"), + mint: parse_official_pubkey!(&mint.0, "mint"), + authority: parse_official_pubkey!(&authority.0, "authority"), + destination: parse_official_pubkey!(&destination.0, "destination"), + } + .instruction(); + return std::result::Result::Ok(convert_official_instruction!(official)); +} + #[cfg(test)] mod tests { #[allow(deprecated)] @@ -952,4 +1522,23 @@ mod tests { ); } } + + #[test] + fn close_accounts_preserves_discriminator_and_exact_signer() { + let result = super::build_close_accounts( + &crate::MdPubkey("11111111111111111111111111111111".to_string()), + &crate::MdPubkey("SysvarRent111111111111111111111111111111111".to_string()), + &crate::MdPubkey("So11111111111111111111111111111111111111112".to_string()), + &crate::MdPubkey("Vote111111111111111111111111111111111111111".to_string()), + &crate::MdPubkey("Stake11111111111111111111111111111111111111".to_string()), + ); + assert!(result.is_ok()); + let instruction = match result { + std::result::Result::Ok(value) => value, + std::result::Result::Err(_) => return, + }; + assert_eq!(instruction.data.first().copied(), std::option::Option::Some(57)); + assert_eq!(instruction.accounts.len(), 5); + assert!(instruction.accounts[3].is_signer); + } } diff --git a/kb-lib/src/executor/metadata/metaplex_token_metadata/executor.rs b/kb-lib/src/executor/metadata/metaplex_token_metadata/executor.rs index fa8b86e..0c169fe 100644 --- a/kb-lib/src/executor/metadata/metaplex_token_metadata/executor.rs +++ b/kb-lib/src/executor/metadata/metaplex_token_metadata/executor.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/executor/metadata/metaplex_token_metadata/executor.rs -// version: 4 +// version: 5 //! Exact Metaplex Token Metadata capability dispatch. @@ -162,6 +162,12 @@ mod tests { crate::EX_METAPLEX_TOKEN_METADATA_VERIFY_OPERATION, ); assert!(matches!(supported, crate::ExApiExecutionCapability::Supported { .. })); + let transfer = ::capability( + &executor, + &program_id, + crate::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION, + ); + assert!(matches!(transfer, crate::ExApiExecutionCapability::Supported { .. })); let unknown = ::capability( &executor, &program_id, diff --git a/kb-lib/src/executor/metadata/metaplex_token_metadata/intent.rs b/kb-lib/src/executor/metadata/metaplex_token_metadata/intent.rs index 2648631..16da167 100644 --- a/kb-lib/src/executor/metadata/metaplex_token_metadata/intent.rs +++ b/kb-lib/src/executor/metadata/metaplex_token_metadata/intent.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/executor/metadata/metaplex_token_metadata/intent.rs -// version: 4 +// version: 6 //! Typed current and deprecated Metaplex Token Metadata execution intents. @@ -26,13 +26,32 @@ pub const EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION: &str = /// Stable deprecated operation code for SetCollectionSize, discriminator 34. pub const EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION: &str = "metadata.metaplex_token_metadata.set_collection_size"; +/// Stable operation code for the current Burn wrapper, discriminator 41. +pub const EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION: &str = "metadata.metaplex_token_metadata.burn"; +/// Stable operation code for the current Delegate wrapper, discriminator 44. +pub const EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION: &str = + "metadata.metaplex_token_metadata.delegate"; +/// Stable operation code for the current Revoke wrapper, discriminator 45. +pub const EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION: &str = + "metadata.metaplex_token_metadata.revoke"; +/// Stable operation code for the current Lock wrapper, discriminator 46. +pub const EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION: &str = "metadata.metaplex_token_metadata.lock"; +/// Stable operation code for the current Unlock wrapper, discriminator 47. +pub const EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION: &str = + "metadata.metaplex_token_metadata.unlock"; +/// Stable operation code for the current Transfer wrapper, discriminator 49. +pub const EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION: &str = + "metadata.metaplex_token_metadata.transfer"; +/// Stable operation code for CloseAccounts, discriminator 57. +pub const EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION: &str = + "metadata.metaplex_token_metadata.close_accounts"; /// Deprecated operations that require explicit operator approval at runtime. pub const EX_METAPLEX_TOKEN_METADATA_DEPRECATED_OPERATION_CODES: &[&str] = &[ EX_METAPLEX_TOKEN_METADATA_PUFF_METADATA_OPERATION, EX_METAPLEX_TOKEN_METADATA_SET_TOKEN_STANDARD_OPERATION, EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION, ]; -/// Current and deprecated operations implemented through `0.4.7-pre.004`. +/// Current and deprecated operations implemented through `0.4.7-pre.005`. pub const EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES: &[&str] = &[ EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION, EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION, @@ -41,6 +60,13 @@ pub const EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES: &[&str] = &[ EX_METAPLEX_TOKEN_METADATA_VERIFY_OPERATION, EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION, EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION, + EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION, + EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION, + EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION, + EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION, + EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION, + EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION, + EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION, ]; /// One current or explicitly deprecated Metaplex Token Metadata operation. @@ -168,6 +194,116 @@ pub enum ExMetaplexTokenMetadataOperation { /// New collection size. size: u64, }, + #[allow(missing_docs)] + /// Build the current Burn wrapper. + Burn { + authority: crate::MdPubkey, + collection_metadata: std::option::Option, + metadata: crate::MdPubkey, + edition: std::option::Option, + mint: crate::MdPubkey, + token: crate::MdPubkey, + master_edition: std::option::Option, + master_edition_mint: std::option::Option, + master_edition_token: std::option::Option, + edition_marker: std::option::Option, + token_record: std::option::Option, + #[ts(type = "unknown")] + burn_args: mpl_token_metadata::types::BurnArgs, + }, + #[allow(missing_docs)] + /// Build the current unified Delegate wrapper. + Delegate { + delegate_record: std::option::Option, + delegate: crate::MdPubkey, + metadata: crate::MdPubkey, + master_edition: std::option::Option, + token_record: std::option::Option, + mint: crate::MdPubkey, + token: std::option::Option, + authority: crate::MdPubkey, + spl_token_program: std::option::Option, + authorization_rules_program: std::option::Option, + authorization_rules: std::option::Option, + #[ts(type = "unknown")] + delegate_args: mpl_token_metadata::types::DelegateArgs, + }, + #[allow(missing_docs)] + /// Build the current unified Revoke wrapper. + Revoke { + delegate_record: std::option::Option, + delegate: crate::MdPubkey, + metadata: crate::MdPubkey, + master_edition: std::option::Option, + token_record: std::option::Option, + mint: crate::MdPubkey, + token: std::option::Option, + authority: crate::MdPubkey, + spl_token_program: std::option::Option, + authorization_rules_program: std::option::Option, + authorization_rules: std::option::Option, + #[ts(type = "unknown")] + revoke_args: mpl_token_metadata::types::RevokeArgs, + }, + #[allow(missing_docs)] + /// Build the current Lock wrapper. + Lock { + authority: crate::MdPubkey, + token_owner: std::option::Option, + token: crate::MdPubkey, + mint: crate::MdPubkey, + metadata: crate::MdPubkey, + edition: std::option::Option, + token_record: std::option::Option, + spl_token_program: std::option::Option, + authorization_rules_program: std::option::Option, + authorization_rules: std::option::Option, + #[ts(type = "unknown")] + lock_args: mpl_token_metadata::types::LockArgs, + }, + #[allow(missing_docs)] + /// Build the current Unlock wrapper. + Unlock { + authority: crate::MdPubkey, + token_owner: std::option::Option, + token: crate::MdPubkey, + mint: crate::MdPubkey, + metadata: crate::MdPubkey, + edition: std::option::Option, + token_record: std::option::Option, + spl_token_program: std::option::Option, + authorization_rules_program: std::option::Option, + authorization_rules: std::option::Option, + #[ts(type = "unknown")] + unlock_args: mpl_token_metadata::types::UnlockArgs, + }, + #[allow(missing_docs)] + /// Build the current Transfer wrapper. + Transfer { + token: crate::MdPubkey, + token_owner: crate::MdPubkey, + destination_token: crate::MdPubkey, + destination_owner: crate::MdPubkey, + mint: crate::MdPubkey, + metadata: crate::MdPubkey, + edition: std::option::Option, + token_record: std::option::Option, + destination_token_record: std::option::Option, + authority: crate::MdPubkey, + authorization_rules_program: std::option::Option, + authorization_rules: std::option::Option, + #[ts(type = "unknown")] + transfer_args: mpl_token_metadata::types::TransferArgs, + }, + #[allow(missing_docs)] + /// Close ownerless metadata and edition accounts. + CloseAccounts { + metadata: crate::MdPubkey, + edition: crate::MdPubkey, + mint: crate::MdPubkey, + authority: crate::MdPubkey, + destination: crate::MdPubkey, + }, } #[allow(deprecated)] @@ -188,6 +324,15 @@ impl crate::ExMetaplexTokenMetadataOperation { Self::SetCollectionSize { .. } => { crate::EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION }, + Self::Burn { .. } => crate::EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION, + Self::Delegate { .. } => crate::EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION, + Self::Revoke { .. } => crate::EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION, + Self::Lock { .. } => crate::EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION, + Self::Unlock { .. } => crate::EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION, + Self::Transfer { .. } => crate::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION, + Self::CloseAccounts { .. } => { + crate::EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION + }, }; } @@ -228,7 +373,7 @@ mod tests { #[test] #[allow(deprecated)] fn operation_codes_are_exact_unique_and_partition_deprecated_operations() { - assert_eq!(crate::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES.len(), 7); + assert_eq!(crate::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES.len(), 14); let mut unique = std::collections::BTreeSet::new(); for operation_code in crate::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES { assert!(unique.insert(*operation_code)); diff --git a/kb-lib/src/lib.rs b/kb-lib/src/lib.rs index e4b3037..0b74a3c 100644 --- a/kb-lib/src/lib.rs +++ b/kb-lib/src/lib.rs @@ -1,5 +1,5 @@ // file: kb-lib/src/lib.rs -// version: 29 +// version: 28 //! Consolidated decoder, executor, materializer and shared model library. #![warn(missing_docs)] @@ -358,18 +358,32 @@ pub use self::decoder::decoder_metadata_metaplex_token_metadata_decode_use_autho pub use self::decoder::decoder_spl_elgamal_registry_parse_elgamal_registry_state; /// Parses one Token-2022 Mint, Account, or Multisig state. pub use self::decoder::decoder_spl_token_2022_parse_token_2022_state; +/// Stable Metaplex Token Metadata burn operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_BURN_OPERATION; +/// Stable Metaplex Token Metadata close_accounts operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_CLOSE_ACCOUNTS_OPERATION; /// Stable operation code for the current Metaplex Create wrapper. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION; +/// Stable Metaplex Token Metadata delegate operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_DELEGATE_OPERATION; /// Deprecated Metaplex operation codes requiring explicit approval. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_DEPRECATED_OPERATION_CODES; +/// Stable Metaplex Token Metadata lock operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_LOCK_OPERATION; /// Stable deprecated Metaplex PuffMetadata operation code. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_PUFF_METADATA_OPERATION; +/// Stable Metaplex Token Metadata revoke operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_REVOKE_OPERATION; /// Stable deprecated Metaplex SetCollectionSize operation code. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_SET_COLLECTION_SIZE_OPERATION; /// Stable deprecated Metaplex SetTokenStandard operation code. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_SET_TOKEN_STANDARD_OPERATION; /// Current and deprecated Metaplex Token Metadata operations. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_SUPPORTED_OPERATION_CODES; +/// Stable Metaplex Token Metadata transfer operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION; +/// Stable Metaplex Token Metadata unlock operation code. +pub use self::executor::EX_METAPLEX_TOKEN_METADATA_UNLOCK_OPERATION; /// Stable operation code for the current Metaplex Unverify wrapper. pub use self::executor::EX_METAPLEX_TOKEN_METADATA_UNVERIFY_OPERATION; /// Stable operation code for the current Metaplex Update wrapper. diff --git a/test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json b/test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json index 9c06a16..4202330 100644 --- a/test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json +++ b/test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json @@ -1,6 +1,6 @@ { "schema_version": 3, - "milestone": "0.4.7-pre.002", + "milestone": "0.4.7-pre.005", "surface_code": "metadata.metaplex_token_metadata", "program_id": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", "program_family": "independent_metaplex_foundation_program", @@ -4902,7 +4902,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 42, @@ -5235,7 +5235,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 45, @@ -5356,7 +5356,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 46, @@ -5470,7 +5470,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 47, @@ -5584,7 +5584,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 48, @@ -5843,7 +5843,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" }, { "discriminator": 50, @@ -6519,7 +6519,7 @@ "authoritative_owned_account_reread", "operation_specific_state_transition" ], - "implementation_status": "scheduled" + "implementation_status": "implemented_pre_005" } ], "instruction_coverage_proof": {