如何扩展EthQL解码自己的ERC标准?自定义交易解码器开发实战教程
【免费下载链接】ethqlA GraphQL interface to Ethereum :fire:项目地址: https://gitcode.com/gh_mirrors/et/ethql
EthQL 是一个把以太坊链数据暴露为 GraphQL 接口的开源项目,内置的「交易解码器」可以自动识别 ERC20 转账、授权等标准操作,让decoded字段直接返回可读的结构化数据。本教程带你从零扩展一个自定义 ERC 标准解码器,让你的 EthQL 节点也能读懂任何 ERC 合约的交易与事件。🔓
EthQL 交易解码器的工作原理
在动手之前,先花 2 分钟理解解码链路,后续每一步都有据可依:
- 解码引擎:core 插件内置 SimpleDecodingEngine,它维护一个解码器注册表。查询交易的
decoded字段时,引擎会依次用每个解码器的 ABI 去尝试decodeMethod(tx.inputData),第一个命中且定义了转换器的解码器即胜出。 - 类型名规则:命中后,引擎按
`${standard}${首字母大写(操作名)}`生成__typename(事件追加Event后缀)。例如 ERC20 的transfer函数得到ERC20Transfer,Transfer事件得到ERC20TransferEvent——这个名字直接决定你在 GraphQL 里能用哪个 fragment。 - 触发条件:只有当交易
inputData存在且不等于0x时,resolver 才会调用解码器(见 transaction.ts 中的decoded函数)。
核心抽象DecoderDefinition定义在 decoder/index.ts,包含四个部件:
| 字段 | 作用 |
|---|---|
entity | 解码对象所属实体,如token |
standard | 标准名,如ERC20、ERC721 |
abiDecoder | 由createAbiDecoder(abi路径)创建,负责把 calldata / 日志解成参数 |
txTransformers/logTransformers | 函数名/事件名 → 类型化对象的转换器字典 |
自定义解码器开发:完整五步走
下面以扩展一个 ERC721(NFT)解码器为例,完整流程可对照项目中的 ERC20 实现(decoders/index.ts)。
第一步:准备合约 ABI 文件
把目标合约的 ABI 存成 JSON 文件,放在插件目录下(参考 erc20.json 的存放方式)。createAbiDecoder(path)会加载该文件并包装底层的abi-decoder库。⚠️ 只需包含你想解码的函数和事件,越精简匹配越快。
第二步:编写解码器类
解码器是一个实现了DecoderDefinition的类,骨架如下:
class Erc721TokenDecoder implements DecoderDefinition<Erc721TxBindings, Erc721LogBindings> { public readonly entity = 'token'; public readonly standard = 'ERC721'; public readonly abiDecoder = createAbiDecoder(__dirname + '/../../abi/erc721.json'); public readonly txTransformers = { transfer: (decoded, tx, context) => ({ from: new EthqlAccount(extractParamValue(decoded.params, 'from')), to: new EthqlAccount(extractParamValue(decoded.params, 'to')), tokenId: extractParamValue(decoded.params, 'tokenId'), }), }; public readonly logTransformers = { Transfer: (decoded, tx, context) => ({ from: new EthqlAccount(extractParamValue(decoded.events, 'from')), to: new EthqlAccount(extractParamValue(decoded.events, 'to')), }), }; }几个关键点:
- 转换器接收三个参数:
decoded(ABI 解码结果)、tx(原始交易)、context(可访问 web3、eth 等服务)。 - 函数参数用
extractParamValue(decoded.params, '名称')提取;日志事件用decoded.events。 - 转换器返回值就是 GraphQL 响应中该类型的字段,可以返回普通值,也可以返回带方法的对象(见下一步)。
第三步:定义数据模型与合约封装
参考 model/index.ts:用 TypeScript 接口描述每种操作的字段;如果需要在查询里继续读取链上数据(比如 NFT 的name()、持有者的balanceOf()),可以像Erc20TokenContract那样用 web3 的 Contract 封装一个类,转换器里返回其实例,resolver 调用时就能按需发起链上读取。
第四步:编写 GraphQL Schema
新建 schema 文件(参考 schema/erc20.ts),类型命名必须与第二步的__typename规则严格对齐:
type ERC721Transfer implements DecodedTransaction & ERC721Transaction { entity: Entity standard: String operation: String from: Account to: Account tokenId: String } type ERC721TransferEvent implements DecodedLog { entity: Entity standard: String event: String from: Account to: Account }第五步:注册插件并挂载到服务器
插件入口参考 erc20/src/index.ts,把解码器挂到decoder服务的配置上:
export const ERC721_PLUGIN: EthqlPluginFactory = _ => ({ name: 'erc721', priority: 10, schema: [erc721Schema], serviceDefinitions: { decoder: { config: { decoders: [new Erc721TokenDecoder()], }, }, }, dependsOn: { services: ['web3', 'eth', 'decoder'], }, order: { after: ['core'], }, });最后在服务器入口(server/src/index.ts)把新插件加入plugins数组,即可启动服务。插件机制的完整字段说明见 plugin/src/index.ts。
验证解码效果:GraphQL 查询示例
启动本地服务:
git clone https://gitcode.com/gh_mirrors/et/ethql cd ethql yarn install yarn bootstrap yarn run dev浏览器打开http://localhost:4000/graphql,执行:
{ transaction(hash: "0x你的NFT交易哈希") { decoded { standard operation ... on ERC721Transfer { tokenId from { address } to { address } } } } }如果 fragment 名拼写不对(比如on ERC20Transfer),说明__typename没对上——回去检查standard字段和操作名大小写。
常见坑与最佳实践清单
- 类型名对齐:
standard + 首字母大写的操作名(事件加Event)是 fragment 匹配的唯一依据,三者(解码器standard、schema 类型名、查询 fragment)必须完全一致。 - 精确匹配:
txTransformers里只为确实想解码的 ABI 函数建条目,引擎靠「函数名是否在字典中」判断是否命中。 - 注册顺序:引擎返回第一个命中的解码器,多个解码器都能匹配同一 ABI 时,插件
priority越小、启动越靠前,注意避免标准名冲突。 - 调试技巧:开发时设置环境变量
DEBUG=ethql:*可看到 resolver 层日志。 - 事件解码:
decodeLog走abiDecoder.decodeLogs,日志参数要从decoded.events而不是decoded.params里取。
总结
扩展 EthQL 解码自己的 ERC 标准,本质上就是四件套:ABI 文件 + 解码器类 + GraphQL Schema + 插件注册。掌握 SimpleDecodingEngine 的「遍历注册表 → ABI 匹配 → 转换器输出」链路后,无论是 ERC721、ERC1155 还是私有标准,都能在半天内接入你的 GraphQL 端点,让链上交易从十六进制乱码变成结构化数据。🚀
【免费下载链接】ethqlA GraphQL interface to Ethereum :fire:项目地址: https://gitcode.com/gh_mirrors/et/ethql
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考