Fix wallet bridge on Firefox: use postMessage instead of CustomEvent

Manual testing on Zen/Firefox surfaced "Uncaught Error: Permission
denied to access property 'id'" the moment the isolated-world relay
dispatched a CustomEvent to the world:'MAIN' injected script. That's
a Firefox-specific Xray-wrapper restriction: a CustomEvent's `detail`
object created in one world can't have its properties read from the
other, even though the event itself fires fine. Chromium doesn't
enforce this, which is why it wasn't caught until testing on the
actual target browser (Zen).

Switched both sides of the bridge (wallet-bridge/inject.ts,
wallet-bridge/relay.ts) to window.postMessage with a `channel` field
and same-window source check, since postMessage structured-clones
its payload across the boundary correctly on both browsers -- the
same approach Phantom's own inpage<->content-script bridge uses.

Also added [nexa/...]-prefixed console.debug breadcrumbs through the
wallet-connect/wallet-bridge/wallet-auth chain, since diagnosing this
without them (previous commit shipped none) took several rounds of
"nothing happened" back and forth.

Still not fully verified end-to-end against live Phantom -- the
crash is fixed, but a full connect -> sign -> verify round trip
hasn't been confirmed yet. See CLAUDE.md.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YXiHuScXrjxBh7yFGAPq3B
This commit is contained in:
2026-09-07 12:59:04 +02:00
co-authored by claude
parent 56a2ff9930
commit 140616a3e4
6 changed files with 66 additions and 30 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ export default defineBackground(() => {
case 'nexa:wallet-connected':
handleWalletConnected(sender.tab?.id, message.walletAddress)
.then(() => ws.reconnectNow())
.catch(() => undefined); // signing/verify failed — ws-client's own retry loop keeps trying
.catch((err) => console.debug('[nexa/background] wallet auth failed:', err)); // ws-client's own retry loop keeps trying regardless
return false;
default: