Skip to content

Comments

feat: support passive wallet_sessionChanged event listeners before connect() in extension contexts#173

Draft
adonesky1 wants to merge 1 commit intomainfrom
ad/create-passive-wallet_sessionChanged-listeners
Draft

feat: support passive wallet_sessionChanged event listeners before connect() in extension contexts#173
adonesky1 wants to merge 1 commit intomainfrom
ad/create-passive-wallet_sessionChanged-listeners

Conversation

@adonesky1
Copy link
Contributor

@adonesky1 adonesky1 commented Feb 12, 2026

Ticket: https://consensyssoftware.atlassian.net/browse/WAPI-1082

Summary

  • Creates a passive DefaultTransport during SDK initialization when the MetaMask extension is detected, enabling wallet_sessionChanged event listeners to work before connect() is called
  • Adds wallet_sessionChanged to the DefaultTransport notification filter — the extension already broadcasts these events but the SDK was silently dropping them
  • Activates window.postMessage listeners when onNotification() is called, not just during connect()
  • Handles passive-to-active transition cleanly when connect() is later called, and avoids sending wallet_revokeSession for sessions the SDK didn't create

Motivation

In configurations where the dapp uses the wallet's own injected provider (native wallet-standard adapter for Solana, or window.ethereum for EVM) for connection, the dapp may also create a MetaMask Connect SDK instance to listen for session change events. Previously, wallet_sessionChanged events could not be received until connect() was called on the SDK because:

  1. No transport was created during init without a stored session
  2. DefaultTransport.onNotification() didn't activate window.postMessage listeners
  3. DefaultTransport.#handleNotification explicitly filtered out wallet_sessionChanged events

Since DefaultTransport and the extension's injected code share the same window.postMessage channel, the SDK can passively observe extension-broadcasted events — it just wasn't wired up to do so.

Changes

packages/connect-multichain/src/multichain/transports/default/index.ts

  1. #handleNotification: Added wallet_sessionChanged to the event whitelist. Also fixed a pre-existing operator precedence issue where the typeof responseData === 'object' guard didn't cover the metamask_accountsChanged check.
  2. onNotification(): Added this.#setupMessageListener() call so window.postMessage listeners are active when notification callbacks are registered (not just when connect() or sendEip1193Message() is called). This is safe — #setupMessageListener() is idempotent.
  3. teardown(): New method that cleans up message listeners and pending requests without sending wallet_revokeSession. Used when tearing down a passive transport that didn't create the session.

packages/connect-multichain/src/multichain/index.ts

  1. #isPassiveTransport: New flag tracking whether the current transport was set up passively for event listening (no SDK-managed connection).
  2. #setupTransport(): When no stored transport exists but the extension is detected on a web platform (DesktopWeb or MetaMaskMobileWebview), creates a passive DefaultTransport and wires up notification listeners. Does NOT call transport.connect(), does NOT write to storage, keeps status as 'loaded'.
  3. #setupDefaultTransport(): Clears the passive flag when transitioning to active mode.
  4. disconnect(): Uses teardown() instead of disconnect() for passive transports to avoid sending wallet_revokeSession for sessions the SDK didn't create. Resets the passive flag.

Test updates

  • packages/connect-multichain/src/init.test.ts: Updated "no transport found during init" assertion — in web environment with extension, passive transport is now expected to exist.
  • packages/connect-multichain/src/connect.test.ts: Updated 4 assertions where sdk.transport was expected to throw in 'loaded' state — now conditional on platform (web has passive transport, others do not).

Test plan

  • Verify passive DefaultTransport is created on web platform with extension installed (no stored session)
  • Verify wallet_sessionChanged events from the extension flow through to core.on('wallet_sessionChanged', handler) registered before connect()
  • Verify standard flow still works: createMultichainClient()connect() → events
  • Verify stored session recovery flow is not affected
  • Verify passive-to-active transition: SDK init (passive) → later call connect() → works correctly
  • Verify disconnect() in passive mode does not send wallet_revokeSession
  • Verify no passive transport is created on non-web platforms (node, RN, mobile web)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant