ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

EIP-2696 详解:JavaScript `request` 方法 RPC 传输标准与 Ethereum Provider 接口实践

2026/9/15 15:55:12 拓冰建站 浏览量
EIP-2696 详解:JavaScript `request` 方法 RPC 传输标准与 Ethereum Provider 接口实践 EIP-2696 详解JavaScriptrequest方法 RPC 传输标准与 Ethereum Provider 接口实践【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPsEIP-2696JavaScriptrequestmethod RPC transport是 Ethereum Improvement Proposal 仓库EIPS中一项已进入Final状态的 Interface 类标准它定义了 JavaScript 应用与以太坊区块链之间通过共享 JavaScript 对象进行远程过程调用RPC的统一传输机制。本文将以该标准为骨架结合仓库内 EIP-1193、EIP-2700、EIP-1474 等关联规范完整解析request方法接口、参数编码规则、结果返回契约与错误码体系帮助读者掌握 DApp 与钱包/Provider 之间标准通信的实现原理与实战写法。标准定位一份纯粹的传输层规范EIP-2696 由 Micah Zoltu 与 Erik Marks 于 2020 年 6 月提出核心诉求是为 Ethereum Provider以太坊提供者与 Ethereum Client以太坊客户端之间定义一种标准化的 RPC 传输机制前提是二者可以通过一个共享的 JavaScript 对象进行交互。需要特别强调的是该标准只描述传输机制本身它不规定哪些 payload 是合法的也不规定客户端与 Provider 之间如何发现或协商 payload 内容。也就是说它解决的是请求怎么发、结果怎么收、错误怎么报它不解决能调用哪些 RPC 方法、方法参数是什么这属于 EIP-1474 等 RPC 方法规范范畴它也不解决Provider 对象暴露在哪里、如何被发现如window.ethereum仅是社区惯例交由后续标准约定。这一设计让 EIP-2696 成为整个 Ethereum Provider JavaScript API 生态的底层基石后续的 EIP-1193Provider 完整 API与 EIP-2700事件发射器均是在此基础上的延伸与补全。动机为什么需要标准化 Provider 对象在 JavaScript 运行时NodeJS、Electron、浏览器等中运行时本身或其插件可以向运行时内注入对象。作者编写一个运行时或运行时插件时可以选择向运行在该运行时中的 JavaScript 应用暴露一个 Ethereum Provider从而提供对类以太坊区块链的间接访问以及潜在的签名工具。为了保证 Provider 与 Client 之间的最大兼容性就必须对这个对象的形状shape进行标准化——这正是 EIP-2696 的意义所在。没有这一标准每个钱包或运行时插件都可能定义自己的一套调用方式例如历史上纷繁复杂的send、sendAsync与回调风格 API导致 DApp 开发者不得不针对不同实现编写适配代码。规范主体request方法接口定义RFC-2119 约束规范全文使用 RFC-2119 中的关键词语MUST、MUST NOT、REQUIRED、SHALL、SHALL NOT、SHOULD、SHOULD NOT、RECOMMENDED、MAY、OPTIONAL来界定强制性与建议性要求读者在解读实现义务时需要按此语义理解。TypeScript 接口规范给出的核心接口定义如下interface RequestArguments { readonly method: string; readonly params?: readonly unknown[] | object; } interface EthereumProvider { request(args: RequestArguments): Promiseunknown }对实现方的强制要求MUST包括Provider必须在暴露的EthereumProvider对象上实现request方法request方法必须能够以单个参数调用该参数包含请求参数且须符合上述 TypeScriptinterface定义。值得注意的是RequestArguments的字段均为readonlyparams为可选字段其类型是readonly unknown[] | object——即既可以是数组也可以是对象这为不同 RPC 方法的参数形态留出了空间。与 JSON-RPC 的对应关系这是 EIP-2696 中最关键的映射规则如果 Provider 支持某个在别处定义的 JSON-RPC 请求那么它必须接受对应的request调用且满足RequestArguments.method与该 RPC 调用的 JSON-RPCmethod字符串一致RequestArguments.params与该 RPC 调用的params对象一致params应编码为符合指定 JSON-RPC 类型的 JavaScript 对象而不是像传统 JSON-RPC 传输那样编码为 JSON 字符串。请求示例若一个 JSON-RPC 请求的载荷为{ jsonrpc: 2.0, id: 1, method: do_work, params: [ 5, hello ] }则与之对应的EthereumProvider.request调用为declare const provider: EthereumProvider provider.request({ method: method, params: [ 5, hello ] })可以看到JSON-RPC 外层包裹的jsonrpc版本号与id字段在request调用中被完全剥离仅保留method与params两个语义字段且参数直接以原生 JavaScript 数组传递。这正是传输机制标准化的核心体现上层应用无需关心 JSON 序列化与 RPC 协议的细节。结果ResultsPromise 的解析契约对于 Provider 支持的 JSON-RPC 请求request必须返回一个与对应 JSON-RPC 请求的result定义相匹配的对象。换言之调用方通过await provider.request(...)或.then(...)拿到的是 RPC 结果本身而非任何协议包裹层。结果示例若 JSON-RPC 响应的载荷为{ jsonrpc: 2.0, id: 1, result: { color: red, value: 5 } }则对应的EthereumProvider.request响应为{ color: red, value: 5 }这一契约在 EIP-1193 中被进一步强化返回的 Promise必须按照 RPC 方法的规范解析出结果不得解析出任何 RPC 协议特有的响应对象除非 RPC 方法的返回类型本身如此定义。EIP-1193 规范第 84-86 行。错误ErrorsProviderRpcError与统一错误码错误对象接口当 Provider 因任何原因无法完成请求时必须以错误形式 resolve 该 Promise并且只要可能错误必须符合ProviderRpcError的形状interface ProviderRpcError extends Error { message: string; code: number; data?: unknown; }规范同时承认一个现实无法保证 JavaScript 应用永远不会抛出内存溢出out of memory或栈溢出stack overflow错误因此要求是在可能的情况下whenever possible保证 Promise 拒绝符合上述形状。标准错误码表EIP-2696 定义了五个标准错误码与 EIP-1193 的 Provider Errors 完全一致codemessagemeaning4001User Rejected Request用户拒绝了该请求4100Unauthorized请求的方法和/或账户尚未获得用户授权4200Unsupported MethodProvider 不支持所请求的方法4900DisconnectedProvider 与所有链断开连接4901Chain DisconnectedProvider 未连接到所请求的链错误码使用规则如果提供的code出现在上表、JSON-RPC 规范的错误对象定义中或所遵循的关联 JSON-RPC 请求标准中那么错误原因reason必须与该 code 的既定含义保持一致message必须与既定 message 一致。而data字段可以MAY包含与错误相关的任何数据或有助于用户理解、排查错误的信息。在 EIP-1193 中这两条与连接状态相关的错误码被赋予了更细的语义EIP-1193 规范第 145-156 行4900表示 Provider 与所有链断开连接4901表示 Provider 仅与特定链断开但与其他链仍保持连接——即4901隐含Provider 连接着其他链只是没连上被请求的那条。横向关联EIP-2696 在 Provider 标准族中的位置要真正用好 EIP-2696有必要理解它与仓库中相邻标准的分工标准定位与 EIP-2696 的关系EIP-1193: Ethereum Provider JavaScript API定义完整的 Provider APIrequest 事件完整继承了request接口与ProviderRpcError错误体系并补充事件模型EIP-2700: JavaScript Provider Event Emitter定义 Provider 的on/removeListener事件机制与 EIP-2696 是同一作者Micah Zoltu、Erik Marks同年相继提出一个管发出请求一个管接收通知EIP-1474: Remote procedure call specification规定节点应实现的标准 RPC 方法集合及 JSON-RPC 约定是request可以调用的方法层规范含标准错误码如-32700Parse error、-32603Internal error 等EIP-695:eth_chainId定义eth_chainIdRPC 方法是request({ method: eth_chainId })这类实际调用的方法来源其中 EIP-2700 的接口定义与 EIP-2696 形成互补interface EthereumProvider { on(eventName: string, listener: (...params: unknown[]) void): void removeListener(eventName: string, listener: (...params: unknown[]) void): void }两个标准刻意将具体事件名与 listener 回调的形状留给了独立标准去定义最终由 EIP-1193 落实为connect、disconnect、chainChanged、accountsChanged、message五个事件体现了 EIP-2696 家族分层标准、各司其职的设计哲学。此外EIP-7039Scheme-Handler Discovery Option for Wallets即 SHADOW进一步展示了 EIP-2696 接口的复用价值该提案通过postMessage传输的请求数据必须满足 EIP-1193 的RequestArguments接口并按其解释执行响应对象中的ProviderRpcError也沿用同一套错误体系EIP-7039 规范第 54-73 行。这说明RequestArguments与ProviderRpcError已经成为跨传输通道共享对象注入、postMessage端口等通用的数据契约。实战结合 EIP-1193 编写标准化的 DApp 调用代码EIP-2696 本身不涉及对象暴露位置但在浏览器 DApp 场景中Provider 通常以window.ethereum约定形式出现注意这只是惯例而非标准。结合 EIP-1193 的消费者示例一段符合 EIP-2696 传输契约的典型代码如下// 多数 Provider 在页面加载时以 window.ethereum 形式可用仅惯例非标准 const ethereum window.ethereum; // 示例 1查询 chainId方法定义见 EIP-695 ethereum .request({ method: eth_chainId }) .then((chainId) { console.log(hexadecimal string: ${chainId}); console.log(decimal number: ${parseInt(chainId, 16)}); }) .catch((error) { console.error(Error fetching chainId: ${error.code}: ${error.message}); }); // 示例 2查询最新区块params 以原生数组传递而非 JSON 字符串 ethereum .request({ method: eth_getBlockByNumber, params: [latest, true], }) .then((block) { console.log(Block ${block.number}:, block); }) .catch((error) { console.error( Error fetching last block: ${error.message}. Code: ${error.code}. Data: ${error.data} ); });这段代码体现了 EIP-2696 的三个核心契约单一参数对象request只接收一个RequestArguments对象其中method为字符串params为可选的原生数组/对象Promise 化结果成功时解析出 RPC 方法的结果值失败时拒绝为带code/message/data的ProviderRpcError剥离协议包裹jsonrpc版本号与id等 JSON-RPC 传输细节对应用层完全透明。对于错误处理的完整实现可以参考 EIP-1193 中对 Promise 拒绝条件的归纳EIP-1193 规范第 90-104 行RPC 请求返回错误、Provider 遇到错误或无法处理请求时必须拒绝Provider 断开时拒绝错误码应为4900请求指向特定链而 Provider 未连接该链但连接着其他链时拒绝错误码应为4901。Rationale为何对齐 JSON-RPC规范作者在 Rationale 中坦承这套机制或许不是应用与区块链通信的最佳方案但它与社区既有实践高度一致因此从现有系统迁移到这套机制的难度相对较低。当时社区中的绝大多数通信都通过 JSON-RPC 完成与 JSON-RPC 标准对齐可以快速集成到既有系统中——这也解释了为什么request的method/params直接对应 JSON-RPC 的同名字段以及为什么要求 Provider 返回与 JSON-RPCresult定义一致的对象。安全考量信任模型与注意事项EIP-2696 明确指出Ethereum Provider 与客户端之间的关系是可信关系即假设用户隐式信任注入到客户端中的 Ethereum Provider或者客户端明确建立了与它的连接。这条假设在 EIP-1193 的 Security Considerations 中被进一步展开Provider 本质是在不可信环境如第三方网站中暴露的钱包扩展实现者应将 Provider 对象视为受对手方控制Provider 不得包含任何用户私密数据Provider 与钱包程序必须相互隔离钱包/客户端应对来自 Provider 的请求进行限流rate-limit并校验所有来自 Provider 的数据出于隐私保护默认不应暴露任何账户账户访问应通过eth_requestAccountsEIP-1102或wallet_requestPermissionsEIP-2255等显式授权方法。版本与适用前提本篇文章基于当前仓库中的标准文本EIP-2696 原文撰写。EIP-2696 状态为Final2020-06-04 创建类型为 Standards Track / Interface。需要明确的是该标准描述的是传输层契约实际能调用哪些 RPC 方法由 EIP-1474 等方法级规范及具体 Provider 实现决定Provider 对象如何暴露如window.ethereum不属于本规范范围实现时请以具体钱包/运行时的文档为准错误码的完整含义与事件模型请参照 EIP-1193 的配套定义。理解 EIP-2696 的request方法就等于拿到了理解整个 Ethereum Provider JavaScript 生态的钥匙——无论是钱包实现方还是 DApp 应用方这套RequestArguments Promise ProviderRpcError的三元契约都值得作为首选的通信范式。版权说明EIP-2696 原文版权依据 CC0 协议 放弃Copyright and related rights waived via CC0本文基于其公开内容整理撰写。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考