web3.js 账户抽象实战指南:web3-account-abstraction 的 Bundler RPC 封装与 UserOperation 全解析
web3.js 账户抽象实战指南web3-account-abstraction 的 Bundler RPC 封装与 UserOperation 全解析【免费下载链接】web3.jsCollection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.项目地址: https://gitcode.com/gh_mirrors/we/web3.js本文基于 web3.js 仓库中的 web3-account-abstraction 包文档系统讲解该子包的安装方式、AccountAbstraction类的完整 API发送、估算、查询、哈希计算 UserOperation以及UserOperation数据结构。读完本文你将能够独立对接任意 Bundler RPC 节点完成 ERC-4337 账户抽象流程并理解每个方法底层的请求封装、十六进制转换与 UserOperation 哈希算法实现。包定位与安装web3-account-abstraction是 web3.js 4.x 系列的子包专门用于以太坊 JSON-RPC 交互中的账户抽象Account Abstraction场景。按照 README 的说明Account Abstraction 特性“通过允许智能合约更灵活地管理用户账户和交易来增强用户体验与安全性”——即以智能合约账户替代传统 EOA交易由 Bundler 打包提交、由 EntryPoint 合约统一执行。从 package.json 可以确认该包的关键元信息包名web3-account-abstraction当前仓库版本为1.0.0-rc.0许可证 LGPL-3.0运行环境要求node 14、npm 6.12.0对应 README 中“NodeJS (LTS/Fermium)”的前置条件同时提供 ESM./lib/esm/index.js、CommonJS./lib/commonjs/index.js与类型声明./lib/types/index.d.ts三种入口依赖项为同仓库的其他子包web3-core、web3-eth-abi、web3-types、web3-utils、web3-validator。使用 NPM 安装npm install web3-account-abstraction使用 Yarn 安装yarn add web3-account-abstraction安装完成后包的 入口文件 会导出AccountAbstraction类同时作为默认导出、types.ts中的全部类型以及utils.ts中的工具函数。包内构建与测试脚本README 完整列出了package.json中的常用脚本这里一并给出并标注其实际命令来源见 package.json 的scripts字段ScriptDescription实际命令cleanUsesrimrafto removedist/rimraf dist rimraf libbuildUsestscto build package and dependent packagesconcurrently并行执行build:cjs、build:esm、build:typeslintUseseslintto lint packageeslint --cache --cache-strategy content --ext .ts .lint:fixUseseslintto check and fix any warningseslint --fix --ext .js,.ts .formatUsesprettierto format the codeprettier --write **/*testUsesjestto run unit testsjest --config./test/unit/jest.config.jstest:integrationUsesjestto run tests under/test/integrationjest --config./test/integration/jest.config.js --passWithNoTeststest:unitUsesjestto run tests under/test/unitjest --config./test/unit/jest.config.js其中build采用concurrently --kill-others-on-fail并行构建 CJS、ESM、类型三个产物任一失败即终止其他任务保证产物一致性。AccountAbstraction 类构造与请求路由核心实现位于 src/web3_aa.ts。AccountAbstraction类继承自web3-core的Web3Context这是它得以复用统一请求管理机制的基础export class AccountAbstractionAPI extends AARpcApi extends Web3Context { // local package level request manager private readonly bundlerRequestManager!: Web3RequestManagerAPI; public constructor(provider?: SupportedProvidersAPI | string) { super(); if ( (typeof provider string provider.trim() ! ) || isSupportedProvider(provider as SupportedProvidersAPI) ) { this.bundlerRequestManager new Web3RequestManagerAPI(provider); } } }从源码结构看构造逻辑有两点值得注意独立的 Bundler 请求管理器。构造函数接受一个 Bundler 的 URL 字符串或实现SupportedProviders接口的 Provider 对象用它创建包级私有的bundlerRequestManager。Account Abstraction 的 RPC 方法eth_sendUserOperation等由 Bundler 而非普通链上节点提供因此单独管理这条请求通道避免与主网 Provider 混淆。双重请求通道降级。所有方法内部统一采用(this.bundlerRequestManager ?? this.requestManager).send(...)的模式——优先走 Bundler 专属通道若构造时未传入 Bundler Provider则回退到Web3Context的requestManager可通过web3.setProvider或中间件体系注入的通道。测试文件 test/unit/account_abstraction.test.ts 正是通过 spybundlerRequestManager.send来验证各方法最终发送的 RPC method 与 params。最小使用示例与源码 TSDoc 中的示例一致import { AccountAbstraction } from web3-account-abstraction; const aa new AccountAbstraction(https://bundler-provider); aa.supportedEntryPoints().then(console.log); // [0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8, 0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6]UserOperation 数据结构所有方法的第一参数都是UserOperation其定义在 src/types.ts字段类型是否必填含义senderAddress是智能合约账户地址即这笔操作代表的用户nonceUint256是账户操作序号防止重放initCodeHexStringBytes是首次部署账户时的初始化代码空值须为0xcallDataHexStringBytes是内层账户实际执行的调用数据callGasLimitUint256否内部执行可用的 gasverificationGasLimitUint256是验证validateUserOp消耗的 gas 上限preVerificationGasUint256是该操作的预验证 gas 开销maxFeePerGasUint256否每单位 gas 的最高费用maxPriorityFeePerGasUint256否每单位 gas 的最高优先费paymasterAndDataHexStringBytes是代付合约地址及附加数据无则填0xsignatureHexStringBytes是账户签名此外还有两个关联类型UserOperationRequiretypes.ts将callGasLimit、maxFeePerGas、maxPriorityFeePerGas三个可选项提升为必填项用于本地计算 UserOperation 哈希因为哈希算法需要完整的 gas 与费用字段。AARpcApitypes.ts以方法签名的形式声明了本包支持的全部 RPC 接口——eth_sendUserOperation、eth_estimateUserOperationGas、eth_getUserOperationByHash、eth_getUserOperationReceipt、eth_supportedEntryPoints以及本地方法generateUserOpHash作为Web3RequestManagerAPI的类型约束保证 RPC 调用的类型安全。返回值类型同样在 types.ts 中定义GetUserOperationByHashAPI含blockHash、blockNumber、entryPoint、transactionHash、完整userOperation、EstimateUserOperationGasAPI三个 gas 字段、GetUserOperationReceiptAPI含userOpHash、sender、nonce、paymaster、actualGasCost、actualGasUsed、success、reason、logs、receipt。方法逐一解析1. sendUserOperation提交操作到 Bundler实现见 web3_aa.tspublic async sendUserOperation(userOperation: UserOperation, entryPoint: Address) { let userOp { ...userOperation }; const validator isUserOperationAllHex(userOp); if (!validator) { userOp convertValuesToHex(userOperation) as UserOperation; } return (this.bundlerRequestManager ?? this.requestManager).send({ method: eth_sendUserOperation, params: [userOp, entryPoint], }); }该方法有两个前置行为值得注意自动十六进制化。Bundler 协议要求 UserOperation 所有字段必须以十六进制字符串传递空字节字段如空initCode须为0x。sendUserOperation会先调用 utils.ts 中的isUserOperationAllHex逐字段执行isHexStrict严格校验只要有一个字段不是严格 hex就用convertValuesToHex做整体转换字符串补0x前缀、number/bigint 转十六进制字符串、boolean 转0x0/0x1utils.ts。这意味着你传入十进制数字形式的nonce: 123、callGasLimit: 1000也能被正确接受返回 userOpHash。若 Bundler 接受该操作会将其放入 UserOperation mempool 并返回userOpHashHexString32Bytes后续凭此哈希查询状态。调用示例源自方法 TSDocaa.sendUserOperation({ sender: 0x9fd042a18e90ce326073fa70f111dc9d798d9a52, nonce: 123, initCode: 0x68656c6c6f, callData: 0x776F726C64, callGasLimit: 1000, verificationGasLimit: 2300, preVerificationGas: 3100, maxFeePerGas: 8500, maxPriorityFeePerGas: 1, paymasterAndData: 0x626c6f63746f, signature: 0x636c656d656e74 }, 0x636c656d656e74).then(console.log); // 0xe554d0701f7fdc734f84927d109537f1ac4ee4ebfa3670c71d224a4fa15dbcd12. estimateUserOperationGas估算 gas 三要素实现见 web3_aa.ts。Bundler 根据一个“可选地缺少 gas 限制与 gas 价格”的 UserOperation返回所需的preVerificationGas该操作的 gas 开销verificationGasLimit验证该操作实际消耗的 gascallGasLimit内层账户执行使用的值。注意两个细节按协议约定估算时signature字段被钱包忽略这样估算操作不会要求用户授权但仍可能需要一个“半有效”签名例如长度正确但内容无效的签名源码会主动补全缺失的费用字段若maxFeePerGas为undefined则设为0maxPriorityFeePerGas同理web3_aa.ts。这一行为被单元测试明确覆盖——account_abstraction.test.ts 分别验证了两种缺省情况下eth_estimateUserOperationGas请求的 params 中对应字段为0。3. getUserOperationByHash按哈希查询操作详情实现见 web3_aa.ts向 Bundler 发送eth_getUserOperationByHash。若操作尚未打包进区块则返回null否则返回完整 UserOperation并额外附带entryPoint、blockNumber、blockHash、transactionHash四个打包上下文字段。4. getUserOperationReceipt获取操作回执实现见 web3_aa.ts。回执字段对应GetUserOperationReceiptAPI包括userOpHash、entryPoint、sender、nonce、paymaster未使用代付则为空、actualGasCost账户或代付方实际支付、actualGasUsed含预验证、创建、验证与执行在内的总 gas、success是否无 revert 完成、reasonrevert 原因、logs仅该操作产生的日志不含同 bundle 内其他操作的日志以及receipt——注意返回的TransactionReceipt是针对整个 bundle 交易的而非单笔操作。5. supportedEntryPoints查询支持的 EntryPoint实现见 web3_aa.ts发送无参的eth_supportedEntryPoints返回 Bundler 支持的 EntryPoint 合约地址数组。按规范数组第一个元素应为该客户端优先推荐的 EntryPoint。6. generateUserOpHash本地计算操作哈希generateUserOpHashweb3_aa.ts是纯本地方法不经过任何 Provider直接委托给 utils.ts 中的同名函数用于在发送前或验证回执时计算 UserOperation 哈希。其算法严格对应 ERC-4337 EntryPoint 的哈希约定分两步 ABI 编码 keccak256export const generateUserOpHash ( userOp: UserOperationRequire, entryPoint: string, chainId: string, ): string { // 第一步按 EntryPoint 约定编码 11 个字段 const types: AbiInput[] [ address, uint256, bytes32, bytes32, uint256, uint256, uint256, uint256, uint256, bytes32, ]; const values [ userOp.sender, userOp.nonce, sha3Checked(userOp.initCode), // initCode 先取 keccak256 sha3Checked(userOp.callData), // callData 先取 keccak256 userOp.callGasLimit, userOp.verificationGasLimit, userOp.preVerificationGas, userOp.maxFeePerGas, userOp.maxPriorityFeePerGas, sha3Checked(userOp.paymasterAndData), // paymasterAndData 先取 keccak256 ]; const packed: string encodeParameters(types, values); // 第二步再编码 (hash, entryPoint, chainId) 并做最终 keccak256 const enc: string encodeParameters([bytes32, address, uint256], [sha3Checked(packed), entryPoint, chainId]); return sha3Checked(enc); };几个实现要点长字节字段initCode、callData、paymasterAndData在参与编码前会先做sha3keccak256避免超长数据直接进入 ABI 编码encodeParameters来自web3-eth-abi子包sha3来自web3-utils子包sha3Checked是对sha3的包装——当哈希结果为undefined时抛出sha3 returned undefined错误utils.ts这一异常路径也被单元测试覆盖account_abstraction.test.ts 通过传入空initCode触发因为算法要求callGasLimit、maxFeePerGas、maxPriorityFeePerGas必须存在入参类型是必填版本UserOperationRequire而非UserOperation。单元测试给出了确定性的向量校验account_abstraction.test.ts对文档示例中的 userOp、entryPoint 0xaE036c65C649172b43ef7156b009c6221B596B8b、chainId 0x1计算结果应为0xe554d0701f7fdc734f84927d109537f1ac4ee4ebfa3670c71d224a4fa15dbcd1完整工作流示例综合以上方法一个典型的账户抽象提交流程如下import { AccountAbstraction, UserOperation } from web3-account-abstraction; const aa new AccountAbstraction(http://127.0.0.1:8555/); // 1. 查询 Bundler 支持的 EntryPoint const entryPoints await aa.supportedEntryPoints(); const entryPoint entryPoints[0]; // 2. 估算 gas费用字段可省略库内自动补 0 const gas await aa.estimateUserOperationGas({ sender: 0x9fd042a18e90ce326073fa70f111dc9d798d9a52, nonce: 0, initCode: 0x, callData: 0x776F726C64, signature: 0x, paymasterAndData: 0x, }, entryPoint); // { callGasLimit: 0x..., verificationGasLimit: 0x..., preVerificationGas: 0x... } // 3. 组装完整 UserOperation含账户签名提交 const userOp: UserOperation { sender: 0x9fd042a18e90ce326073fa70f111dc9d798d9a52, nonce: 0, initCode: 0x, callData: 0x776F726C64, ...gas, maxFeePerGas: 8500, maxPriorityFeePerGas: 1, paymasterAndData: 0x, signature: 0x636c656d656e74, }; const userOpHash await aa.sendUserOperation(userOp, entryPoint); // 4. 本地核验哈希需使用必填版本的完整字段 const localHash aa.generateUserOpHash(userOp, entryPoint, 0x1); // 5. 轮询直至打包读取回执 const receipt await aa.getUserOperationReceipt(userOpHash); const detail await aa.getUserOperationByHash(userOpHash);该流程中每一步与源码方法的对应关系均可在 web3_aa.ts 的 TSDoc 示例中找到印证单元测试则通过 mockbundlerRequestManager.send验证了每个方法发出的method名与params结构完全符合 Bundler RPC 规范account_abstraction.test.ts。版本与使用前提当前仓库中该包版本为1.0.0-rc.0release candidateAPI 以 src/web3_aa.ts 与 src/types.ts 的实际导出为准Node.js 需14ES 目标为 2020见 README 徽章与 package.jsonengines字段所有eth_*UserOperation*方法依赖一个实现 Bundler RPC 的节点构造函数中传入的 Bundler URL/Provider 决定请求通道未传入时回退到Web3Context的requestManager本地方法generateUserOpHash与类型、工具函数的使用不依赖任何网络节点。进一步的类型定义、构建脚本与变更记录可分别查阅 types.ts、package.json 和 CHANGELOG.md。【免费下载链接】web3.jsCollection of comprehensive TypeScript libraries for Interaction with the Ethereum JSON RPC API and utility functions.项目地址: https://gitcode.com/gh_mirrors/we/web3.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考