当前位置: 首页 > 工具软件 > Solana > 使用案例 >

150-Solana入门(十四)- 创建初始化Mint

田志尚
2023-12-01

今天来看一个很重要的问题

就是创建账户,初始化Mint,创建Token账户

我们先来看客户端中的tx

    const mint_tx = new anchor.web3.Transaction().add(
        anchor.web3.SystemProgram.createAccount({
            fromPubkey: provider.wallet.publicKey,
            newAccountPubkey: mintKey.publicKey,
            space: MINT_SIZE,
            programId: TOKEN_PROGRAM_ID,
            lamports,
        }),
        createInitializeMintInstruction(
            mintKey.publicKey,
            0,
            provider.wallet.publicKey,
            provider.wallet.publicKey,
        ),
        createAssociatedTokenAccountInstruction(
            provider.wallet.publicKey,
            nftTokenAccount,
            provider.wallet.publicKey,
            mintKey.publicKey
        )
    );
    const res = await program.provider.sendAndConfirm(mint_tx, [mintKey]);

那么我们需要把

createAccount
createInitializeMintInstruction
createAssociatedTokenAccountInstruction

这三个指令放到合约中去调用

试试看吧

试了很久很久

试了很多很多很多很多次

算是成功了一半

invoke的方式或者是anchor cpi的方式

分开调用的情况下都是成功的

但是合在一起就是不成功

真的很头疼

先看看invoke的方式

use anchor_lang::prelude::*;
use anchor_lang::solana_program;
use anchor_spl::token::spl_token;

use crate::solana_program::program::invoke;

declare_id!("HzMAyAPXaDKvtApQVqz1CSL8vHKRxF3FiM86WraCHgSs");

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

    pub fn create(
        ctx: Context<Create>,
        lamports: u64,
        space: u64,
    ) -> Result<()> {
        let account_infos = vec![
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.from.to_account_info(),
            ctx.accounts.to.to_account_info(),
        ];
        invoke(
            &solana_program::system_instruction::create_account(
                &ctx.accounts.from.key(),
                &ctx.accounts.to.key(),
                lamports,
                space,
                &ctx.accounts.token_program.key(),
            ),
            account_infos.as_slice(),
        )?;

        Ok(())
    }

    pub fn init_mint(
        ctx: Context<InitMint>,
    ) -> Result<()> {
        let account_infos = vec![
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.rent.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.freeze_authority.to_account_info(),
        ];
        invoke(
            &spl_token::instruction::initialize_mint(
                ctx.accounts.token_program.key,
                ctx.accounts.mint.key,
                ctx.accounts.authority.key,
                Some(ctx.accounts.freeze_authority.key),
                9,
            )?,
            account_infos.as_slice(),
        )?;

        Ok(())
    }

    pub fn create_init_01(
        ctx: Context<CreateInit01>,
        lamports: u64,
        space: u64,
    ) -> Result<()> {
        msg!("Create Account");
        let account_infos = vec![
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.from.to_account_info(),
            ctx.accounts.to.to_account_info(),
        ];
        invoke(
            &solana_program::system_instruction::create_account(
                &ctx.accounts.from.key(),
                &ctx.accounts.to.key(),
                lamports,
                space,
                &ctx.accounts.token_program.key(),
            ),
            account_infos.as_slice(),
        )?;

        msg!("Initialize Mint");
        let account_infos = vec![
            ctx.accounts.system_program.to_account_info(),
            ctx.accounts.token_program.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.rent.to_account_info(),
            ctx.accounts.authority.to_account_info(),
            ctx.accounts.freeze_authority.to_account_info(),
        ];
        invoke(
            &spl_token::instruction::initialize_mint(
                ctx.accounts.token_program.key,
                ctx.accounts.mint.key,
                ctx.accounts.authority.key,
                Some(ctx.accounts.freeze_authority.key),
                9,
            )?,
            account_infos.as_slice(),
        )?;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Create<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub from: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub to: AccountInfo<'info>,


    pub signer: Signer<'info>,
}

#[derive(Accounts)]
pub struct InitMint<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub mint: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub authority: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub freeze_authority: AccountInfo<'info>,


    pub signer: Signer<'info>,
}

#[derive(Accounts)]
pub struct CreateInit01<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub mint: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub authority: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub freeze_authority: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub from: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub to: AccountInfo<'info>,

    pub signer: Signer<'info>,
}
 

然后是anchro cpi的方式

use anchor_lang::prelude::*;
use anchor_lang::system_program::{create_account, CreateAccount};
use anchor_spl::token::{initialize_mint, InitializeMint};

declare_id!("HzMAyAPXaDKvtApQVqz1CSL8vHKRxF3FiM86WraCHgSs");

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

    pub fn create(
        ctx: Context<Create>,
        lamports: u64,
        space: u64,
    ) -> Result<()> {
        let cpi_accounts = CreateAccount {
            from: ctx.accounts.from.to_account_info(),
            to: ctx.accounts.to.to_account_info(),
        };
        let cpi_program = ctx.accounts.system_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
        create_account(cpi_ctx, lamports, space, ctx.accounts.token_program.key)?;

        Ok(())
    }

    pub fn init_mint(
        ctx: Context<InitMint>,
    ) -> Result<()> {
        let cpi_accounts = InitializeMint {
            mint: ctx.accounts.mint.to_account_info(),
            rent: ctx.accounts.rent.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
        initialize_mint(cpi_ctx, 9, ctx.accounts.authority.key, None)?;

        Ok(())
    }

    pub fn create_init_01(
        ctx: Context<CreateInit01>,
        lamports: u64,
        space: u64,
    ) -> Result<()> {
        msg!("Create Account");
        let cpi_accounts = CreateAccount {
            from: ctx.accounts.authority.to_account_info(),
            to: ctx.accounts.mint.to_account_info(),
        };
        let cpi_program = ctx.accounts.system_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
        create_account(cpi_ctx, lamports, space, ctx.accounts.token_program.key)?;

        msg!("Initialize Mint");
        let cpi_accounts = InitializeMint {
            mint: ctx.accounts.mint.to_account_info(),
            rent: ctx.accounts.rent.to_account_info(),
        };
        let cpi_program = ctx.accounts.token_program.to_account_info();
        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
        initialize_mint(cpi_ctx, 9, ctx.accounts.authority.key, None)?;

        Ok(())
    }
}

#[derive(Accounts)]
pub struct Create<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub from: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub to: AccountInfo<'info>,

    #[account(mut)]
    pub signer: Signer<'info>,
}

#[derive(Accounts)]
pub struct InitMint<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub mint: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub authority: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub freeze_authority: AccountInfo<'info>,

    #[account(mut)]
    pub signer: Signer<'info>,
}

#[derive(Accounts)]
pub struct CreateInit01<'info> {
    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_program: AccountInfo<'info>,
    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,

    #[account(mut)]
    pub mint: Signer<'info>,

    #[account(mut)]
    pub authority: Signer<'info>,
}

但是我用纯原生rust合约试了一下

是成功的

pub fn process_init(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
) -> ProgramResult {
    let account_info_iter = &mut accounts.iter();
    let authority_info = next_account_info(account_info_iter)?;
    let signer_info = next_account_info(account_info_iter)?;
    let mint_info = next_account_info(account_info_iter)?;
    let token_program_info = next_account_info(account_info_iter)?;
    let rent_info = next_account_info(account_info_iter)?;
    let system_info = next_account_info(account_info_iter)?;

    assert_signer(&signer_info)?;
    let size = 82;
    let rent = &Rent::from_account_info(&rent_info)?;
    let required_lamports = rent.minimum_balance(size);

    
    msg!("create_account create");
    invoke(
        &system_instruction::create_account(
            signer_info.key,
            mint_info.key,
            required_lamports,
            size as u64,
            token_program_info.key,
        ),
        &[signer_info.clone(), mint_info.clone()],
    )?;
    msg!("initialize_mint");
    invoke(
        &initialize_mint(
            token_program_info.key,
            mint_info.key,
            authority_info.key,
            Some(authority_info.key),
            9,
        )?,
        &[authority_info.clone(), mint_info.clone(),rent_info.clone(),token_program_info.clone(),],
    )?;

    msg!("initialize_mint::{:?} complete",mint_info.key.clone());

    Ok(())
}

相比较起来

原生的和anchor中调用invoke

已经几乎是一一对应了

但是原生成功,anchor失败

我真的很无语

 类似资料: