Chrome扩展接入MetaMask:Web端代码无法检测MetaMask的迁移方案咨询
Chrome扩展适配MetaMask身份验证解决方案
核心原因
原有Web代码失效的根本原因是Chrome扩展的JavaScript运行上下文(包括弹窗页、内容脚本)默认与宿主网页上下文隔离,无法直接访问MetaMask注入到宿主页面的window.ethereum对象。
适配方案(支持Manifest V3主流版本)
1. 配置manifest.json
添加必要权限、注入脚本声明和可访问资源配置:
{ "manifest_version": 3, "name": "你的扩展名称", "version": "1.0.0", "permissions": ["activeTab", "scripting"], "host_permissions": ["<all_urls>"], "action": { "default_popup": "popup.html" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content-script.js"] } ], "web_accessible_resources": [ { "resources": ["inject.js"], "matches": ["<all_urls>"] } ] }
2. 编写页面注入脚本inject.js
该脚本会被注入到宿主页面执行,可以直接访问window.ethereum对象,负责处理MetaMask交互逻辑:
window.addEventListener('message', async (event) => { if (event.source !== window || !event.data.type || event.data.source !== 'custom-extension') return if (event.data.type === 'REQUEST_METAMASK_ACCOUNTS') { if (!window.ethereum) { window.postMessage({ type: 'METAMASK_ACCOUNTS_RESPONSE', source: 'custom-extension', error: 'MetaMask not installed' }, '*') return } try { const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }) window.postMessage({ type: 'METAMASK_ACCOUNTS_RESPONSE', source: 'custom-extension', data: accounts }, '*') } catch (e) { window.postMessage({ type: 'METAMASK_ACCOUNTS_RESPONSE', source: 'custom-extension', error: e.message }, '*') } } })
3. 编写桥接用内容脚本content-script.js
负责在扩展上下文和宿主页面之间转发消息:
// 向宿主页面注入inject.js const injectScript = document.createElement('script') injectScript.src = chrome.runtime.getURL('inject.js') document.documentElement.appendChild(injectScript) injectScript.onload = () => injectScript.remove() // 接收页面返回的MetaMask消息,转发到扩展弹窗 window.addEventListener('message', (event) => { if (event.source !== window || !event.data.type || event.data.source !== 'custom-extension') return if (event.data.type === 'METAMASK_ACCOUNTS_RESPONSE') { chrome.runtime.sendMessage(event.data) } }) // 接收扩展弹窗的请求,转发到页面 chrome.runtime.onMessage.addListener((message) => { if (message.type === 'REQUEST_METAMASK_ACCOUNTS' && message.source === 'custom-extension') { window.postMessage(message, '*') } })
4. 改造原有弹窗逻辑(popup.js)
替换原有直接访问window.ethereum的逻辑,改为通过消息传递调用MetaMask能力:
function toggleButton() { const loginButton = document.getElementById("login-button"); loginButton.addEventListener("click", loginWithMetaMask); } async function loginWithMetaMask() { const [currentTab] = await chrome.tabs.query({active: true, currentWindow: true}) chrome.tabs.sendMessage(currentTab.id, { type: 'REQUEST_METAMASK_ACCOUNTS', source: 'custom-extension' }, (response) => { const loginButton = document.getElementById("login-button"); if (response.error) { if (response.error === 'MetaMask not installed') { loginButton.innerText = "请先安装MetaMask"; } console.error(response.error) return } const userWallet = document.getElementById("user-wallet"); userWallet.innerText = response.data[0]; }) } window.addEventListener("DOMContentLoaded", toggleButton);
注意事项
- 调试时请确保当前激活的标签页为普通网页,Chrome内置页面(如chrome://extensions/)无法注入脚本,会导致调用失败
- 首次请求账号时会弹出MetaMask授权窗口,用户完成授权后即可正常获取钱包地址
内容的提问来源于stack exchange,提问作者RonKon
相关产品推荐
相关产品推荐

