Skip to Content
dApp 接入

Provider API

OneKey 浏览器扩展在用户访问的网页中注入 window.$onekey.ethereum API。网站可通过它请求访问 Ethereum 账户、读取所连接链的数据,以及请求用户签署消息或交易。检测到 provider,并不代表用户已连接账户或授权请求。

Ethereum JavaScript provider API 由 EIP-1193  定义。新应用建议通过 EIP-6963  发现多个钱包 provider,避免浏览器扩展之间的冲突。

Provider 检测

在多钱包环境中,建议使用 EIP-6963 标准发现 provider。

推荐:通过 EIP-6963 支持多钱包

OneKey 支持 EIP-6963。dApp 可通过该标准发现多个已安装的钱包 provider,避免全局注入对象冲突。新集成建议采用这种方式。

// This code snippet demonstrates how to listen for announced providers // and store them for your dApp to use. let onekeyProvider = null; const onAnnounceProvider = (event) => { // The event.detail contains the provider info and the provider object itself. // event.detail = { info: { uuid, name, icon, rdns }, provider } if (event.detail.info.rdns === 'so.onekey.app.wallet') { onekeyProvider = event.detail.provider; } // You can also store all providers in an array to let users choose. }; // Listen for the announcement event from all wallets window.addEventListener('eip6963:announceProvider', onAnnounceProvider); // It's also good practice to dispatch a request event to prompt wallets // that may have loaded after the initial page load. window.dispatchEvent(new Event('eip6963:requestProvider')); // Use the discovered provider when the user selects OneKey and clicks Connect. // Announcements are asynchronous; do not treat a fixed timeout as proof that // the wallet is not installed. Remove the event listener when your UI unmounts.

旧版检测方式与 Provider 对象

为兼容旧版 dApp,OneKey 也会将 provider 注入 window.ethereum。

  • window.ethereum:常用的全局 provider 对象。安装多个钱包时,它可能被其他扩展覆盖。OneKey 提供该对象以兼容已有集成。
  • window.$onekey.ethereum:OneKey 专用命名空间中的 provider,可用于明确选择 OneKey。多钱包发现仍建议使用 EIP-6963。

基本用法

对于任何非简单的以太坊 Web 应用(dApp)来说,你需要完成三个基本任务:

  1. 检测以太坊 Provider: 首先需要确认用户是否安装了像 OneKey 这样的钱包。推荐使用 EIP-6963 标准,如上文 Provider 检测 部分所述。
  2. 访问用户账户: 检测到 provider 后,需要请求查看用户账户的权限。这几乎总是通过在 provider 对象上调用 eth_requestAccounts 方法来完成。
  3. 监控网络变更: 用户可以随时切换不同的网络(如以太坊主网和 Sepolia)。你的 dApp 必须监听 chainChanged 事件以了解当前连接的网络。

Provider 对象是构建完整 Web3 应用的基本工具。虽然你可以直接使用 provider API 进行所有交互,但许多开发者更喜欢使用便捷库来简化开发。我们推荐经过社区验证的强大库,如 ethers.js 或 viem,它们提供更高级的抽象和实用工具。

链 ID

查询当前所选链,不要硬编码钱包支持列表。provider 返回的 Chain ID 为十六进制字符串。

const chainId = await provider.request({ method: 'eth_chainId' }); console.log(chainId); // For example, '0x1' for Ethereum mainnet.

构建交易前,请确认当前链属于应用支持的网络。添加网络的方法见 RPC API。

方法

获取 provider 对象(例如通过 EIP-6963)后,你可以使用以下 EIP-1193 方法与用户钱包交互。

eth_requestAccounts

使用 eth_requestAccounts 从用户钱包请求一个或多个账户。调用此方法通常会向用户显示连接请求弹窗。

