一个简单的 Solana NFT 合约示例(一)

864 阅读1分钟
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Mint, TokenAccount, Transfer};

declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");

// 创建NFT合约
#[program]
mod nft {
    use solana_program::{
        account_info::{next_account_info, AccountInfo},
        entrypoint,
        entrypoint::ProgramResult,
        msg,
        program_error::ProgramError,
        pubkey::Pubkey,
    };
    use spl_token::{
        state::Account as TokenAccount,
        instruction::{initialize_account, initialize_mint, mint_to},
    };

    // 定义NFT合约结构体
    pub struct Processor;

    // 定义NFT合约处理方法
    impl Processor {
        // 初始化Mint和Account
        pub fn process(
            program_id: &Pubkey,
            accounts: &[AccountInfo],
            name: String,
            symbol: String,
            supply: u64,
        ) -> ProgramResult {
            // 通过accounts迭代器获取Mint的account信息、MintOwner的account信息、接收NFT的account信息
            let accounts_iter = &mut accounts.iter();
            let mint_info = next_account_info(accounts_iter)?;
            let mint_authority_info = next_account_info(accounts_iter)?;
            let destination_info = next_account_info(accounts_iter)?;

            // 验证MintOwner的签名
            if !mint_authority_info.is_signer {
                return Err(ProgramError::MissingRequiredSignature);
            }

            // 初始化Mint账户
            initialize_mint(program_id, mint_info, mint_authority_info, None, 0)?;

            // 初始化Account账户
            let account_info = next_account_info(accounts_iter)?;
            initialize_account(program_id, account_info, mint_info.key, mint_authority_info)?;

            // Mint指定数量的NFT并转账至Account账户
            mint_to(program_id, mint_info, destination_info, mint_authority_info, &[], supply)?;

            // 打印Mint和Account账户地址以及创建的NFT数量
            msg!("Mint account: {}", mint_info.key);
            msg!("Account account: {}", account_info.key);
            msg!("Number of tokens minted: {}", supply);

            // 返回成功结果
            Ok(())
        }
    }

    // 定义处理入口方法
    #[entrypoint]
    pub fn entry(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
        // 解析指令数据
        let (name, symbol, supply) = deserialize_input(instruction_data)?;

        // 调用处理方法
        Processor::process(program_id, accounts, name, symbol, supply)
    }

    // 解析指令数据
    fn deserialize_input(input: &[u8]) -> Result<(String, String, u64), ProgramError> {
        // 使用Solana SDK中的Serde库反序列化输入数据
        let (name, symbol, supply) = serde::Deserialize::deserialize(input)
            .map_err(|_| ProgramError::InvalidInstructionData)?;
        Ok((name, symbol, supply))
    }
}