Chansol Lim
Chansol Lim

Reputation: 99

Need help on building a function that creates a new edition nft from a master edition nft

[image link to my code]

https://i.sstatic.net/UWtpj.png

I am currently writing a Solana Metaplex NFT program in Rust/Anchor-Solana, specifically working on writing a logic to create a edition NFT from a master edition NFT.

While invoking mpl_token_metadata::instruction::mint_new_edition_from_master_edition_via_token instruction, I found out that it requires both metadata and metadata_mint field as arguments. Whereas, on the metaplex documentation, it seems the instruction only requires the Master record metadata account.

Question:

Which account key, or value, should I put in to each of those fields(metadata and metadata_mint) and why?

Code:

pub fn create_new_edition_nft(
        ctx: Context<CreateNewEdition>,
        edition: u64,
    ) -> Result<()> {
        let edition_infos = vec![
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.new_metadata.to_account_info(),
            ctx.accounts.new_edition.to_account_info(),
            ctx.accounts.master_edition.to_account_info(),
            ctx.accounts.new_mint.to_account_info(),
            ctx.accounts.new_mint_authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.token_account_owner.to_account_info(),
            ctx.accounts.token_account.to_account_info(),
            ctx.accounts.new_metadata_update_authority.to_account_info(),
            ctx.accounts.metadata.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.rent.to_account_info(),
        ];
        msg!("Edition Account Infos Assigned");
        invoke(&mint_new_edition_from_master_edition_via_token(
            ctx.accounts.token_program.key(),ctx.accounts.new_metadata.key(),ctx.accounts.new_edition.key(), ctx.accounts.master_edition.key(), ctx.accounts.new_mint.key(),ctx.accounts.new_mint_authority.key(), ctx.accounts.payer.key(), ctx.accounts.token_account_owner.key(), ctx.accounts.token_account.key(), ctx.accounts.new_metadata_update_authority.key(), ctx.accounts.metadata.key(), ctx.accounts.metadata.key(), edition
        ), edition_infos.as_slice())?;

        msg!("A New Edition Nft Minted !!!");
        Ok(())
    }

#[derive(Accounts)]
pub struct CreateNewEdition<'info> {
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub new_metadata: UncheckedAccount<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub new_edition: UncheckedAccount<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub master_edition: UncheckedAccount<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub new_mint: UncheckedAccount<'info>,    
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub edition_mark_pda: UncheckedAccount<'info>,    
    #[account(mut)]
    pub new_mint_authority: Signer<'info>,
    #[account(mut)]
    pub payer: AccountInfo<'info>,
    // /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub token_account_owner: UncheckedAccount<'info>,
    // /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub token_account: UncheckedAccount<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub new_metadata_update_authority: UncheckedAccount<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub metadata: UncheckedAccount<'info>,    
    // #[account(mut)]
    pub token_program: Program<'info, Token>,
    pub system_program: Program<'info, System>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,
}

Documentation Reference:

Documentation for printing a new edition from a master edition:

https://docs.metaplex.com/programs/token-metadata/instructions#print-a-new-edition-from-a-master-edition

Upvotes: 1

Views: 513

Answers (1)

trust_nickol
trust_nickol

Reputation: 2114

The documentation on metaplex you are talking about is the documentation of the solana instructions but not the rust api. They are different. If you take a look at the rust code, you will see the differences.

The accounts described in the documentation match the accounts provided by the code:

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),
];

The variable metadata_mint you are talking about is used to calculate the address of the edition_mark_pda address on chain:

    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,
    );

When you compare this with the documentation, you will see what should be provided:

Edition pda to mark creation - will be checked for pre-existence. (pda of ['metadata', program id, master metadata mint id, 'edition', edition_number]) where edition_number is NOT the edition number you pass in args but actually edition_number = floor(edition/EDITION_MARKER_BIT_SIZE).

metadata := Master record metadata account

metadata_mint := master metadata mint id

Upvotes: 0

Related Questions