use crate::{
deprecated_instruction::{MintPrintingTokensViaTokenArgs, SetReservationListArgs},
state::{Collection, Creator, Data, DataV2, Uses, EDITION, EDITION_MARKER_BIT_SIZE, PREFIX},
};
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::{
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
sysvar,
};
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct UpdateMetadataAccountArgs {
pub data: Option<Data>,
pub update_authority: Option<Pubkey>,
pub primary_sale_happened: Option<bool>,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct UpdateMetadataAccountArgsV2 {
pub data: Option<DataV2>,
pub update_authority: Option<Pubkey>,
pub primary_sale_happened: Option<bool>,
pub is_mutable: Option<bool>,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct CreateMetadataAccountArgs {
pub data: Data,
pub is_mutable: bool,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct CreateMetadataAccountArgsV2 {
pub data: DataV2,
pub is_mutable: bool,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct CreateMasterEditionArgs {
pub max_supply: Option<u64>,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct MintNewEditionFromMasterEditionViaTokenArgs {
pub edition: u64,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct ApproveUseAuthorityArgs {
pub number_of_uses: u64,
}
#[repr(C)]
#[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug, Clone)]
pub struct UtilizeArgs {
pub number_of_uses: u64,
}
#[derive(BorshSerialize, BorshDeserialize, Clone)]
pub enum MetadataInstruction {
CreateMetadataAccount(CreateMetadataAccountArgs),
UpdateMetadataAccount(UpdateMetadataAccountArgs),
DeprecatedCreateMasterEdition(CreateMasterEditionArgs),
DeprecatedMintNewEditionFromMasterEditionViaPrintingToken,
UpdatePrimarySaleHappenedViaToken,
DeprecatedSetReservationList(SetReservationListArgs),
DeprecatedCreateReservationList,
SignMetadata,
DeprecatedMintPrintingTokensViaToken(MintPrintingTokensViaTokenArgs),
DeprecatedMintPrintingTokens(MintPrintingTokensViaTokenArgs),
CreateMasterEdition(CreateMasterEditionArgs),
MintNewEditionFromMasterEditionViaToken(MintNewEditionFromMasterEditionViaTokenArgs),
ConvertMasterEditionV1ToV2,
MintNewEditionFromMasterEditionViaVaultProxy(MintNewEditionFromMasterEditionViaTokenArgs),
PuffMetadata,
UpdateMetadataAccountV2(UpdateMetadataAccountArgsV2),
CreateMetadataAccountV2(CreateMetadataAccountArgsV2),
CreateMasterEditionV3(CreateMasterEditionArgs),
VerifyCollection,
Utilize(UtilizeArgs),
ApproveUseAuthority(ApproveUseAuthorityArgs),
RevokeUseAuthority,
UnverifyCollection,
ApproveCollectionAuthority,
RevokeCollectionAuthority,
}
#[allow(clippy::too_many_arguments)]
pub fn create_metadata_accounts(
program_id: Pubkey,
metadata_account: Pubkey,
mint: Pubkey,
mint_authority: Pubkey,
payer: Pubkey,
update_authority: Pubkey,
name: String,
symbol: String,
uri: String,
creators: Option<Vec<Creator>>,
seller_fee_basis_points: u16,
update_authority_is_signer: bool,
is_mutable: bool,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata_account, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new_readonly(mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(update_authority, update_authority_is_signer),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::CreateMetadataAccount(CreateMetadataAccountArgs {
data: Data {
name,
symbol,
uri,
seller_fee_basis_points,
creators,
},
is_mutable,
})
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn create_metadata_accounts_v2(
program_id: Pubkey,
metadata_account: Pubkey,
mint: Pubkey,
mint_authority: Pubkey,
payer: Pubkey,
update_authority: Pubkey,
name: String,
symbol: String,
uri: String,
creators: Option<Vec<Creator>>,
seller_fee_basis_points: u16,
update_authority_is_signer: bool,
is_mutable: bool,
collection: Option<Collection>,
uses: Option<Uses>,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata_account, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new_readonly(mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(update_authority, update_authority_is_signer),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::CreateMetadataAccountV2(CreateMetadataAccountArgsV2 {
data: DataV2 {
name,
symbol,
uri,
seller_fee_basis_points,
creators,
collection,
uses,
},
is_mutable,
})
.try_to_vec()
.unwrap(),
}
}
pub fn update_metadata_accounts(
program_id: Pubkey,
metadata_account: Pubkey,
update_authority: Pubkey,
new_update_authority: Option<Pubkey>,
data: Option<Data>,
primary_sale_happened: Option<bool>,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata_account, false),
AccountMeta::new_readonly(update_authority, true),
],
data: MetadataInstruction::UpdateMetadataAccount(UpdateMetadataAccountArgs {
data,
update_authority: new_update_authority,
primary_sale_happened,
})
.try_to_vec()
.unwrap(),
}
}
pub fn update_metadata_accounts_v2(
program_id: Pubkey,
metadata_account: Pubkey,
update_authority: Pubkey,
new_update_authority: Option<Pubkey>,
data: Option<DataV2>,
primary_sale_happened: Option<bool>,
is_mutable: Option<bool>,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata_account, false),
AccountMeta::new_readonly(update_authority, true),
],
data: MetadataInstruction::UpdateMetadataAccountV2(UpdateMetadataAccountArgsV2 {
data,
update_authority: new_update_authority,
primary_sale_happened,
is_mutable,
})
.try_to_vec()
.unwrap(),
}
}
pub fn puff_metadata_account(program_id: Pubkey, metadata_account: Pubkey) -> Instruction {
Instruction {
program_id,
accounts: vec![AccountMeta::new(metadata_account, false)],
data: MetadataInstruction::PuffMetadata.try_to_vec().unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn update_primary_sale_happened_via_token(
program_id: Pubkey,
metadata: Pubkey,
owner: Pubkey,
token: Pubkey,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata, false),
AccountMeta::new_readonly(owner, true),
AccountMeta::new_readonly(token, false),
],
data: MetadataInstruction::UpdatePrimarySaleHappenedViaToken
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn create_master_edition(
program_id: Pubkey,
edition: Pubkey,
mint: Pubkey,
update_authority: Pubkey,
mint_authority: Pubkey,
metadata: Pubkey,
payer: Pubkey,
max_supply: Option<u64>,
) -> Instruction {
let accounts = vec![
AccountMeta::new(edition, false),
AccountMeta::new(mint, false),
AccountMeta::new_readonly(update_authority, true),
AccountMeta::new_readonly(mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
Instruction {
program_id,
accounts,
data: MetadataInstruction::CreateMasterEdition(CreateMasterEditionArgs { max_supply })
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn create_master_edition_v3(
program_id: Pubkey,
edition: Pubkey,
mint: Pubkey,
update_authority: Pubkey,
mint_authority: Pubkey,
metadata: Pubkey,
payer: Pubkey,
max_supply: Option<u64>,
) -> Instruction {
let accounts = vec![
AccountMeta::new(edition, false),
AccountMeta::new(mint, false),
AccountMeta::new_readonly(update_authority, true),
AccountMeta::new_readonly(mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new(metadata, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
Instruction {
program_id,
accounts,
data: MetadataInstruction::CreateMasterEditionV3(CreateMasterEditionArgs { max_supply })
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn mint_new_edition_from_master_edition_via_token(
program_id: Pubkey,
new_metadata: Pubkey,
new_edition: Pubkey,
master_edition: Pubkey,
new_mint: Pubkey,
new_mint_authority: Pubkey,
payer: Pubkey,
token_account_owner: Pubkey,
token_account: Pubkey,
new_metadata_update_authority: Pubkey,
metadata: Pubkey,
metadata_mint: Pubkey,
edition: u64,
) -> Instruction {
let edition_number = edition.checked_div(EDITION_MARKER_BIT_SIZE).unwrap();
let as_string = edition_number.to_string();
let (edition_mark_pda, _) = Pubkey::find_program_address(
&[
PREFIX.as_bytes(),
program_id.as_ref(),
metadata_mint.as_ref(),
EDITION.as_bytes(),
as_string.as_bytes(),
],
&program_id,
);
let accounts = vec![
AccountMeta::new(new_metadata, false),
AccountMeta::new(new_edition, false),
AccountMeta::new(master_edition, false),
AccountMeta::new(new_mint, false),
AccountMeta::new(edition_mark_pda, false),
AccountMeta::new_readonly(new_mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(token_account_owner, true),
AccountMeta::new_readonly(token_account, false),
AccountMeta::new_readonly(new_metadata_update_authority, false),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
Instruction {
program_id,
accounts,
data: MetadataInstruction::MintNewEditionFromMasterEditionViaToken(
MintNewEditionFromMasterEditionViaTokenArgs { edition },
)
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn sign_metadata(program_id: Pubkey, metadata: Pubkey, creator: Pubkey) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(metadata, false),
AccountMeta::new_readonly(creator, true),
],
data: MetadataInstruction::SignMetadata.try_to_vec().unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn convert_master_edition_v1_to_v2(
program_id: Pubkey,
master_edition: Pubkey,
one_time_auth: Pubkey,
printing_mint: Pubkey,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(master_edition, false),
AccountMeta::new(one_time_auth, false),
AccountMeta::new(printing_mint, false),
],
data: MetadataInstruction::ConvertMasterEditionV1ToV2
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn mint_edition_from_master_edition_via_vault_proxy(
program_id: Pubkey,
new_metadata: Pubkey,
new_edition: Pubkey,
master_edition: Pubkey,
new_mint: Pubkey,
edition_mark_pda: Pubkey,
new_mint_authority: Pubkey,
payer: Pubkey,
vault_authority: Pubkey,
safety_deposit_store: Pubkey,
safety_deposit_box: Pubkey,
vault: Pubkey,
new_metadata_update_authority: Pubkey,
metadata: Pubkey,
token_program: Pubkey,
token_vault_program_info: Pubkey,
edition: u64,
) -> Instruction {
let accounts = vec![
AccountMeta::new(new_metadata, false),
AccountMeta::new(new_edition, false),
AccountMeta::new(master_edition, false),
AccountMeta::new(new_mint, false),
AccountMeta::new(edition_mark_pda, false),
AccountMeta::new_readonly(new_mint_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(vault_authority, true),
AccountMeta::new_readonly(safety_deposit_store, false),
AccountMeta::new_readonly(safety_deposit_box, false),
AccountMeta::new_readonly(vault, false),
AccountMeta::new_readonly(new_metadata_update_authority, false),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new_readonly(token_vault_program_info, false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
Instruction {
program_id,
accounts,
data: MetadataInstruction::MintNewEditionFromMasterEditionViaVaultProxy(
MintNewEditionFromMasterEditionViaTokenArgs { edition },
)
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn verify_collection(
program_id: Pubkey,
metadata: Pubkey,
collection_authority: Pubkey,
payer: Pubkey,
collection_mint: Pubkey,
collection: Pubkey,
collection_master_edition_account: Pubkey,
collection_authority_record: Option<Pubkey>,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(metadata, false),
AccountMeta::new(collection_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(collection_mint, false),
AccountMeta::new_readonly(collection, false),
AccountMeta::new_readonly(collection_master_edition_account, false),
];
if collection_authority_record.is_some() {
accounts.push(AccountMeta::new_readonly(
collection_authority_record.unwrap(),
false,
));
}
Instruction {
program_id,
accounts: accounts,
data: MetadataInstruction::VerifyCollection.try_to_vec().unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn unverify_collection(
program_id: Pubkey,
metadata: Pubkey,
collection_authority: Pubkey,
collection_mint: Pubkey,
collection: Pubkey,
collection_master_edition_account: Pubkey,
collection_authority_record: Option<Pubkey>,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(metadata, false),
AccountMeta::new(collection_authority, true),
AccountMeta::new_readonly(collection_mint, false),
AccountMeta::new_readonly(collection, false),
AccountMeta::new_readonly(collection_master_edition_account, false),
];
if collection_authority_record.is_some() {
accounts.push(AccountMeta::new_readonly(
collection_authority_record.unwrap(),
false,
));
}
Instruction {
program_id,
accounts: accounts,
data: MetadataInstruction::UnverifyCollection
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn utilize(
program_id: Pubkey,
metadata: Pubkey,
token_account: Pubkey,
mint: Pubkey,
use_authority_record_pda: Option<Pubkey>,
use_authority: Pubkey,
owner: Pubkey,
burner: Option<Pubkey>,
number_of_uses: u64,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(metadata, false),
AccountMeta::new(token_account, false),
AccountMeta::new(mint, false),
AccountMeta::new(use_authority, true),
AccountMeta::new_readonly(owner, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(spl_associated_token_account::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
];
if use_authority_record_pda.is_some() {
accounts.push(AccountMeta::new(use_authority_record_pda.unwrap(), false));
}
if burner.is_some() {
accounts.push(AccountMeta::new_readonly(burner.unwrap(), false));
}
Instruction {
program_id,
accounts,
data: MetadataInstruction::Utilize(UtilizeArgs { number_of_uses })
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn approve_use_authority(
program_id: Pubkey,
use_authority_record: Pubkey,
user: Pubkey,
owner: Pubkey,
payer: Pubkey,
owner_token_account: Pubkey,
metadata: Pubkey,
mint: Pubkey,
burner: Pubkey,
number_of_uses: u64,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(use_authority_record, false),
AccountMeta::new(owner, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(user, false),
AccountMeta::new(owner_token_account, false),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new_readonly(burner, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::ApproveUseAuthority(ApproveUseAuthorityArgs { number_of_uses })
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn revoke_use_authority(
program_id: Pubkey,
use_authority_record: Pubkey,
user: Pubkey,
owner: Pubkey,
owner_token_account: Pubkey,
metadata: Pubkey,
mint: Pubkey,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(use_authority_record, false),
AccountMeta::new(owner, true),
AccountMeta::new_readonly(user, false),
AccountMeta::new(owner_token_account, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(spl_token::id(), false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::RevokeUseAuthority
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn approve_collection_authority(
program_id: Pubkey,
collection_authority_record: Pubkey,
new_collection_authority: Pubkey,
update_authority: Pubkey,
payer: Pubkey,
metadata: Pubkey,
mint: Pubkey,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(collection_authority_record, false),
AccountMeta::new_readonly(new_collection_authority, false),
AccountMeta::new(update_authority, true),
AccountMeta::new(payer, true),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(mint, false),
AccountMeta::new_readonly(solana_program::system_program::id(), false),
AccountMeta::new_readonly(sysvar::rent::id(), false),
],
data: MetadataInstruction::ApproveCollectionAuthority
.try_to_vec()
.unwrap(),
}
}
#[allow(clippy::too_many_arguments)]
pub fn revoke_collection_authority(
program_id: Pubkey,
collection_authority_record: Pubkey,
update_authority: Pubkey,
metadata: Pubkey,
mint: Pubkey,
) -> Instruction {
Instruction {
program_id,
accounts: vec![
AccountMeta::new(collection_authority_record, false),
AccountMeta::new(update_authority, true),
AccountMeta::new_readonly(metadata, false),
AccountMeta::new_readonly(mint, false),
],
data: MetadataInstruction::RevokeCollectionAuthority
.try_to_vec()
.unwrap(),
}
}