use { borsh::{BorshDeserialize, BorshSerialize}, mpl_token_metadata::instruction as mpl_instruction, solana_program::{ account_info::{next_account_info, AccountInfo}, entrypoint::ProgramResult, msg, program::{invoke, invoke_signed}, program_pack::Pack, pubkey::Pubkey, rent::Rent, system_instruction, sysvar::Sysvar, }, spl_token::{instruction as token_instruction, state::Mint}, }; use crate::state::MintAuthorityPda; #[derive(BorshSerialize, BorshDeserialize, Debug)] pub struct CreateTokenArgs { pub nft_title: String, pub nft_symbol: String, pub nft_uri: String, } pub fn create_token( program_id: &Pubkey, accounts: &[AccountInfo], args: CreateTokenArgs, ) -> ProgramResult { let accounts_iter = &mut accounts.iter(); let mint_account = next_account_info(accounts_iter)?; let mint_authority = next_account_info(accounts_iter)?; let metadata_account = next_account_info(accounts_iter)?; let payer = next_account_info(accounts_iter)?; let rent = next_account_info(accounts_iter)?; let system_program = next_account_info(accounts_iter)?; let token_program = next_account_info(accounts_iter)?; let token_metadata_program = next_account_info(accounts_iter)?; let (mint_authority_pda, bump) = Pubkey::find_program_address(&[MintAuthorityPda::SEED_PREFIX.as_bytes()], program_id); assert!(&mint_authority_pda.eq(mint_authority.key)); // First create the account for the Mint // msg!("Creating mint account..."); msg!("Mint: {}", mint_account.key); invoke( &system_instruction::create_account( payer.key, mint_account.key, (Rent::get()?).minimum_balance(Mint::LEN), Mint::LEN as u64, token_program.key, ), &[ mint_account.clone(), payer.clone(), system_program.clone(), token_program.clone(), ], )?; // Now initialize that account as a Mint (standard Mint) // msg!("Initializing mint account..."); msg!("Mint: {}", mint_account.key); invoke( &token_instruction::initialize_mint( token_program.key, mint_account.key, mint_authority.key, Some(mint_authority.key), 0, // 0 Decimals for the NFT standard )?, &[ mint_account.clone(), mint_authority.clone(), token_program.clone(), rent.clone(), ], )?; // Now create the account for that Mint's metadata // msg!("Creating metadata account..."); msg!("Metadata account address: {}", metadata_account.key); invoke_signed( &mpl_instruction::create_metadata_accounts_v3( *token_metadata_program.key, *metadata_account.key, *mint_account.key, *mint_authority.key, *payer.key, *mint_authority.key, args.nft_title, args.nft_symbol, args.nft_uri, None, 0, true, false, None, None, None, ), &[ metadata_account.clone(), mint_account.clone(), mint_authority.clone(), payer.clone(), token_metadata_program.clone(), rent.clone(), ], &[&[MintAuthorityPda::SEED_PREFIX.as_bytes(), &[bump]]], )?; msg!("Token mint created successfully."); Ok(()) }