Edition

Overview

In Metaplex, an NFT edition refers to a copy or a replica of an original NFT, known as a "Master Edition." This concept is somewhat similar to creating limited or unlimited prints of a piece of art in the traditional art world, where each print is numbered and can be sold individually.

Key Concepts:

  1. Master Edition: The original NFT that holds metadata, including the total number of editions allowed (if any). It represents the "first" or "original" piece.
  1. Editions: These are copies or prints of the Master Edition. Each edition is a unique token but shares the same metadata as the Master Edition, except for a unique edition number.

Use Cases:

  • Limited Editions: If an artist wants to release a limited number of prints of their artwork, they can create a Master Edition and specify the number of editions allowed. Collectors can then purchase these editions, each with its own unique edition number.
  • Unlimited Editions: If the artist does not want to limit the number of copies, they can create an unlimited edition, allowing for continuous minting of editions.

Tx

Instruction

We can use MetadataInstruction::Print to create print NFT of certain original NFT.
/// --- programs/token-metadata/program/src/instruction/mod.rs --- pub enum MetadataInstruction { /// ... /// Given a token account containing the master edition token to prove authority, and a brand new non-metadata-ed mint with one token /// make a new Metadata + Edition that is a child of the master edition denoted by this authority token. /// Account index 18, holder_delegate_record, is optional and only used for escrowless edition printing. It is fetched from the remaining accounts. #[account(0, writable, name="edition_metadata", desc="New Metadata key (pda of ['metadata', program id, mint id])")] #[account(1, writable, name="edition", desc="New Edition (pda of ['metadata', program id, mint id, 'edition'])")] #[account(2, writable, name="edition_mint", desc="Mint of new token - THIS WILL TRANSFER AUTHORITY AWAY FROM THIS KEY")] #[account(3, name="edition_token_account_owner", desc="Owner of the token account of new token")] #[account(4, writable, name="edition_token_account", desc="Token account of new token")] #[account(5, signer, name="edition_mint_authority", desc="Mint authority of new mint")] #[account(6, optional, writable, name="edition_token_record", desc="Token record account")] #[account(7, writable, name="master_edition", desc="Master Record Edition V2 (pda of ['metadata', program id, master metadata mint id, 'edition'])")] #[account(8, writable, name="edition_marker_pda", desc="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).")] #[account(9, signer, writable, name="payer", desc="payer")] #[account(10, optional_signer, name="master_token_account_owner", desc="owner of token account containing master token")] #[account(11, name="master_token_account", desc="token account containing token from master metadata mint")] #[account(12, name="master_metadata", desc="Master record metadata account")] #[account(13, name="update_authority", desc="The update authority of the master edition.")] #[account(14, name="spl_token_program", desc="Token program")] #[account(15, name="spl_ata_program", desc="SPL Associated Token Account program")] #[account(16, name="sysvar_instructions", desc="Instructions sysvar account")] #[account(17, name="system_program", desc="System program")] // #[account(18, optional, name="holder_delegate_record", desc="The Delegate Record authorizing escrowless edition printing")] // #[account(19, optional, signer, name="delegate", desc="The authority printing the edition for a delegated print")] #[args(initialize_mint: bool)] Print(PrintArgs), /// ... }

Execution

/// --- programs/token-metadata/program/src/processor/metadata/print.rs --- pub fn print<'a>( program_id: &'a Pubkey, accounts: &'a [AccountInfo<'a>], args: PrintArgs, ) -> ProgramResult { match args { PrintArgs::V1 { .. } => print_v1(program_id, accounts, args), PrintArgs::V2 { .. } => print_v2(program_id, accounts, args), } } pub fn print_v1<'a>( program_id: &'a Pubkey, accounts: &'a [AccountInfo<'a>], args: PrintArgs, ) -> ProgramResult { let context = Print::to_context(accounts)?; print_logic(program_id, context, args, None, None) } pub fn print_v2<'a>( program_id: &'a Pubkey, accounts: &'a [AccountInfo<'a>], args: PrintArgs, ) -> ProgramResult { let context = Print::to_context(&accounts[0..18])?; if accounts.len() < 19 { return Err(ProgramError::NotEnoughAccountKeys); } let holder_delegate_record_info = if accounts[18].key == &crate::ID { None } else { Some(&accounts[18]) }; let delegate_info = if accounts.len() < 20 || accounts[19].key == &crate::ID { None } else { Some(&accounts[19]) }; print_logic( program_id, context, args, holder_delegate_record_info, delegate_info, ) }

Reference

  1. https://developers.metaplex.com/token-metadata/print