接口定义语言 (IDL) 文件提供了描述程序指令和账户的标准化 JSON 文件。此文件简化了链上程序与客户端应用程序集成的过程。
IDL 的主要优势:
- 标准化:提供一致的格式来描述程序的指令和帐户
- 客户端生成:用于生成与程序交互的客户端代码
该anchor build
命令生成一个位于 的 IDL 文件 /target/idl/<program-name>.json
。
下面的代码片段突出显示了程序、IDL 和客户端如何相互关联。
程序指令
IDL 中的数组instructions
直接对应于程序中定义的指令。它指定每条指令所需的帐户和参数。
- Program:下面的程序包含一条
initialize
指令,指定其所需的帐户和参数。 - 程序帐户:
accounts
IDL 中的数组对应于程序中用宏注释的结构体。#[account]
这些结构体定义了程序创建的账户中存储的数据。
use anchor_lang::prelude::*;
declare_id!("BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd");
#[program]
mod hello_anchor {
use super::*;
pub fn initialize(ctx: Context<Initialize>, data: u64) -> Result<()> {
ctx.accounts.new_account.data = data;
msg!("Changed data to: {}!", data);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init, payer = signer, space = 8 + 8)]
pub new_account: Account<'info, NewAccount>,
#[account(mut)]
pub signer: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[account]
pub struct NewAccount {
data: u64,
}
IDL
生成的 IDL 文件包含标准化 JSON 格式的指令,包括其名称、帐户、参数和鉴别器。
{
"address": "BYFW1vhC1ohxwRbYoLbAWs86STa25i9sD5uEusVjTYNd",
"metadata": {
"name": "hello_anchor",
"version": "0.1.0",
"spec": "0.1.0",
"description": "Created with Anchor"
},
"instructions": [
{
"name": "initialize",
"discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
"accounts": [
{
"name": "new_account",
"writable": true,
"signer": true
},
{
"name": "signer",
"writable": true,
"signer": true
},
{
"name": "system_program",
"address": "11111111111111111111111111111111"
}
],
"args": [
{
"name": "data",
"type": "u64"
}
]
}
],
"accounts": [
{
"name": "NewAccount",
"discriminator": [176, 95, 4, 118, 91, 177, 125, 232]
}
],
"types": [
{
"name": "NewAccount",
"type": {
"kind": "struct",
"fields": [
{
"name": "data",
"type": "u64"
}
]
}
}
]
}
Client
然后使用IDL文件生成与程序交互的客户端,简化调用程序指令的过程。
import * as anchor from "@coral-xyz/anchor";
import { Program, BN } from "@coral-xyz/anchor";
import { HelloAnchor } from "../target/types/hello_anchor";
import { Keypair } from "@solana/web3.js";
import assert from "assert";
describe("hello_anchor", () => {
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const wallet = provider.wallet as anchor.Wallet;
const program = anchor.workspace.HelloAnchor as Program<HelloAnchor>;
it("initialize", async () => {
// Generate keypair for the new account
const newAccountKp = new Keypair();
// Send transaction
const data = new BN(42);
const transactionSignature = await program.methods
.initialize(data)
.accounts({
newAccount: newAccountKp.publicKey,
signer: wallet.publicKey,
})
.signers([newAccountKp])
.rpc();
// Fetch the created account
const newAccount = await program.account.newAccount.fetch(
newAccountKp.publicKey,
);
console.log("Transaction signature: ", transactionSignature);
console.log("On-chain data is:", newAccount.data.toString());
assert(data.eq(newAccount.data));
});
});
鉴别器
Anchor 为程序中的每个指令和账户类型分配一个唯一的 8 字节鉴别符。这些鉴别符作为标识符来区分不同的指令或账户类型。
鉴别器是使用前缀的 Sha256 哈希的前 8 个字节与指令或帐户名称相结合生成的。从 Anchor v0.30 开始,这些鉴别器包含在 IDL 文件中。
请注意,使用 Anchor 时,您通常不需要直接与这些鉴别器交互。本节主要介绍如何生成和使用鉴别器。
instructions
指令鉴别器被程序用来决定在调用时要执行哪条具体指令。
当调用 Anchor 程序指令时,鉴别符将作为指令数据的前 8 个字节包含在内。此操作由 Anchor 客户端自动完成。
IDL
"instructions": [
{
"name": "initialize",
"discriminator": [175, 175, 109, 31, 13, 152, 155, 237],
...
}
]
accounts
账户鉴别器用于在反序列化链上数据时识别具体的账户类型,在账户创建时设置。
IDL
"accounts": [
{
"name": "NewAccount",
"discriminator": [176, 95, 4, 118, 91, 177, 125, 232]
}
]
指令的鉴别器是前缀的 Sha256 哈希的前 8 个字节global加上指令名称。
例如:
sha256("global:initialize")
十六进制输出:
af af 6d 1f 0d 98 9b ed d4 6a 95 07 32 81 ad c2 1b b5 e0 e1 d7 73 b2 fb bd 7a b5 04 cd d4 aa 30
前 8 个字节用作指令的鉴别符。
af = 175
af = 175
6d = 109
1f = 31
0d = 13
98 = 152
9b = 155
ed = 237
您可以在此处的Anchor 代码库中找到鉴别器生成的实现 ,该代码库在此处使用 。
总结:https://solana.com/docs/programs/anchor/idl
版权属于:区块链中文技术社区 / 转载原创者
本文链接:https://bcskill.com/index.php/archives/2116.html
相关技术文章仅限于相关区块链底层技术研究,禁止用于非法用途,后果自负!本站严格遵守一切相关法律政策!