691 字
3 分钟
EIP-1193 And EIP-6963
EIP-1193 定义了标准化的 window.ethereum 接口,让 DApp 能够与钱包交互。而 EIP-6963 是为了解决多个钱包同时注入 window.ethereum 导致的冲突问题,引入了多 Provider 发现机制,通过事件监听和派发来注册和发现不同的钱包 Provider。
EIP-1193 (以太坊提供者标准)
- 统一钱包/DApp 通信接口
- 规范基础方法(请求账户/切换网络)
- 定义标准事件模型
- 提供错误处理规范
核心功能实现
window.ethereum = {
// 基础方法
request: async ({ method, params }) => {
// 示例:请求账户
if (method === 'eth_requestAccounts') {
return ['0x...'] // 返回账户数组
}
},
// 事件监听
on: (event, callback) => {
// 关键事件:
// - accountsChanged 账户变更
// - chainChanged 网络切换
}
}
EIP-6963
- 解决多钱包冲突问题
- 标准化钱包元数据格式
info: { uuid: "350670db-19fa-4704...", name: "MetaMask", icon: "data:image/svg+xml,...", rdns: "io.metamask" // 反向域名标识 }
- 支持 DApp 同时连接多个钱包
核心功能实现
const walletInfo = {
uuid: "your-wallet-unique-id", // 唯一标识
name: "YourWalletName", // 钱包名称
icon: "data:image/svg+xml,...",// 钱包图标(Base64 或 URL)
provider: yourProviderObject // 符合 EIP-1193 的 Provider
};
// 多钱包发现机制
window.addEventListener('eip6963:announceProvider', (event) => {
const { info, provider } = event.detail
console.log('发现钱包:', info.name)
})
// 钱包方广播自身
new CustomEvent("eip6963:announceProvider", {
detail: { info: Object.freeze(walletInfo) },
})
钱包实现方的兼容方案
钱包需要同时支持 EIP-1193(传统 window.ethereum 注入)和 EIP-6963(多 Provider 发现),以覆盖新旧 DApp 的需求。
同时注入两种 Provider:
- 保留对 window.ethereum 的注入(EIP-1193)。
- 通过 事件广播 注册自己的 Provider(EIP-6963)。
// 钱包的注入逻辑
if (!window.ethereum) {
window.ethereum = myProvider; // EIP-1193
}
// EIP-6963 注册逻辑
const info = {
uuid: 'my-wallet-uuid',
name: 'MyWallet',
icon: 'data:image/png;base64,...',
provider: myProvider,
};
window.dispatchEvent(
new CustomEvent('eip6963:announceProvider', {
detail: Object.freeze({ info }),
})
);
DApp 接入方的兼容方案
DApp 需要同时支持 EIP-1193(传统单 Provider)和 EIP-6963(多 Provider 发现),确保无论用户使用哪种钱包都能正常工作。
- 优先使用 EIP-6963 发现多 Provider:
- 监听 eip6963
事件,收集所有可用 Provider。 - 允许用户选择具体使用的钱包。
- 监听 eip6963
const providers = new Map();
// 监听 EIP-6963 的 Provider 注册事件
window.addEventListener('eip6963:announceProvider', (event) => {
const { info } = event.detail;
providers.set(info.uuid, info);
});
// 主动请求已注册的 Provider(兼容部分钱包的实现)
window.dispatchEvent(new Event('eip6963:requestProvider'));
- 回退到 EIP-1193 的 window.ethereum:
- 如果没有通过 EIP-6963 发现 Provider,则检查 window.ethereum。
let selectedProvider;
// 如果存在 EIP-6963 的 Provider
if (providers.size > 0) {
// 显示 UI 让用户选择钱包
selectedProvider = await selectProviderFromList(providers);
}
// 回退到 EIP-1193
else if (window.ethereum) {
selectedProvider = window.ethereum;
} else {
throw new Error('No Ethereum provider found');
}
- 统一操作接口:
- 无论通过哪种方式获取 Provider,最终都使用 EIP-1193 的标准方法(如 eth_requestAccounts, eth_sendTransaction)。
// 请求用户授权
const accounts = await selectedProvider.request({
method: 'eth_requestAccounts',
});
// 发送交易
const txHash = await selectedProvider.request({
method: 'eth_sendTransaction',
params: [txParams],
});
EIP-1193 And EIP-6963
https://alexdev.top/posts/eip-1193_and_eip6963/post/