本页目录
React + wagmi
本指南演示如何在 React 应用中,使用 wagmi 和 EIP-1193 连接 OneKey。使用 OneKey 专用 provider(window.$onekey.ethereum),确保标为“OneKey”的按钮确实连接 OneKey。
安装
npm i wagmi@^2 viem@^2 @tanstack/react-query@^5wagmi 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 的连接状态,但不一定撤销钱包中的权限。
资源
最后更新于