下载

arrow_down

构建

arrow_down

更多

arrow_down
activityactivityactivityactivity
  • themelight
  • languageIcon

  • menu
Skip to Content

Wagmi

Wagmi 通过优先考虑开发者体验、性能、功能覆盖和稳定性,使应用程序开发者能够专注于为以太坊构建高质量、高性能的体验。它为开发者提供直观的构建块来创建他们的以太坊应用程序。

本节将介绍如何将 Bitget WalletBitget Wallet Lite 集成到 Wagmi 系统中。

快速开始

1.安装依赖

pnpm add wagmi

2.配置链和提供者

import { configureChains, allChains } from 'wagmi' import { alchemyProvider } from 'wagmi/providers/alchemy' import { publicProvider } from 'wagmi/providers/public' // 使用 Alchemy 提供者配置链和提供者。 // 两个流行的提供者是 Alchemy (alchemy.com) 和 Infura (infura.io) const { chains, provider } = configureChains(allChains, [ alchemyProvider(), publicProvider(), ])

3.创建 BitgetWalletConnector

import { InjectedConnector } from 'wagmi/connectors/injected' class BitgetWalletConnector extends InjectedConnector { constructor({ chains = [], options_ = {} }) { const options = { name: 'BitgetWallet', ...options_, } super({ chains, options }) this.id = 'BitgetWallet' this.ready = typeof window != 'undefined' && !!this.findProvider(window?.bitkeep?.ethereum) } async getProvider() { if (typeof window !== 'undefined') { // TODO: Fallback to `ethereum#initialized` event for async injection // https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection= this.provider = window.bitkeep?.ethereum } return this.provider } getReady(ethereum) { if (!ethereum.isBitKeep || !ethereum) return // Brave tries to make itself look like BitKeep // Could also try RPC `web3_clientVersion` if following is unreliable if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return if (ethereum.isTokenPocket) return if (ethereum.isTokenary) return return ethereum } findProvider(ethereum) { if (ethereum?.providers) return ethereum.providers.find(this.getReady) return this.getReady(ethereum) } }

4.创建 BitgetWalletLiteConnector

import { InjectedConnector } from 'wagmi/connectors/injected' import { OmniConnect } from '@bitget-wallet/omni-connect' class BitgetWalletLiteConnector extends InjectedConnector { constructor({ chains = [], options_ = {} }) { const options = { name: 'BitgetWallet', ...options_, } super({ chains, options }) this.id = 'BitgetWallet' this.ready = typeof window != 'undefined' && !!this.findProvider(window?.bitkeep?.ethereum) this.omni = new OmniConnect({ metadata: { name: options_.dappName, iconUrl: options_.dappIconUrl, url: options_.dappUrl, privacyPolicyUrl: '', termsOfUseUrl: '', }, namespace: { eip155: { chains: chains, // methods: ["eth_sign", "personal_sign"], // events: ["accountsChanged", "chainChanged"], }, }, }) } async getProvider() { if (typeof window !== 'undefined') { // TODO: Fallback to `ethereum#initialized` event for async injection // https://github.com/BitKeep/detect-provider#synchronous-and-asynchronous-injection= this.provider = this.omni?.eip155?.provider } return this.provider } getReady(ethereum) { if (!ethereum.isBitKeep || !ethereum) return // Brave tries to make itself look like BitKeep // Could also try RPC `web3_clientVersion` if following is unreliable if (ethereum.isBraveWallet && !ethereum._events && !ethereum._state) return if (ethereum.isTokenPocket) return if (ethereum.isTokenary) return return ethereum } findProvider(ethereum) { if (ethereum?.providers) return ethereum.providers.find(this.getReady) return this.getReady(ethereum) } }

5.设置客户端

import { createClient } from 'wagmi' import { MetaMaskConnector } from 'wagmi/connectors/metaMask' import BitgetWalletConnector from './connectors/BitgetWalletConnector' const mainnetIds = [1, 10, 137, 42161] // BitgetWallet 目前只支持主网网络 // 设置客户端 const client = createClient({ autoConnect: true, connectors: [ new MetaMaskConnector({ chains }), new BitgetWalletConnector({ chains: chains.filter((v) => mainnetIds.includes(v.id)), options: { name: 'BitgetWallet', icon: './assets/bitkeep-icon.png', }, }), new BitgetWalletConnector({ chains: chains.filter((v) => mainnetIds.includes(v.id)), options: { name: 'BitgetWallet', iconUrl: './assets/bitkeep-icon.png', dappName: 'your dappName', dappIconUrl: 'your dappIconUrl', dappUrl: 'your dappUrl', }, }), ], provider, })

在 React 应用中使用

import { WagmiConfig, useConnect, useAccount, useDisconnect, useSignMessage, useNetwork, useSwitchNetwork, } from 'wagmi' import { verifyMessage } from 'ethers/lib/utils' const { isConnected, connector } = useAccount() const { connect, connectors, error, isLoading, pendingConnector } = useConnect() const { disconnect } = useDisconnect() export function NetworkSwitcher() { const { chain } = useNetwork() const { chains, error, isLoading, pendingChainId, switchNetwork } = useSwitchNetwork() if (!chain) return null return ( <div> <div> 连接到 {chain.name ?? chain.id} {chain.unsupported && ' (不支持)'} </div> {switchNetwork && ( <div> {chains .filter((x) => x.id !== chain.id) .map((x) => ( <button disabled={!switchNetwork || x.id === pendingChainId} key={x.id} onClick={() => switchNetwork(x.id)} > 切换到 {x.name ?? x.id} {isLoading && x.id === pendingChainId && ' (切换中)'} </button> ))} </div> )} <div>{error && error.message}</div> </div> ) } function Profile() { const { address, isConnected } = useAccount() const { data, error, isLoading, signMessage } = useSignMessage({ message: 'gm wagmi frens', }) const { disconnect } = useDisconnect() if (isConnected) { return ( <div> <div>连接到 {address}</div> <button onClick={() => signMessage()}>签名消息</button> <button onClick={() => disconnect()}>断开连接</button> <NetworkSwitcher /> </div> ) } return ( <div> {connectors.map((connector) => ( <button disabled={!connector.ready} key={connector.id} onClick={() => connect({ connector })} > {connector.name} {!connector.ready && ' (不支持)'} {isLoading && connector.id === pendingConnector?.id && ' (连接中)'} </button> ))} {error && <div>{error.message}</div>} </div> ) } function App() { return ( <WagmiConfig client={client}> <Profile /> </WagmiConfig> ) }

连接钱包

使用 Hook

import { useConnect, useAccount } from 'wagmi' function ConnectWallet() { const { connect, connectors, isPending } = useConnect() const { address, isConnected } = useAccount() if (isConnected) { return <div>连接到 {address}</div> } return ( <div> {connectors.map((connector) => ( <button key={connector.id} onClick={() => connect({ connector })} disabled={isPending} > 连接到 {connector.name} </button> ))} </div> ) }

获取账户信息

import { useAccount, useBalance, useEnsName } from 'wagmi' function Account() { const { address, isConnected } = useAccount() const { data: balance } = useBalance({ address, }) const { data: ensName } = useEnsName({ address, }) if (!isConnected) return <div>未连接</div> return ( <div> <div>地址: {ensName || address}</div> <div> 余额: {balance?.formatted} {balance?.symbol} </div> </div> ) }

发送交易

import { useSendTransaction, useAccount } from 'wagmi' import { parseEther } from 'viem' function SendTransaction() { const { address } = useAccount() const { sendTransaction, isPending } = useSendTransaction() const handleSend = () => { sendTransaction({ to: '0x...', value: parseEther('0.01'), }) } return ( <button onClick={handleSend} disabled={isPending}> {isPending ? '发送中...' : '发送 0.01 ETH'} </button> ) }

合约交互

读取合约

import { useReadContract } from 'wagmi' const erc20Abi = [ { name: 'balanceOf', type: 'function', stateMutability: 'view', inputs: [{ name: 'account', type: 'address' }], outputs: [{ name: '', type: 'uint256' }], }, ] as const function TokenBalance() { const { address } = useAccount() const { data: balance } = useReadContract({ address: '0x...', abi: erc20Abi, functionName: 'balanceOf', args: [address], }) return <div>代币余额: {balance?.toString()}</div> }

写入合约

import { useWriteContract } from 'wagmi' function TransferToken() { const { writeContract, isPending } = useWriteContract() const handleTransfer = () => { writeContract({ address: '0x...', abi: erc20Abi, functionName: 'transfer', args: ['0x...', parseEther('1')], }) } return ( <button onClick={handleTransfer} disabled={isPending}> {isPending ? '转账中...' : '转账 1 代币'} </button> ) }

签名消息

import { useSignMessage } from 'wagmi' function SignMessage() { const { signMessage, isPending } = useSignMessage() const handleSign = () => { signMessage({ message: 'Hello from Bitget Wallet!', }) } return ( <button onClick={handleSign} disabled={isPending}> {isPending ? '签名中...' : '签名消息'} </button> ) }

网络切换

import { useSwitchChain } from 'wagmi' function SwitchNetwork() { const { switchChain, chains } = useSwitchChain() return ( <div> {chains.map((chain) => ( <button key={chain.id} onClick={() => switchChain({ chainId: chain.id })} > 切换到 {chain.name} </button> ))} </div> ) }

监听事件

import { useWatchContractEvent } from 'wagmi' function EventListener() { useWatchContractEvent({ address: '0x...', abi: erc20Abi, eventName: 'Transfer', onLogs: (logs) => { console.log('新的转账事件:', logs) }, }) return <div>监听转账事件...</div> }

断开连接

import { useDisconnect } from 'wagmi' function DisconnectWallet() { const { disconnect } = useDisconnect() return <button onClick={() => disconnect()}>断开连接</button> }

完整示例

import { useAccount, useConnect, useDisconnect, useBalance } from 'wagmi' function WalletConnection() { const { address, isConnected } = useAccount() const { connect, connectors } = useConnect() const { disconnect } = useDisconnect() const { data: balance } = useBalance({ address }) if (isConnected) { return ( <div> <div>地址: {address}</div> <div> 余额: {balance?.formatted} {balance?.symbol} </div> <button onClick={() => disconnect()}>断开连接</button> </div> ) } return ( <div> {connectors.map((connector) => ( <button key={connector.id} onClick={() => connect({ connector })}> 连接到 {connector.name} </button> ))} </div> ) }

注意事项

  1. 版本兼容性: 确保使用兼容的 wagmi 和 viem 版本
  2. 错误处理: 使用 error 状态处理连接和交易错误
  3. 性能优化: 合理使用 React Query 的缓存机制
  4. 类型安全: 充分利用 TypeScript 的类型推断

相关资源

Last updated on