Support Phantom account switching and add sign-out

Wires Phantom's own accountChanged/disconnect provider events
(inject.ts) so switching accounts or disconnecting directly in
Phantom's UI is detected, not just our own connect/sign calls --
relayed as unsolicited postMessage events (relay.ts's onWalletEvent)
since they aren't a response to any request we made.

Adds a "Sign out" button in the popup (nexa:sign-out) that clears the
stored session, force-closes the WS connection via a new
ws-client.ts disconnect() (distinct from reconnectNow() -- it also
suppresses auto-reconnect until a new wallet connects), and asks the
content script to call provider.disconnect(), which revokes
Phantom's trust for the origin so the next silent connect correctly
fails until the user reconnects.

Fixes a real bug this surfaced: the existing "skip re-auth if a
session token exists" check in background.ts only checked for *any*
token, so switching Phantom accounts would have silently kept
authenticating as the old wallet. Session storage now tracks which
wallet it belongs to (backend-client.ts's storeSession(token,
walletAddress)) so the handler can tell "already signed in" apart
from "signed in as a different wallet than the one that just
connected."

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YXiHuScXrjxBh7yFGAPq3B
This commit is contained in:
2026-09-07 13:48:05 +02:00
co-authored by claude
parent 9f06a83b64
commit b93a9c6f10
11 changed files with 206 additions and 47 deletions
+5 -1
View File
@@ -21,8 +21,12 @@ export type NexaMessage =
// Wallet auth (content script <-> background). See
// content-scripts/wallet-connect.ts and background/wallet-auth.ts.
| { type: 'nexa:wallet-connected'; walletAddress: string }
| { type: 'nexa:wallet-disconnected' }
| { type: 'nexa:wallet-sign-request'; nonce: string }
| { type: 'nexa:request-wallet-connect' };
| { type: 'nexa:request-wallet-connect' }
| { type: 'nexa:wallet-disconnect-request' }
// Sign-out (popup -> background). See entrypoints/popup/App.tsx.
| { type: 'nexa:sign-out' };
/** Response shape for 'nexa:wallet-sign-request', returned via sendResponse (not a dispatched NexaMessage). */
export type WalletSignResult = { signature: string } | { error: string };