切换浏览器Metamask地址时Web3 getAccounts返回结果不更新如何解决
问题根本原因
- 你服务端的Web3实例绑定的是本地
127.0.0.1:7545的Ganache测试节点,调用web3.eth.getAccounts()返回的是Ganache启动时生成的固定测试账户列表,默认取第一个返回,和用户浏览器中Metamask插件的账户选择状态完全无关。 - Metamask的账户、网络状态仅存储在用户浏览器的插件沙箱环境中,服务端默认无法直接读取该状态,你现有的逻辑相当于直接查本地节点的默认账户,自然不会随Metamask切换而变化。
修复方案
你需要调整逻辑:Metamask相关的账户读取操作放在前端执行,不要通过服务端查Ganache节点拿账户。
1. 前端client.js修改
直接通过浏览器注入的window.ethereum(Metamask提供的API)读取当前账户,同时可以监听账户切换事件自动更新:
// 检查Metamask安装状态并申请授权 async function initMetamask() { if (!window.ethereum) { alert("请先安装Metamask插件"); return false; } // 向用户申请账户访问权限 await window.ethereum.request({ method: 'eth_requestAccounts' }); return true; } async function updateUserAddr() { const isReady = await initMetamask(); if (!isReady) return; // 读取Metamask当前选中的账户 const accounts = await window.ethereum.request({ method: 'eth_accounts' }); const currentAccount = accounts[0]; $('#address_id_poster').text(currentAccount); // 如果业务需要服务端拿到账户,可在这里调用接口把账户传给后端 // await fetch('/save-account?addr=' + currentAccount) } // 监听Metamask账户切换事件,自动更新页面展示 window.ethereum.on('accountsChanged', (accounts) => { $('#address_id_poster').text(accounts[0]); }); // 页面加载时初始化 updateUserAddr();
2. 服务端调整
你可以直接删除原有/get-account接口的逻辑,若业务需要服务端使用当前账户,新增接口接收前端传递的账户参数即可。
额外注意
确保你的Metamask当前连接的网络是本地Ganache测试网,网络配置的RPC地址、链ID要和Ganache启动参数一致,避免链不匹配的问题。
内容的提问来源于stack exchange,提问作者JDS
相关产品推荐
相关产品推荐

