You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Localnet用Anchor测试Metaplex指令?遇执行账户错误

问题1:Localnet测试Metaplex Metadata程序部署错误

你遇到的instruction expected an executable account错误确实是因为Localnet默认未部署Metaplex Metadata程序(固定地址为metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s),需要手动将其加载到本地测试节点,具体两种方法:

  • 方法一:启动测试节点时直接克隆Devnet的Metadata程序
    运行命令:

    solana-test-validator --url https://api.devnet.solana.com --clone metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s
    

    该命令会从Devnet拉取Metadata程序并部署到本地节点,启动后即可正常调用create_metadata_accounts_v3指令。

  • 方法二:Metaplex CLI部署(需先安装Metaplex CLI)
    先启动本地节点:

    solana-test-validator
    

    再执行部署命令:

    metaplex metadata deploy --cluster localnet
    

同时要确保Anchor程序中正确引用Metadata程序ID,示例代码片段:

use anchor_spl::metadata::{create_metadata_accounts_v3, Metadata, MetadataAccount};
use anchor_spl::token::Mint;

declare_id!("你的程序ID");

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

    pub fn mint_nft(ctx: Context<MintNft>, name: String, symbol: String, uri: String) -> Result<()> {
        create_metadata_accounts_v3(
            ctx.accounts.metadata_program.to_account_info(),
            ctx.accounts.metadata.to_account_info(),
            ctx.accounts.mint.to_account_info(),
            ctx.accounts.mint_authority.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.update_authority.to_account_info(),
            name,
            symbol,
            uri,
            None,
            0,
            true,
            false,
            None,
            None,
        )?;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct MintNft<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
    pub mint_authority: Signer<'info>,
    #[account(
        init,
        payer = payer,
        mint::decimals = 0,
        mint::authority = mint_authority,
        mint::freeze_authority = mint_authority,
    )]
    pub mint: Account<'info, Mint>,
    #[account(
        init,
        payer = payer,
        seeds = [b"metadata", metadata_program.key().as_ref(), mint.key().as_ref()],
        bump,
        space = Metadata::LEN,
    )]
    pub metadata: Account<'info, Metadata>,
    /// CHECK: 验证为Metaplex Metadata程序固定地址
    #[account(address = metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s)]
    pub metadata_program: UncheckedAccount<'info>,
    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
    pub rent: Sysvar<'info, Rent>,
}
问题2:Devnet重复部署需修改程序ID的问题

Anchor默认支持程序升级,无需每次重新部署新程序生成新ID,解决方法如下:

  • 使用anchor upgrade升级已有程序
    确保Anchor.toml中programs.devnet下的程序ID为之前部署的固定ID,然后运行升级命令:

    anchor upgrade --program-id 你的程序ID target/deploy/你的程序名.so
    

    升级后程序ID不变,已初始化的账户可继续使用。

  • 测试脚本复用已初始化账户
    在测试代码中通过try_find_program_address查找已存在的集合/管理员账户,避免重复创建,示例TypeScript代码片段:

    import * as anchor from "@coral-xyz/anchor";
    import { Program } from "@coral-xyz/anchor";
    import { NftCollection } from "../target/types/nft_collection";
    
    describe("nft-collection", () => {
      const provider = anchor.AnchorProvider.env();
      anchor.setProvider(provider);
    
      // 直接指定已部署的程序ID
      const program = new Program<NftCollection>(
        require("../target/idl/nft_collection.json"),
        new anchor.web3.PublicKey("你的程序ID"),
        provider
      );
    
      // 尝试查找已存在的集合账户
      const [collectionAccount] = anchor.web3.PublicKey.findProgramAddressSync(
        [Buffer.from("collection"), provider.wallet.publicKey.toBuffer()],
        program.programId
      );
    
      // 测试逻辑:如果账户已初始化则直接使用,否则创建
      // ...
    });
    
  • 避免不必要的重新部署
    只有当程序结构发生重大变更(如账户结构修改导致无法兼容升级)时,才需要重新部署新程序,否则优先使用升级流程。

内容的提问来源于stack exchange,提问作者Lê Văn Anh Tú

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:33:11