Skip to Content

React + wagmi

本指南演示如何在 React 应用中,使用 wagmi 和 EIP-1193 连接 OneKey。使用 OneKey 专用 provider(window.$onekey.ethereum),确保标为“OneKey”的按钮确实连接 OneKey。

安装

npm i wagmi@^2 viem@^2 @tanstack/react-query@^5

wagmi v2 基于 viem 构建。本指南使用 Injected 连接器来支持注入式钱包(OneKey / 其他 EIP-1193 Provider)。

创建 OneKey 注入式连接器

优先使用 OneKey 的专用注入,以避免多钱包环境下的歧义。

// onekeyConnector.ts import { createConfig, http } from 'wagmi' import { mainnet, polygon, arbitrum, base, optimism } from 'wagmi/chains' import { injected } from 'wagmi/connectors' import type { EIP1193Provider } from 'viem' function getOneKeyProvider(): EIP1193Provider | undefined { if (typeof window === 'undefined') return undefined const walletWindow = window as Window & { $onekey?: { ethereum?: EIP1193Provider } } return walletWindow.$onekey?.ethereum } export const config = createConfig({ chains: [mainnet, polygon, arbitrum, base, optimism], connectors: [ injected({ target() { return { id: 'onekey', name: 'OneKey', provider: getOneKeyProvider(), } }, shimDisconnect: true, }), ], transports: { [mainnet.id]: http(), [polygon.id]: http(), [arbitrum.id]: http(), [base.id]: http(), [optimism.id]: http(), }, })

说明

  • 优先使用 window.$onekey.ethereum,在多钱包环境中明确选择 OneKey。
  • OneKey 不可用时,显示安装或重试入口。wagmi 发现的其他钱包保留各自名称。
  • 由用户操作触发 eth_requestAccounts,处理 4001(用户拒绝),不要自动重试。

应用设置

// main.tsx import React from 'react' import ReactDOM from 'react-dom/client' import { WagmiProvider } from 'wagmi' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { config } from './onekeyConnector' import App from './App' const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> <App /> </QueryClientProvider> </WagmiProvider> </React.StrictMode>, )

连接和读取账户

// App.tsx import { useAccount, useConnect, useDisconnect } from 'wagmi' export default function App() { const { address, isConnected } = useAccount() const { connect, connectors, isPending, error } = useConnect() const { disconnect } = useDisconnect() if (isConnected) { return ( <div> <p>Connected: {address}</p> <button onClick={() => disconnect()}>Disconnect</button> </div> ) } return ( <div> {error && <p role="alert">{error.message}</p>} {connectors.map((c) => ( <button key={c.uid} disabled={isPending} onClick={() => connect({ connector: c })}> Connect with {c.name} </button> ))} </div> ) }

签名和发送

通过当前 wagmi 连接发起签名。钱包请求应由用户操作触发,并在界面中显示被拒绝的请求。

import { useState } from 'react' import { useWalletClient } from 'wagmi' function SignMessageButton() { const { data: walletClient } = useWalletClient() const [result, setResult] = useState('') const [pending, setPending] = useState(false) async function sign() { if (!walletClient) return setPending(true) try { const signature = await walletClient.signMessage({ message: 'Hello from my dApp' }) setResult(signature) } catch (error) { setResult(error instanceof Error ? error.message : 'Signature request failed') } finally { setPending(false) } } return <> <button disabled={!walletClient || pending} onClick={sign}>Sign message</button> <p role="status">{result}</p> </> }

发送交易时,使用 wagmi 的 useSendTransaction,并检查收款地址、金额和所选链。返回交易哈希表示已提交;需要等待回执才能判断执行是否成功。参见发送交易。

事件和网络

  • 监听 accountsChanged / chainChanged 事件并相应更新会话状态。
  • 网络切换/添加:使用 wallet_switchEthereumChain 和 wallet_addEthereumChain。

移动端与钱包发现

在没有注入 provider 的移动浏览器中,使用 WalletConnect 连接器或钱包 UI 库。深度链接负责打开钱包,WalletConnect 会话负责建立连接。

wagmi 可通过 createConfig 的 multiInjectedProviderDiscovery 选项发现 EIP-6963 钱包。直接实现的方式见 Provider 检测。

故障排除

  • provider 不存在时,确认 OneKey 已安装并获准在本站运行,再由用户点击“连接”重试。
  • 用户拒绝请求(4001)后,允许其再次主动尝试。
  • 仅在客户端访问浏览器 provider。上方 typeof window 检查用于避免服务端渲染错误。
  • 模拟断开连接会清除 wagmi 的连接状态,但不一定撤销钱包中的权限。

资源

最后更新于