Token2022 - 更新代币metadata
创建指令
在instructions
目录中添加update_token_metadata.rs
,并粘贴以下代码:
use anchor_lang::solana_program::program::invoke;
use anchor_lang::prelude::*;
use anchor_lang::solana_program::system_instruction;
use crate::constants::MINT_SEEDS;
use crate::errors::ErrorCode;
use crate::states::TokenMetadata;
use anchor_spl::token_2022::spl_token_2022;
use anchor_spl::token_interface::{token_metadata_update_field, Mint, Token2022, TokenMetadataUpdateField};
use spl_token_metadata_interface::state::Field;
#[derive(Accounts)]
#[instruction(metadata_params: TokenMetadata)]
pub struct UpdateTokenMetadata<'info> {
/// CHECK: Must be same as mint
#[account(mut)]
pub metadata: UncheckedAccount<'info>,
#[account(
seeds = [MINT_SEEDS.as_bytes(), metadata_params.name.as_bytes(), metadata_params.symbol.as_bytes()],
bump,
)]
pub mint: Box<InterfaceAccount<'info, Mint>>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token2022>,
}
impl<'info> UpdateTokenMetadata<'info> {
pub fn update_account_lamports_to_minimum_balance<'a>(
account: AccountInfo<'a>,
payer: AccountInfo<'a>,
system_program: AccountInfo<'a>,
) -> Result<()> {
let minimum_balance = Rent::get()?.minimum_balance(account.data_len());
let current_balance = account.get_lamports();
if minimum_balance > current_balance {
let extra_lamports = minimum_balance - current_balance;
invoke(
&system_instruction::transfer(payer.key, account.key, extra_lamports),
&[payer, account, system_program],
)?;
}
Ok(())
}
pub fn update_token_metadata(ctx: Context<UpdateTokenMetadata>, metadata_params: Box<TokenMetadata>) -> Result<()> {
require!(spl_token_2022::ID == ctx.accounts.token_program.key(), ErrorCode::WrongTokenProgram);
let seeds = &[MINT_SEEDS.as_bytes(), metadata_params.name.as_bytes(), metadata_params.symbol.as_bytes(), &[ctx.bumps.mint]];
let signer = [&seeds[..]];
let mint_account_info = ctx.accounts.mint.to_account_info();
let token_program_account_info = ctx.accounts.token_program.to_account_info();
let cpi_accounts = TokenMetadataUpdateField {
token_program_id: token_program_account_info.clone(),
metadata: mint_account_info.clone(), // metadata is same as mint
update_authority: mint_account_info.clone(),
};
let cpi_ctx = CpiContext::new_with_signer(token_program_account_info, cpi_accounts, &signer);
token_metadata_update_field(
cpi_ctx,
Field::Uri,
metadata_params.uri.clone()
)?;
Self::update_account_lamports_to_minimum_balance(
mint_account_info.clone(),
ctx.accounts.payer.to_account_info(),
ctx.accounts.system_program.to_account_info(),
)?;
Ok(())
}
}
在lib.rs中调用上面的指令
pub fn update_token_metadata(ctx: Context<UpdateTokenMetadata>, metadata_params: Box<TokenMetadata>) -> Result<()> {
UpdateTokenMetadata::update_token_metadata(ctx, metadata_params)
}
编译部署
anchor build && anchor deploy
编写测试代码