网页请钱包签名前那份英文名单:EIP-1193 的 Provider 接口与事件 图 1
网页请钱包签名前那份英文名单:EIP-1193 的 Provider 接口与事件 · 图 1

网页和钱包之间的那层玻璃

浏览器里的钱包扩展或注入式钱包,本质上是运行在你机器上的一个独立程序:私钥在它手里,网页碰不到。网页想让钱包干活——显示地址、对一条消息签名、把交易广播出去——必须通过一扇受控的门。EIP-1193 就是把这扇门的形状标准化:它定义了一个叫 Provider 的 JavaScript 对象,网页调用它的方法,钱包实现这些方法。这份 2018 年 6 月起草、后来标记为 Final 的标准刻意保持最小:一个方法、四个事件,不规定数据怎么在底层传输,也不关心钱包内部怎么管钥匙。

request 方法:唯一的入口

Provider 的核心只有一个 request 方法,接收一个参数对象,里面两项:method 和 params。method 是要调用的 RPC 方法名,params 是可选的参数数组或对象。网页调用它,钱包决定批准还是拒绝,拒绝时以错误对象抛出。这种设计把决策权留在钱包一侧:网页只能提出请求,看不见也改不了签名流程。

常用的方法名大体分两类。一类来自以太坊节点的 JSON-RPC 词表,比如查询区块高度、读合约数据、请求发送交易;另一类是钱包特有的,其中最重要的是显式请求账户访问的方法——网页第一次想知道”用户愿意暴露哪个地址”时,必须调用这类方法触发用户确认,而不是默默读取。标准还明确了一点:Provider 无法服务任何链时应当视为断开,而不是返回空数据糊弄网页。

四个事件:钱包主动播报的时刻

被动应答之外,Provider 还要在状态突变时主动发事件,一共四种。connect 在 Provider 第一次能服务某条链时触发;disconnect 在所有链都不可服务时触发,典型场景是用户撤销了网站访问授权。剩下两个是普通用户最容易遭遇的:accountsChanged 在用户切换账户时广播,网页应当立刻刷新余额和权限显示;chainChanged 在网络切换时广播,网页应当重连节点、重新读取链上状态。

这两个事件的存在有现实原因:如果钱包切了账户却不广播,网页会继续在旧账户的视角上给你看数据,你看到的余额和实际签名用的账户可能是两个不同的东西。所以负责任的网页要么监听这两个事件,要么干脆在事件触发时强制刷新页面。反过来说,一个从不监听这些事件的网页,在钱包多账户、多网络的日常里天然容易显示错乱——这是接口层面的缺陷,不一定是恶意。

window.ethereum 只是惯例

一个常见误解需要澄清:把 Provider 挂在页面的 window.ethereum 属性上,是生态惯例,不是 EIP-1193 的规范内容。标准文本明确写了这句话。这个区别在实践中有意义:早期出现过多钱包同时抢注 window.ethereum 的冲突,一个页面装了 MetaMask 又装了别的钱包扩展时,谁最后注入谁占坑,网页调用的可能不是你以为的那个钱包。后来生态用 EIP-6963 的广播发现机制来缓解——钱包不再抢占全局变量,而是各自在页面里广播”我在这儿,这是我的信息”,让网页自己列清单让用户选。EIP-1193 管接口的形状,EIP-6963 管多个钱包共存时怎么被发现,两者是互补关系。

一条自查线

普通用户不需要写代码,但这条线值得记住:网页请求你签名或发交易时,弹什么窗口由钱包决定,不由网页决定。如果一个流程里你从头到尾没见过钱包弹出确认,只在网页里点了”确认”按钮,那要么交易是网页代签(托管型),要么你点的根本不是签名入口。接口标准保证了”门”的形状统一,但门后面站着的是谁,永远要你自己核对。本文只讨论协议机制,不构成任何投资建议。