开发类MetaMask扩展时,无法向PancakeSwap返回响应的问题
开发类MetaMask浏览器扩展时的响应返回问题
我正在开发一款类似MetaMask的浏览器扩展,使用@metamask/providers库向网页注入provider。目前能接收PancakeSwap的JSON RPC请求,用json-rpc-engine处理后,无法将响应返回给网站完成连接流程,试过window.postMessage和metamaskStream.write(data)都无效。
注入页面(inpage)代码
import { WindowPostMessageStream } from "@metamask/post-message-stream"; import { initializeProvider } from "@metamask/providers/dist/initializeInpageProvider"; // contexts const CONTENT_SCRIPT = "contentscript"; const INPAGE = "inpage"; // setup background connection const metamaskStream = new WindowPostMessageStream({ name: INPAGE, target: CONTENT_SCRIPT, }); initializeProvider({ connectionStream: metamaskStream, });
后台(background.js)注入代码
chrome.scripting.registerContentScripts([ { id: "contentscript", matches: ["file://*/*", "http://*/*", "https://*/*"], js: ["inpage-bundle.js"], runAt: "document_start", world: "MAIN", allFrames: true, }, ]);
内容脚本(content script)代码
/*global chrome*/ import { WindowPostMessageStream } from "@metamask/post-message-stream"; import { metamaskStream, provider } from "./inpage"; const Buffer = require("safe-buffer").Buffer; const isManifestV3 = true; // contexts const CONTENT_SCRIPT = "contentscript"; const INPAGE = "inpage"; const setupPageStreams = () => { // the transport-specific streams for communication between inpage and background const pageStream = new WindowPostMessageStream({ name: CONTENT_SCRIPT, target: INPAGE, }); if (isManifestV3) { pageStream.on("data", async ({ data }) => { console.log(data); if (data) { if (data.method === "eth_requestAccounts") { const finalResponse = await new Promise((resolve, reject) => { chrome.runtime.sendMessage( { type: "JSON-RPC", payload: data }, (response) => { console.log(response, "response"); if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); } else if (response && response.type === "JSON-RPC") { resolve(response.payload); } else { reject(new Error("Invalid response received")); } } ); }); if (finalResponse) { const responseToSend = { ...finalResponse, namespace: "global", code: 0, message: "SUCCESS", }; console.log("finalResponse", responseToSend); pageStream.write(responseToSend); } } } }); } }; /** * Initializes two-way communication streams between the browser extension and * the local per-page browser context. This function also creates an event listener to * reset the streams if the service worker resets. */ const initStreams = () => { setupPageStreams(); }; const start = () => { initStreams(); }; start();
问题分析与修复方案
1. 响应格式不符合JSON-RPC规范
@metamask/providers要求响应必须严格遵循JSON-RPC 2.0规范,你当前添加的namespace、code、message自定义字段会导致inpage provider无法识别响应。需要移除这些额外字段,保留标准结构:
// 直接使用后台返回的标准响应,移除自定义字段 const responseToSend = finalResponse;
2. 确保响应ID与请求匹配
JSON-RPC要求响应的id必须和对应请求的id一致,否则网页端会忽略响应。检查后台返回的finalResponse是否携带请求的id,如果没有,手动补充:
const responseToSend = { jsonrpc: "2.0", id: data.id, // 从原始请求中获取ID result: finalResponse.result, };
3. 对齐流的消息结构
inpage端接收的请求是{ data: ... }格式,返回响应时需要保持相同的结构,否则流无法正确解析:
pageStream.write({ data: responseToSend });
4. 完善错误处理
如果请求处理失败,需要返回标准JSON-RPC错误响应,避免静默失败:
pageStream.on("data", async ({ data }) => { console.log(data); if (data?.method === "eth_requestAccounts") { try { const finalResponse = await new Promise((resolve, reject) => { chrome.runtime.sendMessage( { type: "JSON-RPC", payload: data }, (response) => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); } else if (response?.type === "JSON-RPC") { resolve(response.payload); } else { reject(new Error("Invalid response received")); } } ); }); const responseToSend = { jsonrpc: "2.0", id: data.id, result: finalResponse.result, }; pageStream.write({ data: responseToSend }); } catch (error) { const errorResponse = { jsonrpc: "2.0", id: data.id, error: { code: -32000, message: error.message, }, }; pageStream.write({ data: errorResponse }); } } });
5. 确认流的初始化配置
确保content script中的pageStream和inpage中的metamaskStream的name、target完全对应,避免通信方向错误。
内容的提问来源于stack exchange,提问作者Hardil Singh
相关产品推荐
相关产品推荐

