v0.4.7-pre.005

This commit is contained in:
2026-08-02 11:02:05 +02:00
parent d3b63e3a3c
commit 80f102b129
13 changed files with 825 additions and 27 deletions

View File

@@ -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.

View File

@@ -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;

View File

@@ -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.

View File

@@ -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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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<solana_instruction::Instruction> {
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);
}
}

View File

@@ -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 = <crate::ExMetadataMetaplexTokenMetadataExecutor as crate::ExApiTypedInstructionExecutor>::capability(
&executor,
&program_id,
crate::EX_METAPLEX_TOKEN_METADATA_TRANSFER_OPERATION,
);
assert!(matches!(transfer, crate::ExApiExecutionCapability::Supported { .. }));
let unknown = <crate::ExMetadataMetaplexTokenMetadataExecutor as crate::ExApiTypedInstructionExecutor>::capability(
&executor,
&program_id,

View File

@@ -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<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>,
#[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<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>,
#[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<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>,
#[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<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>,
#[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<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>,
#[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<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>,
#[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));

View File

@@ -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.