我们来看一下mpl-token的合约
metaplex-program-library
先来看一下
processor.rs文件
最开始的一部分是导包
然后我们看
process_instruction
这个也就是程序的入口
let instruction = MetadataInstruction::try_from_slice(input)?;
然后将input转换成instruction
然后match一下指令,执行具体的操作
然后从211行开始就是具体的操作
pub fn process_create_metadata_accounts_v2<'a>(
program_id: &'a Pubkey,
accounts: &'a [AccountInfo<'a>],
data: DataV2,
allow_direct_creator_writes: bool,
is_mutable: bool,
) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let metadata_account_info = next_account_info(account_info_iter)?;
let mint_info = next_account_info(account_info_iter)?;
let mint_authority_info = next_account_info(account_info_iter)?;
let payer_account_info = next_account_info(account_info_iter)?;
let update_authority_info = next_account_info(account_info_iter)?;
let system_account_info = next_account_info(account_info_iter)?;
let rent_info = next_account_info(account_info_iter)?;
process_create_metadata_accounts_logic(
&program_id,
CreateMetadataAccountsLogicArgs {
metadata_account_info,
mint_info,
mint_authority_info,
payer_account_info,
update_authority_info,
system_account_info,
rent_info,
},
data,
allow_direct_creator_writes,
is_mutable,
false,
true,
)
}
create_metadata_account
创建账户
这里就是构造了一些参数,然后调用
process_create_metadata_accounts_logic方法
然后我们看
process_create_metadata_accounts_logic
pub fn process_create_metadata_accounts_logic(
program_id: &Pubkey,
accounts: CreateMetadataAccountsLogicArgs,
data: DataV2,
allow_direct_creator_writes: bool,
mut is_mutable: bool,
is_edition: bool,
add_token_standard: bool,
) -> ProgramResult {
let CreateMetadataAccountsLogicArgs {
metadata_account_info,
mint_info,
mint_authority_info,
payer_account_info,
update_authority_info,
system_account_info,
rent_info,
} = accounts;
let mut update_authority_key = *update_authority_info.key;
let existing_mint_authority = get_mint_authority(mint_info)?;
// IMPORTANT NOTE
// This allows the Metaplex Foundation to Create but not update metadata for SPL tokens that have not populated their metadata.
assert_mint_authority_matches_mint(&existing_mint_authority, mint_authority_info).or_else(
|e| {
// Allow seeding by the authority seed populator
if mint_authority_info.key == &SEED_AUTHORITY && mint_authority_info.is_signer {
// When metadata is seeded, the mint authority should be able to change it
if let COption::Some(auth) = existing_mint_authority {
update_authority_key = auth;
is_mutable = true;
}
Ok(())
} else {
Err(e)
}
},
)?;
assert_owned_by(mint_info, &spl_token::id())?;
let metadata_seeds = &[
PREFIX.as_bytes(),
program_id.as_ref(),
mint_info.key.as_ref(),
];
let (metadata_key, metadata_bump_seed) =
Pubkey::find_program_address(metadata_seeds, program_id);
let metadata_authority_signer_seeds = &[
PREFIX.as_bytes(),
program_id.as_ref(),
mint_info.key.as_ref(),
&[metadata_bump_seed],
];
if metadata_account_info.key != &metadata_key {
return Err(MetadataError::InvalidMetadataKey.into());
}
create_or_allocate_account_raw(
*program_id,
metadata_account_info,
rent_info,
system_account_info,
payer_account_info,
MAX_METADATA_LEN,
metadata_authority_signer_seeds,
)?;
let mut metadata = Metadata::from_account_info(metadata_account_info)?;
let compatible_data = data.to_v1();
assert_data_valid(
&compatible_data,
&update_authority_key,
&metadata,
allow_direct_creator_writes,
update_authority_info.is_signer,
false,
)?;
let mint_decimals = get_mint_decimals(mint_info)?;
metadata.mint = *mint_info.key;
metadata.key = Key::MetadataV1;
metadata.data = data.to_v1();
metadata.is_mutable = is_mutable;
metadata.update_authority = update_authority_key;
assert_valid_use(&data.uses, &None)?;
metadata.uses = data.uses;
assert_collection_update_is_valid(is_edition, &None, &data.collection)?;
metadata.collection = data.collection;
if add_token_standard {
let token_standard = if is_edition {
TokenStandard::NonFungibleEdition
} else if mint_decimals == 0 {
TokenStandard::FungibleAsset
} else {
TokenStandard::Fungible
};
metadata.token_standard = Some(token_standard);
} else {
metadata.token_standard = None;
}
puff_out_data_fields(&mut metadata);
let edition_seeds = &[
PREFIX.as_bytes(),
program_id.as_ref(),
metadata.mint.as_ref(),
EDITION.as_bytes(),
];
let (_, edition_bump_seed) = Pubkey::find_program_address(edition_seeds, program_id);
metadata.edition_nonce = Some(edition_bump_seed);
metadata.serialize(&mut *metadata_account_info.data.borrow_mut())?;
Ok(())
}
然后我们看看一共有哪些指令
1.
CreateMetadataAccountV2
2.
UpdateMetadataAccountV2
3.
UpdatePrimarySaleHappenedViaToken
4.
SignMetadata
5.
RemoveCreatorVerification
6.
CreateMasterEditionV3
7.
MintNewEditionFromMasterEditionViaToken
8.
ConvertMasterEditionV1ToV2
9.
MintNewEditionFromMasterEditionViaVaultProxy
10.
PuffMetadata
然后3个关于Collection的
VerifyCollection
SetAndVerifyCollection
UnverifyCollection
然后
Utilize
然后4个关于Authority的
然后2个关于代理账户DelegatedAccount的
然后我们看一下api文档
那么主要的就是
1.创建账户
2.更新账户
3.创建主版本
4.sign metadata
5.puff metadata
6.utilize
然后我们来看看主要方法
1.CreateMetadataAccountV2
Create Metadata object.
2.UpdateMetadataAccountV2
Update a Metadata with is_mutable as a parameter
3.CreateMasterEditionV3
/// Register a Metadata as a Master Edition V2, which means Edition V2s can be minted. /// Henceforth, no further tokens will be mintable from this primary mint. Will throw an error if more than one /// token exists, and will throw an error if less than one token exists in this primary mint.
4.SignMetadata
Sign a piece of metadata that has you as an unverified creator so that it is now verified.
5.PuffMetadata
/// Puff a Metadata - make all of it's variable length fields (name/uri/symbol) a fixed length using a null character /// so that it can be found using offset searches by the RPC to make client lookups cheaper.
6.Utilize
/// Utilize or Use an NFT , burns the NFT and returns the lamports to the update authority if the use method is burn and its out of uses. /// Use Authority can be the Holder of the NFT, or a Delegated Use Authority.