IDL 是接口定义语言(Interface Definition Language)的缩写。 在 Solana 上,IDL 是描述程序接口的 JSON 文件。它们允许区块链浏览器和用户解码程序指令、账户数据和程序错误,并提供以不同编程语言生成客户端的能力。
为什么 IDL 很重要
- 标准化 → 为程序接口提供统一的格式。
- 开发者体验 → 自动生成客户端 SDK。
- 可组合性 → 其他开发者无需阅读源代码即可与你的程序进行交互。
- 可读性 → 任何人都可以在区块链浏览器中读取程序指令和账户数据,而无需阅读程序源代码。
IDL 的用途
解码指令和账户数据
所有区块链浏览器都使用程序 IDL 来解码指令和账户数据。在此你可以看到 Solana Explorer UI 中
Anchor 0.30.1
和
Legacy IDL
的示例。在
这笔交易
中,你可以看到 2048 游戏的已解码指令,包括 pushInDirection 及其方向。
你可以通过使用 Solana JS 工具库 在 TypeScript 客户端中解码指令和账户数据。
解析 Anchor 事件或账户变更
你可以使用生成的 TypeScript 类型轻松订阅程序中的账户变更。
import { Connection } from "@solana/web3.js";const connection = new Connection("https://api.devnet.solana.com");// Fetch account onceconst account = await program.account.counter.fetch(counterPda);// Subscribe via websocket to account changesprogram.account.counter.subscribe(counterPda).on("change", (account) => {console.log("Account changed:", account);});// Or use decoder to decode any account or instruction dataconnection.onAccountChange(counterPda, (accInfo) => {console.log("Account changed:",program.coder.accounts.decode("counterData", account.data));});
例如,你可以在程序中触发 Anchor 事件,然后记录这些事件、将其写入数据库,或用它们向 Telegram 群组发送消息。
// Emit the purchase eventemit!(PurchaseMade {buyer: *ctx.accounts.signer.key,product_name: name,price,timestamp: Clock::get()?.unix_timestamp,table_number,receipt_id,telegram_channel_id: ctx.accounts.receipts.telegram_channel_id.clone(),store_name: ctx.accounts.receipts.store_name.clone(),receipts_account: ctx.accounts.receipts.key(),});
为此,你可以使用 Solana JS 工具库 来解析事件。这里有一个 示例实现, 它利用 Anchor 事件向 Telegram 群组发送消息。
解码交易
你也可以在客户端中使用 Solana JS 工具库 解码交易,这将为你提供整笔交易的类型化对象。
构建自己的客户端
使用 IDL,你可以用多种语言创建自己的客户端。只需找到你想交互的程序,下载其 IDL,然后即可用你偏好的语言生成客户端。
这里有一个如何用 TypeScript 生成客户端的示例。
Anchor 中的 IDL
如果你正在使用 Anchor 框架:
- 构建程序时会自动生成 IDL。
- IDL 文件位于
target/idl/<program>.json。 - TypeScript 类型生成于
target/types/<program>.ts。 - 程序地址存储在 IDL 中(
idl.address)。
anchor buildcat target/idl/counter.json
IDL 的结构剖析
以下是一个最简示例(Anchor v0.30+ 规范):
{"address": "6khKp4BeJpCjBY1Eh39ybiqbfRnrn2UzWeUARjQLXYRC","metadata": {"name": "counter","version": "0.1.0","spec": "0.1.0"},"instructions": [{"name": "increment","discriminator": [11, 18, 104, 9, 104, 174, 59, 33],"accounts": [{ "name": "counter", "writable": true }],"args": []}],"accounts": [{"name": "Counter","discriminator": [255, 176, 4, 245, 188, 253, 124, 25]}],"types": [{"name": "Counter","type": {"kind": "struct","fields": [{ "name": "count", "type": "u64" }]}}]}
- address:链上程序 ID。
- metadata:关于程序/接口的
{ name, version, spec, ... }信息。 - instructions:包含
accounts、args和discriminator的可调用方法。 - accounts:程序公开的账户类型(含判别器)。
- types:指令/账户引用的结构体/枚举/类型别名。
- events / errors / constants:事件、错误码和常量的可选定义。
注意:Anchor v0.30 引入了新的 IDL 规范。旧版 IDL(v0.30 之前)在顶层使用
name、version等字段,并在账户中使用isMut/isSigner。 你可以使用anchor idl convert转换旧版 IDL,或使用 Anchor v0.30+ 重新构建。如果你需要即时将旧版 IDL 转换为新规范,也可以使用这段 转换代码。 例如,如果你维护一个 Solana 区块链浏览器并希望保持向后兼容性,这将非常有用。
TypeScript 客户端
Anchor 还会自动为你生成 TypeScript 客户端。你可以在 target/types 文件夹中找到生成的客户端。
然后在你的客户端(TypeScript,v0.30+)中,你可以像这样轻松调用程序指令并获取账户:
import { AnchorProvider, Program } from "@coral-xyz/anchor";import idl from "./counter.json";const provider = AnchorProvider.local();const program = new Program(idl, provider);await program.methods.increment().rpc();
C# 客户端
要生成 C# 客户端,你可以使用以下命令:
cd programdotnet tool install Solana.Unity.Anchor.Tool <- run oncedotnet anchorgen -i target/idl/counter.json -o target/idl/Counter.cs
你可以在 Solana 游戏预设 或 游戏文档 中了解更多关于如何在 Unity 中使用 C# 客户端进行交互的内容。
Python 客户端
对于 Python,你可以使用 AnchorPy 库。
未来将通过 Codama 渲染器提供更多客户端生成器。
不使用 Anchor 的 IDL
并非所有程序都使用 Anchor 构建。 对于原生 Solana 程序:
- 一个名为 Codama 的工具目前正在开发中,用于通过宏从 Rust 生成 IDL,或通过转换 Anchor IDL 来生成。这里有一个进行中的
Codama 宏
示例,用于生成 Codama IDL。Codama 可将 Anchor/Shank IDL 转换为 Codama IDL。若要获取 Anchor IDL,请使用 Anchor 生成(或对旧版项目使用
anchor idl convert)。 - 在 Codama 宏完全就绪之前,你也可以使用 Metaplex Shank 生成 Shank IDL,然后将其转换为 Codama IDL。
- 你也可以手动编写 IDL(Anchor 或 Codama 格式),但这并不十分可靠。Cursor 等 AI 工具可以帮助你编写 IDL,但你应始终对照程序源代码验证 IDL,更好的方式是使用 Anchor、Codama 或 Metaplex Shank。
链上存储 IDL
有两种方式可以将 IDL 上传至链上。最常用的标准方式是 Anchor IDL account。Anchor 通过向程序添加额外指令来支持链上上传和更新 IDL,但这会增加程序的体积,这也是 program metadata program 被创建的原因。在 program metadata program 中,所有程序 IDL 以及 security.txt 信息(如名称、联系方式和图标)都存储在 program metadata program 的 PDA 中。
Anchor IDL Account
Anchor 将 IDL 以你程序的 PDA 形式保存在链上。
- IDL 可以链上上传至 Anchor IDL account。
- 这使得区块链浏览器、钱包和 SDK 能够直接从 Solana 获取 IDL。
首次使用(初始化 IDL account):
anchor idl init <PROGRAM_ID> -f target/idl/counter.json --provider.cluster devnet
升级(由授权方进行后续更新):
anchor idl upgrade <PROGRAM_ID> -f target/idl/counter.json --provider.cluster devnet
常用相关命令:
anchor idl fetch -o idl.json <PROGRAM_ID>anchor idl authority <PROGRAM_ID>anchor idl set-authority -p <PROGRAM_ID> -n <NEW_AUTHORITY>anchor idl erase-authority -p <PROGRAM_ID>
请注意,默认情况下 Anchor IDL account 的生成是无需许可的。因此请尽快上传你的 IDL,然后设置授权方。
你可以在 Anchor 文档 中了解更多关于 Anchor IDL account 的内容。
Program Metadata Program(PMP)
program metadata program 是一个允许你将程序 IDL 和 security.txt 信息(如名称、联系方式和图标)存储在链上的程序。这可能将成为未来链上存储 IDL 的标准方式。
npx @solana-program/program-metadata write idl <program-id> ./idl.json
你可以在 program metadata program 文档 中了解更多关于 program metadata program 的内容。
注意:截至本文最后更新时,PMP 尚未得到所有区块链浏览器的支持。
最佳实践
程序部署的最佳实践是使用像 Squads 这样的多签方案,并通过 Solana GitHub Actions 工作流 使这一流程尽可能自动化。
这样,程序将自动完成升级、IDL 上传、构建验证,然后生成一笔待多签成员签名并部署程序的交易提案。
- 保持 IDL 更新 → 每次修改程序时务必更新 IDL。
- 将 IDL 上链存储 → 以确保透明度和工具支持。
- 记录自定义错误 → 提升客户端的用户体验。
- 验证构建 → 确保 IDL 与已部署的程序相匹配。
IDL 版本管理
目前使用 Anchor 时,链上同一时间只能保存一个版本的 IDL。这意味着如果你想对程序进行更改,需要上传新版本的 IDL,最好与程序升级同时进行。如果客户端尚未更新,这可能会导致问题,这也是 program metadata program 被开发出来的原因之一。使用 PMP,你将能够为程序设置不同的种子(seeds)并以此实现版本管理。该设计目前尚未完全定稿,欢迎讨论。
延伸阅读
- Anchor IDL 文档 → 自动生成 IDL 和客户端(TypeScript、C#、Python)。
- Codama → IDL 工具链 + 客户端 生成器(Rust、JS/TS、Umi/Kit 等)。
- Program Metadata Program → 将 IDL 和 security.txt 信息存储在链上。
以上就是 Solana 上 IDL 的基础知识。IDL 是链上程序与链下客户端之间的桥梁,支撑着你今天所见的丰富工具和 SDK 生态系统。
Is this page helpful?