如何使用ethers.js检测MetaMask等Web3钱包是否处于解锁状态
检测Web3钱包解锁状态的稳定通用方案
目前不存在所有钱包都通用的直接检测API,但是可以通过EIP-1102、EIP-1193规定的标准钱包交互逻辑间接实现,兼容绝大多数遵守EIP规范的钱包(包括MetaMask、Coinbase Wallet、WalletConnect等),不需要依赖MetaMask私有的实验性方法。
核心实现逻辑
- 核心原理是调用钱包标准RPC方法
eth_accounts:钱包解锁且已授权当前站点时,会直接返回账户列表;如果未授权,调用eth_requestAccounts会触发授权弹窗;如果钱包处于锁定状态,会先触发解锁弹窗,解锁完成后才会进入授权流程。 - 如果需要纯静默检测不触发弹窗,可以通过
eth_accounts的返回结果判断,不会触发任何用户交互。
代码实现(基于ethers.js v6)
场景1:检测同时允许触发解锁/授权弹窗(适合登录场景)
import { BrowserProvider } from "ethers"; async function checkWalletUnlocked() { if (!window.ethereum) throw new Error("未检测到Web3钱包"); const provider = new BrowserProvider(window.ethereum); try { const accounts = await provider.send("eth_accounts", []); if (accounts.length > 0) { // 已解锁且已授权 return true; } // 已解锁但未授权,触发授权流程 await provider.send("eth_requestAccounts", []); return true; } catch (err) { // 错误码4001代表用户主动拒绝解锁/授权 if (err.code === 4001) return false; // 其余错误默认判定为钱包未解锁/不可用 return false; } }
场景2:静默检测不触发任何弹窗(适合页面初始化状态判断)
async function checkWalletUnlockedSilent() { if (!window.ethereum) return false; const provider = new BrowserProvider(window.ethereum); try { const accounts = await provider.send("eth_accounts", []); // 只有已解锁且已授权的场景才会返回非空账户列表 return accounts.length > 0; } catch (err) { return false; } }
说明
上述实现完全基于公开的EIP标准RPC方法,没有使用任何钱包私有API,稳定性远高于MetaMask私有的window.ethereum._metamask.isUnlocked()实验性方法。
注意:静默检测只能识别「已解锁且已授权当前站点」的状态,如果用户解锁了钱包但从未给当前站点授权,静默检测也会返回false,这种场景需要主动触发一次eth_requestAccounts调用才能确认解锁状态。
内容的提问来源于stack exchange,提问作者Fmerco
相关产品推荐
相关产品推荐

