多钱包
DApp 链接多个钱包,是指在初始化时提供多个钱包选项供用户选择。
技术层面的实现方法
- 提供选项列表。
- 根据选择的选项初始化提供者。
- 使用提供者的 API 集成业务逻辑。
- 通过断开连接并重新选择来切换钱包。
Bitget Wallet 检测器
- 应用内浏览器:
var isBitgetWallet = navigator.userAgent.indexOf('BitKeep') > 0
- 桌面浏览器:
var isBitgetWallet = window.bitkeep
如何开发 DApp 连接多个钱包
在开发 DApp 时,允许用户选择和连接多个钱包是一个关键功能。在这里,我们将详细解释如何在不使用第三方钱包连接库的情况下实现此功能,以及如何使用第三方钱包连接库来实现。
不使用第三方钱包连接库的方法
1. 配置钱包列表
首先,我们需要配置支持的钱包列表。这可以使用简单的 JavaScript 对象来完成:
const walletList = [
{
name: 'MetaMask',
provider: window.ethereum,
check: () => window.ethereum && window.ethereum.isMetaMask,
},
{
name: 'Bitget Wallet',
provider: window.bitkeep,
check: () => window.bitkeep && window.bitkeep.isBitKeep,
},
// 可以在此添加其他钱包
]
2. 检测钱包是否已安装
接下来,我们需要检测用户是否已安装这些钱包。这可以通过遍历钱包列表并调用每个钱包的检查方法来完成:
function detectWallets() {
return walletList.filter((wallet) => wallet.check())
}
3. 管理已连接钱包状态
为了管理连接状态,我们可以使用 React 的useState
钩子创建状态变量:
const [connectedWallet, setConnectedWallet] = useState(null)
4. 连接钱包
用户选择钱包后,我们可以使用相应钱包的提供者连接钱包:
async function connectWallet(wallet) {
if (!wallet.provider) {
alert('请安装钱包扩展')
return
}
try {
const accounts = await wallet.provider.request({
method: 'eth_requestAccounts',
})
if (accounts?.[0]) {
// 如果连接成功,钱包通常会返回账户信息。您也可以在此保存账户。
setConnectedWallet(wallet)
}
} catch (error) {
console.error('连接钱包失败:', error)
}
}
5. 调用钱包 API
连接钱包后,我们可以使用钱包的provider
调用钱包 API,例如获取账户地址:
async function getAccount() {
if (!connectedWallet) return null
const accounts = await connectedWallet.provider.request({
method: 'eth_accounts',
})
return accounts[0]
}
6. 断开钱包连接
1. 监听钱包断开连接事件
以 Bitget Wallet 为例,您可以监听disconnect
事件(您也可以监听accountsChanged
返回空数组[]作为断开连接的依据):
useEffect(() => {
if (connectedWallet) {
connectedWallet.provider.on('disconnect', handleDisconnect)
}
//清理事件监听器
return () => {
if (connectedWallet) {
connectedWallet.provider.removeListener('disconnect', handleDisconnect)
}
}
}, [connectedWallet])
function handleDisconnect() {
console.log('钱包已断开连接')
disconnectWallet()
}
2. 断开连接逻辑
我们需要定义断开连接的逻辑,例如清除状态并通知用户:
function disconnectWallet() {
setConnectedWallet(null)
setAccount(null)
alert('钱包已断开连接')
}
7. 重置页面
为了确保页面状态一致,我们可以在断开钱包连接时重置页面:
function resetPage() {
disconnectWallet()
//其他页面重置逻辑
}
重置页面后,用户可以重新连接到另一个钱包,连接过程与上述相同。这完成了多钱包连接之间的切换操作。
使用第三方钱包连接库的方法
为了简化钱包连接的实现,我们可以使用第三方库,这些库通常可以轻松管理钱包连接和断开连接操作。
在这里,以Web3Modal
为例,我们提供示例代码和文档说明。
1. 使用 Web3Modal
Web3Modal 是一个流行的钱包连接库,支持多个钱包。
安装
npm install web3modal wagmi @tanstack/react-query
示例代码
import { defaultWagmiConfig } from '@web3modal/wagmi/react/config'
import React, { useEffect } from 'react'
import {
createWeb3Modal,
useWeb3Modal,
useWeb3ModalEvents,
useWeb3ModalState,
useWeb3ModalTheme,
} from '@web3modal/wagmi/react'
import { WagmiProvider } from 'wagmi'
import { arbitrum, mainnet } from 'wagmi/chains'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
// 0. 为WAGMIv2初始化queryClient
const queryClient = new QueryClient()
// 1. 获取projectId
const projectId = import.meta.env.VITE_PROJECT_ID
if (!projectId) {
throw new Error('VITE_PROJECT_ID未设置')
}
// 2. wagmiConfig
const wagmiConfig = defaultWagmiConfig({
chains: [mainnet, arbitrum],
projectId,
metadata: {
name: 'Web3Modal React示例',
description: 'Web3Modal React示例',
url: '',
icons: [],
},
})
// 3. 创建模态框
createWeb3Modal({
wagmiConfig,
projectId,
themeMode: 'light',
themeVariables: {
'--w3m-color-mix': '#00DCFF',
'--w3m-color-mix-strength': 20,
},
})
export default function App() {
// 4. 使用模态框钩子
const { walletProvider } = useWeb3ModalProvider()
const event = useWeb3ModalEvents()
useEffect(() => {
if (
event.data.event === 'DISCONNECT_SUCCESS' ||
(event.data.event === 'MODAL_CLOSE' && !event.data.properties.connected)
) {
// 参考不使用第三方库断开钱包链接的方法。断开连接后,重新连接钱包以完成钱包切换操作。
handleDisconnect()
}
}, [event])
useEffect(() => {
// 管理钱包链接状态
if (walletProvider) {
setConnectedWallet(walletProvider)
} else {
setConnectedWallet(null)
}
}, [walletProvider])
return (
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<w3m-button />
<w3m-network-button />
<w3m-connect-button />
<w3m-account-button />
...
</QueryClientProvider>
</WagmiProvider>
)
}
文档说明
相关阅读
Last updated on