Solana[part13]_Anchor实战:为用户Mint Spl TOKEN

Solana[part13]_Anchor实战:为用户Mint Spl TOKEN

该部分代码见:https://github.com/SoniaChan33/anchor_social/commit/5abd954500f2926d999ac644c18a97c91cde9fb6

createLike指令添加需要的account

/anchor_social/src/instructions/tweet.rs

#[derive(Accounts)]
pub struct CreateLike<'info> {
    #[account(
        mut,
        seeds = [b"mint_v3",],
        bump,
    )]
    pub mint_account: Account<'info, Mint>,

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

    /// CHECK : THIS IS AUTHOR WALLET
    pub author_wallet: AccountInfo<'info>,

    #[account(
        init,
        payer = authority,
        space = 8 + Like::INIT_SPACE,
        seeds = [
            Like::SEED_PREFIX.as_bytes().as_ref(),
            profile.key().as_ref(),
            tweet.key().as_ref()
        ],
        bump
    )]
    pub like: Account<'info, Like>,

    #[account(mut)]
    pub tweet: Account<'info, Tweet>,


    #[account(mut, seeds = [Profile::SEED_PREFIX.as_bytes(), authority.key().as_ref()], bump)]
    pub profile: Account<'info, Profile>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,

    pub associated_token_program: Program<'info, AssociatedToken>,

    pub token_program: Program<'info, Token>, // 新增的Token程序字段
}

tweet结构体修改

#[account]
#[derive(InitSpace)]
pub struct Tweet {
    #[max_len(50)]
    pub body: String,

    pub like_count: u64,
    pub author: Pubkey,
}
impl Tweet {
    pub const SEED_PREFIX: &'static str = "tweet";

    pub fn new(body: String, author: Pubkey) -> Self {
        Self {
            body,
            like_count: 0,
            author,
        }
    }
}

添加author属性记录要mint to的author token account 地址

同时需要修改create_tweet函数的细节:

pub fn create_tweet(ctx: Context<CreateTweet>, body: String) -> Result<()> {
    let profile = &mut ctx.accounts.profile;
    profile.tweet_count += 1;
    let tweet = Tweet::new(body, ctx.accounts.tweet.key()); // 这里添加tweet的地址
    ctx.accounts.tweet.set_inner(tweet.clone());
    Ok(())
}

修改createLike方法

pub fn create_like(ctx: Context<CreateLike>) -> Result<()> {
    let tweet = &mut ctx.accounts.tweet;
    tweet.like_count += 1;

    let like = Like::new(ctx.accounts.profile.key(), tweet.key());
    ctx.accounts.like.set_inner(like);
    // 打印mint_account的地址
    msg!("mint_account: {}", ctx.accounts.mint_account.key());
    msg!(
        "author_token_account: {}",
        ctx.accounts.author_token_account.key()
    );

    mint_to(
        CpiContext::new_with_signer(
            ctx.accounts.token_program.to_account_info(),
            MintTo {
                mint: ctx.accounts.mint_account.to_account_info(),
                to: ctx.accounts.author_token_account.to_account_info(),
                authority: ctx.accounts.mint_account.to_account_info(),
            },
            &[&[b"mint_v3", &[ctx.bumps.mint_account]]],
        ),
        100,
    )?;
    Ok(())
}

关键参数解析:

  • CpiContext::new_with_signer:创建跨程序调用(CPI)上下文,因为铸造代币需要调用 Solana 的 Token 程序(token_program)。

  • MintTo

    结构体:指定铸造相关的账户:

    • mint:代币的铸造账户(mint_account),负责生成新代币。
    • to:接收代币的账户(author_token_account,推文作者的代币账户)。
    • authority:铸造权限的拥有者(这里是mint_account自身,因为该账户的权限通过种子验证)。
  • 签名种子&[&[b"mint_v3", &[ctx.bumps.mint_account]]]:用于验证mint_account的权限(该账户是通过b"mint_v3"种子和 bump 值创建的,因此需要用相同种子证明有权限铸造代币)。

  • 最后一个参数100:指定铸造的代币数量(向作者账户铸造 100 个代币)。

api重新调用这部分代码

// 创建推文
const [pda, r3] = await createTweet(defaultWallet, "Hello, world!");

const r4 = await getTweet(defaultWallet, pda);
console.log("defaultWallet public key:", defaultWallet.publicKey);

console.log(r4);

// 创建点赞
const visitorPublicKey = visitorWallet.publicKey;
console.log("Visitor public key:", visitorPublicKey.toString());
const r5 = await createLike(visitorWallet, pda);
console.log("Like created:", r5);

const r6 = await getTweet(defaultWallet, pda);
console.log(r6);

结果校验

  anchor_social git:(main) anchor run api
yarn run v1.22.18
warning ../package.json: No license field
$ /Users/tinachan/anchor_social/node_modules/.bin/ts-node app/index.ts
defaultWallet public key: PublicKey [PublicKey(FcKkQZRxD5P6JwGv58vGRAcX3CkjbX8oqFiygz6ohceU)] {
  _bn: <BN: d91024e709f54d65b29c9328658d06a488414c4cabc36522130c330322428769>
}
{
  body: 'Hello, world!',
  likeCount: <BN: 0>,
  author: PublicKey [PublicKey(BiQgNLwkejkdYyvbSSCjKhTsdK6tmn6YZiXhApX88L1q)] {
    _bn: <BN: 9f3074c28783b31efe51bdc42e5a0a6a8c2314d017da6a8ed713ccecd1aee164>
  }
}
Visitor public key: 7rQKPb1bPLS4xU93a43GYmBK7MfY3ChSTSVfA8fcxbRF
Like created: 59rjviQxEK68USP6VfPjqpciwKNcf98jTUpv7CBWEdFqNbAvh9FBTwH3RCcwviK8Wu92G3WACgwv6rafsWgitWDT
{
  body: 'Hello, world!',
  likeCount: <BN: 1>,
  author: PublicKey [PublicKey(BiQgNLwkejkdYyvbSSCjKhTsdK6tmn6YZiXhApX88L1q)] {
    _bn: <BN: 9f3074c28783b31efe51bdc42e5a0a6a8c2314d017da6a8ed713ccecd1aee164>
  }
}
✨  Done in 2.45s.

成功后查看author token account的账户

image-20250819222538906