try { const accounts = await window.$onekey.ethereum.request({ method: 'eth_requestAccounts' }); // handle accounts } catch (error) { // handle error, e.g., user rejected request }

window.$onekey.ethereum.isConnected()

提示
注意此方法与用户账户无关。
你可能经常会看到”已连接”一词用于描述 Web3 网站是否可以访问用户账户。然而在 provider 接口中,“已连接”和”已断开”指的是 provider 是否可以向当前链发起 RPC 请求。

interface EthereumProvider { isConnected(): boolean; }

如果 provider 已连接到当前链则返回 true,否则返回 false。

如果 provider 未连接,需要重新加载页面以重新建立连接。更多信息请参阅 connect 和 disconnect 事件。

window.$onekey.ethereum.request(args)

interface RequestArguments { method: string; params?: unknown[] | object; } interface EthereumProvider { request(args: RequestArguments): Promise<unknown>; }

使用 request 通过 OneKey 浏览器扩展向以太坊提交 RPC 请求。它返回一个 Promise,解析为 RPC 方法调用的结果。

params 和返回值根据 RPC 方法不同而变化。实际上,如果方法有任何 params,它们几乎总是 Array<any> 类型。

如果请求因任何原因失败,Promise 将以以太坊 RPC 错误拒绝。

OneKey 浏览器扩展支持大多数标准化的以太坊 RPC 方法,以及一些其他钱包可能不支持的方法。

方法详情见 RPC API。

示例

const provider = window.$onekey?.ethereum; if (!provider) throw new Error('OneKey Ethereum provider is unavailable.'); const [from] = await provider.request({ method: 'eth_requestAccounts' }); const to = '<RECIPIENT_EVM_ADDRESS>'; // Replace with a valid 20-byte address. try { const transactionHash = await provider.request({ method: 'eth_sendTransaction', params: [{ from, to, value: '0x0' }], }); console.log('Submitted transaction:', transactionHash); } catch (error) { console.error(error.code, error.message); }

事件

OneKey 浏览器扩展 provider 实现了 Node.js EventEmitter API。本节详细介绍通过该 API 发出的事件。

关于 EventEmitter 的指南有很多,你可以像这样监听事件:

window.$onekey.ethereum.on('accountsChanged', (accounts) => { // Handle the new accounts, or lack thereof. // "accounts" will always be an array, but it can be empty. }); window.$onekey.ethereum.on('chainChanged', (chainId) => { // Handle the new chain. // Correctly handling chain changes can be complicated. // We recommend reloading the page unless you have good reason not to. window.location.reload(); });

connect

interface ConnectInfo { chainId: string; } const handler = (connectInfo: ConnectInfo) => { console.log(connectInfo); }; window.$onekey.ethereum.on('connect', handler);

当 OneKey 浏览器扩展 provider 首次能够向链提交 RPC 请求时,会发出此事件。

我们建议使用 connect 事件处理程序和 window.$onekey.ethereum.isConnected() 方法来确定 provider 何时/是否已连接。

disconnect

const handler = (error: ProviderRpcError) => { console.log(error); }; window.$onekey.ethereum.on('disconnect', handler);

如果 OneKey provider 无法向任何链提交 RPC 请求,则会发出此事件。一般来说,这只会因为网络连接问题或某些意外错误而发生。

一旦发出 disconnect,provider 将不接受任何新请求,直到重新建立与链的连接,这需要重新加载页面。你也可以使用 window.$onekey.ethereum.isConnected() 方法来确定 provider 是否断开连接。

accountsChanged

const handler = (accounts: Array<string>) => { console.log(accounts); }; window.$onekey.ethereum.on('accountsChanged', handler);

eth_accounts RPC 方法的返回值发生变化时,OneKey provider 会发出此事件。eth_accounts 返回向调用方开放的账户地址数组,数组可能为空。每个返回地址均为调用方有权访问的账户。权限按 URL origin 区分,同一 origin 下的页面共享权限。

这意味着每当用户公开的账户地址发生变化时,都会发出 accountsChanged。

chainChanged

提示 使用 eth_chainId 查询当前所选链。

const handler = (chainId: string) => { console.log(chainId); }; window.$onekey.ethereum.on('chainChanged', handler);

当前连接的链发生变化时,OneKey 浏览器扩展 provider 会发出此事件。

所有 RPC 请求都提交到当前连接的链。因此,通过监听此事件来跟踪当前链 ID 非常重要。

处理此事件的常见方式是重新加载页面:

window.$onekey.ethereum.on('chainChanged', (_chainId) => window.location.reload());

message

interface ProviderMessage { type: string; data: unknown; } const handler = (message: ProviderMessage) => { console.log(message); }; window.$onekey.ethereum.on('message', handler);

当 OneKey provider 收到需要通知消费者的消息时,会发出此事件。消息类型由 type 字符串标识。

EIP-1193 通过 message 事件定义 provider 通知。不要假定注入式 provider 支持 eth_subscribe;请在目标钱包和网络中验证所需方法。

错误

OneKey provider 抛出或返回的所有错误都遵循此接口:

interface ProviderRpcError extends Error { message: string; code: number; data?: unknown; }

请求失败时,request(args) 返回的 Promise 会被拒绝。通常可通过错误的 code 属性判断原因。

常见错误码及其含义包括:

  • 4001:请求被用户拒绝。
  • -32602:参数无效。
  • -32603:内部错误。

完整的错误列表请参阅 EIP-1193  和 EIP-1474 。

最后更新于