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

如何在非Anchor的JS代码中获取Anchor账户的鉴别器?

问题:如何在不引入Anchor库的JS代码中生成Anchor账户/指令的鉴别器

我有如下Anchor合约代码:

use anchor_lang::prelude::*;

declare_id!("kek");

#[constant]
pub const MEDIA_TAG: &[u8] = b"MEDIA_STATE";

#[account]
#[derive(Default)]
pub struct MediaState {
    pub authority: Pubkey,
    pub name: String,
}

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

    pub fn create_media(ctx: Context<CreateMedia>, name: String) -> Result<()> {
        msg!("Media name: {}", name);

        let media_state = &mut ctx.accounts.media_state;

        media_state.authority = ctx.accounts.authority.key();
        media_state.name = name;

        msg!("Media created");
        Ok(())
    }
}

#[derive(Accounts)]
#[instruction()]
pub struct CreateMedia<'info> {
    #[account(mut)]
    pub authority: Signer<'info>,

    #[account(
        init,
        seeds = [MEDIA_TAG, authority.key().as_ref()],
        bump,
        payer = authority,
        space = 8 + std::mem::size_of::<MediaState>(),
    )]
    pub media_state: Box<Account<'info, MediaState>>,

    pub system_program: Program<'info, System>,
}

我希望在不引入Anchor库的JavaScript代码中,获取MediaState账户或CreateMedia指令的鉴别器,用于getProgramAccounts的过滤查询:

const publisher = new web3.PublicKey(
    "kek"
);
const connection = new web3.Connection(web3.clusterApiUrl("devnet"));

const accounts = await connection.getProgramAccounts(publisher, {
    filters: [{ memcmp: { offset: 0, bytes: ?????????? } }],
});

目前我通过SolanaPlayground的网络开发者工具拿到了可用的鉴别器值"FtoqZ3bt1he",但不知道如何自行生成该值,特此求助。


解决方案

1. 生成MediaState账户鉴别器

Anchor的账户鉴别器是对账户结构体名称按固定规则哈希后取前8字节得到的,具体步骤:

  • 构造字符串:account:MediaState(格式为account:结构体名称)
  • 对该字符串做SHA-256哈希
  • 取哈希结果的前8字节,再转成Base58编码

在JavaScript中可通过原生crypto模块和bs58包实现:

const crypto = require('crypto');
const bs58 = require('bs58');

// 生成MediaState账户鉴别器
const accountDiscriminator = crypto.createHash('sha256')
  .update(Buffer.from('account:MediaState'))
  .digest()
  .slice(0, 8);

console.log(bs58.encode(accountDiscriminator)); // 输出即为你拿到的"FtoqZ3bt1he"

2. 生成CreateMedia指令鉴别器

指令鉴别器的生成逻辑类似,规则是对指令的完整标识做哈希取前8字节:

  • 构造字符串:global:publisher:create_media(格式为global:模块名:方法名)
  • 对该字符串做SHA-256哈希
  • 取前8字节转Base58编码

代码实现:

const crypto = require('crypto');
const bs58 = require('bs58');

// 生成CreateMedia指令鉴别器
const instructionDiscriminator = crypto.createHash('sha256')
  .update(Buffer.from('global:publisher:create_media'))
  .digest()
  .slice(0, 8);

console.log(bs58.encode(instructionDiscriminator));

核心规则总结

  • 账户鉴别器:sha256("account:结构体名称")的前8字节,转Base58
  • 指令鉴别器:sha256("global:模块名:方法名")的前8字节,转Base58

生成后的值即可直接填入getProgramAccounts的memcmp.bytes字段中使用。


内容的提问来源于stack exchange,提问作者keker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:01:19