Skip to content

Instantly share code, notes, and snippets.

@liushooter
Created October 26, 2023 05:25
Show Gist options
  • Save liushooter/995c30c6736c4dc3154b4096f7ef9f6a to your computer and use it in GitHub Desktop.
Save liushooter/995c30c6736c4dc3154b4096f7ef9f6a to your computer and use it in GitHub Desktop.

Revisions

  1. liushooter created this gist Oct 26, 2023.
    137 changes: 137 additions & 0 deletions solana-nft-anchor.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,137 @@
    use anchor_lang::prelude::*;
    use anchor_spl::{
    associated_token::AssociatedToken,
    metadata::{
    create_master_edition_v3, create_metadata_accounts_v3, CreateMasterEditionV3,
    CreateMetadataAccountsV3, Metadata,
    },
    token::{mint_to, Mint, MintTo, Token, TokenAccount},
    };
    use mpl_token_metadata::{
    pda::{find_master_edition_account, find_metadata_account},
    state::DataV2,
    };

    declare_id!("");

    #[program]
    pub mod solana_nft_anchor {
    use super::*;

    // Create new token mint with PDA as mint authority
    pub fn init_nft(
    ctx: Context<InitNFT>,
    name: String,
    symbol: String,
    uri: String,
    ) -> Result<()> {
    // create mint account
    let cpi_context = CpiContext::new(
    ctx.accounts.token_program.to_account_info(),
    MintTo {
    mint: ctx.accounts.mint.to_account_info(),
    to: ctx.accounts.associated_token_account.to_account_info(),
    authority: ctx.accounts.signer.to_account_info(),
    },
    );

    mint_to(cpi_context, 1)?;

    // create metadata account
    let cpi_context = CpiContext::new(
    ctx.accounts.token_metadata_program.to_account_info(),
    CreateMetadataAccountsV3 {
    metadata: ctx.accounts.metadata_account.to_account_info(),
    mint: ctx.accounts.mint.to_account_info(),
    mint_authority: ctx.accounts.signer.to_account_info(),
    update_authority: ctx.accounts.signer.to_account_info(),
    payer: ctx.accounts.signer.to_account_info(),
    system_program: ctx.accounts.system_program.to_account_info(),
    rent: ctx.accounts.rent.to_account_info(),
    },
    );

    // On-chain token metadata for the mint
    let data_v2 = DataV2 {
    name: name,
    symbol: symbol,
    uri: uri,
    seller_fee_basis_points: 0,
    creators: None,
    collection: None,
    uses: None,
    };

    create_metadata_accounts_v3(
    cpi_context, // cpi context
    data_v2, // token metadata
    false, // is_mutable
    true, // update_authority_is_signer
    None, // collection details
    )?;

    //create master edition account
    let cpi_context = CpiContext::new(
    ctx.accounts.token_metadata_program.to_account_info(),
    CreateMasterEditionV3 {
    edition: ctx.accounts.master_edition_account.to_account_info(),
    mint: ctx.accounts.mint.to_account_info(),
    update_authority: ctx.accounts.signer.to_account_info(),
    mint_authority: ctx.accounts.signer.to_account_info(),
    payer: ctx.accounts.signer.to_account_info(),
    metadata: ctx.accounts.metadata_account.to_account_info(),
    token_program: ctx.accounts.token_program.to_account_info(),
    system_program: ctx.accounts.system_program.to_account_info(),
    rent: ctx.accounts.rent.to_account_info(),
    },
    );

    create_master_edition_v3(cpi_context, None)?;

    Ok(())
    }
    }

    #[derive(Accounts)]
    pub struct InitNFT<'info> {
    /// CHECK: ok, we are passing in this account ourselves
    #[account(mut, signer)]
    pub signer: AccountInfo<'info>,

    #[account(
    init,
    payer = signer,
    mint::decimals = 0,
    mint::authority = signer.key(),
    mint::freeze_authority = signer.key(),
    )]
    pub mint: Account<'info, Mint>,

    #[account(
    init_if_needed,
    payer = signer,
    associated_token::mint = mint,
    associated_token::authority = signer
    )]
    pub associated_token_account: Account<'info, TokenAccount>,

    /// CHECK - address
    #[account(
    mut,
    address=find_metadata_account(&mint.key()).0,
    )]
    pub metadata_account: AccountInfo<'info>,

    /// CHECK: address
    #[account(
    mut,
    address=find_master_edition_account(&mint.key()).0,
    )]
    pub master_edition_account: AccountInfo<'info>,

    pub token_program: Program<'info, Token>,
    pub associated_token_program: Program<'info, AssociatedToken>,
    pub token_metadata_program: Program<'info, Metadata>,
    pub system_program: Program<'info, System>,
    pub rent: Sysvar<'info, Rent>,
    }