多钱包自动发现以及注入冲突解决方案: EIP-6963调研

前言

如果浏览器插件钱包需要向 Dapp 提供以太坊 Provider 能力,必须实现 EIP1193 协议。根据 EIP1193 协议描述,要求插件钱包将 Provider 实现注入到 window.ethereum。 这就导致了一些问题。

  • 注入冲突。用户如果安装了多个插件钱包,就会造成 window.ethereum 被重复覆盖,最终值取决于插件钱包的加载顺序。
  • 恶意竞争。为了让自家钱包的 Provider 实现能够成功注入到 window.ethereum, 有些插件钱包会延迟自家 Provider 的注入,甚至freeze window.ethereum对象,使其无法被覆盖。

同时,由于 EIP1193 没有定义钱包 Provider 的元数据描述接口,导致 Dapp 无法统一自动解析 Provider 中的特定信息来区分不同钱包。插件钱包的元数据(图标,名称等)如果要正确被显示,就需要钱包开发者手动将这些信息提交给 Dapp 或者 Provider Discovery Library (github.com/rainbow-me/...),耗时耗力。

EIP-6963 协议介绍

EIP-6963(Multi Injected Provider Discovery),就很好地解决了上述这些问题。下面简要概述下该协议的核心内容。

EIP6963ProviderInfo

该协议定义了 一个标准化的 EIP6963ProviderInfo 接口,包含了钱包 Provider 的一些相关元数据。

ts 复制代码
/**
 * Represents the assets needed to display a wallet
 */
interface EIP6963ProviderInfo {
  uuid:string;
  name:string;
  icon:string;
  rdns:string;
}
  • uuid: 符合 UUID v4.0 规范的钱包本地唯一标识符。
  • name: 人类可读的钱包名称。
  • icon: 指向图像的 URI,应为 96x96px 的最小分辨率的正方形。建议使用 PNG , WebP 或SVG。
  • rdns: 钱包的反向域名标识符,如 io.metamask.wallet

EIP6963ProviderDetail

该协议定义了一个标准化的 EIP6963ProviderDetail 接口,用于公布钱包 Provider 对象(实现EIP1193规范)和钱包 Provider 的一些相关元数据(实现EIP6963ProviderInfo接口)。

ts 复制代码
interface EIP6963ProviderDetail {
  info: EIP6963ProviderInfo;
  provider: EIP1193Provider;
}

Announce和Request 事件

该协议引入了一组 window 事件,通过事件实现 Dapp 与钱包 Provider 的双向通信。

  • Dapp 与钱包 Provider 都需要使用 window.dispatchEvent 函数来触发事件,使用 window.addEventListener 来监听事件。

  • 定义了 EIP6963AnnounceProviderEvent 接口,并且实现该接口的对象必须是CustomEvent 对象。应该使用Object.freeze() 冻结 detail 属性。

    ts 复制代码
    // Announce Event dispatched by a Wallet
    interface EIP6963AnnounceProviderEvent extends CustomEvent {
      type: "eip6963:announceProvider";
      detail: EIP6963ProviderDetail;
    }
  • 定义了 EIP6963RequestProviderEvent 接口,并且实现该接口的对象必须是 Event 对象。

    ts 复制代码
    // Request Event dispatched by a DApp
    interface EIP6963RequestProviderEvent extends Event {
      type: "eip6963:requestProvider";
    }

通信流程

钱包端

  • 钱包通过window.addEventListener监听eip6963:requestProvider事件, 当收到该事件时,应该立即通过 window.dispatchEvent 触发EIP6963AnnounceProviderEvent 事件,将钱包的EIP6963ProviderDetail 信息发送给 Dapp。
  • 由于钱包可能晚于 Dapp 加载完成,导致未能成功监听到 Dapp 发送的eip6963:requestProvider 事件。所以当钱包加载完成时,应该立即通过 window.dispatchEvent 触发一次 EIP6963AnnounceProviderEvent
ts 复制代码
let info: EIP6963ProviderInfo;
let provider: EIP1193Provider;

const announceEvent: EIP6963AnnounceProviderEvent = new CustomEvent(
  "eip6963:announceProvider",
  { detail: Object.freeze({ info, provider }) }
);

// The Wallet dispatches an announce event which is heard by
// the DApp code that had run earlier
window.dispatchEvent(announceEvent);

// The Wallet listens to the request events which may be
// dispatched later and re-dispatches the `EIP6963AnnounceProviderEvent`
window.addEventListener("eip6963:requestProvider", () => {
  window.dispatchEvent(announceEvent);
});

Dapp端

  • Dapp 应该通过 window.addEventListener 监听 eip6963:announceProvider 事件。并且在页面生命周期内,不得移除该事件监听。
  • 当监听eip6963:announceProvider 事件后,Dapp 才可以通过window.dispatchEvent 发送eip6963:requestProvider 事件,向钱包请求 EIP6963ProviderDetail 信息。
ts 复制代码
// The DApp listens to announced providers
window.addEventListener(
  "eip6963:announceProvider",
  (event: EIP6963AnnounceProviderEvent) => {}
);

// The DApp dispatches a request event which will be heard by 
// Wallets' code that had run earlier
window.dispatchEvent(new Event("eip6963:requestProvider"));

EIP-6963 具体实现

  • 一些主流钱包已经陆续实现了该协议,如: Metamask, Okx Wallet, Bitget Wallet, Brave, Rainbow, Safeheron Wallet 等。更多钱包见github.com/WalletConne...
  • 如果你的插件钱包需要实现该协议,可以参考Metamask代码github.com/MetaMask/pr...

EIP-6963 测试

如果需要测试钱包是否支持了该协议,可以使用如下 Dapp 测试

相关推荐
2601_962072504 分钟前
CBCX:电力需求增长考验电网容量
区块链
PedroQue996 分钟前
@meng-xi/create-uni-app v1.0.0 正式发布
前端·uni-app
younuo365514 分钟前
广州网站搭建费用明细:域名、服务器与开发成本全解析
服务器·前端·github
恋猫de小郭22 分钟前
Flutter A2UI 深度解析,它是怎么提供动态生产力的,然后为什么 A2UI 不只是 Flutter
android·前端·flutter
snow@li24 分钟前
服务器运维:Alibaba Cloud Linux 4 LTS・Vue前端 Java 后端 K3S 部署 CICD 目录规范清单
linux·前端·vue.js
百变梦仔28 分钟前
Codex 启动回复合格后,我会用三类证据验收前端改动
前端·github
the局外人31 分钟前
别让 Codex 一口气写完整个前端:5 组 Skills,把页面、逻辑、测试和构建拆清楚
前端·人工智能·agent
honkun633 分钟前
vue 表格组件 vxe-table 实实现专业记账凭证编辑表格与自动汇总
前端·javascript·vue.js
前端snow40 分钟前
ai agent ---nest+langchain实现SSE推送信息
前端
IMPYLH42 分钟前
HTML 的 <nav> 元素
前端·html