Skip to content

@metamask/connect-evm v0.9.0 uses browser transport (window.postMessage) on React Native instead of WebSocket relay #254

@lonestarx1

Description

@lonestarx1

Bug Description

@metamask/connect-evm v0.9.0 does not work on React Native because it resolves to the browser transport (windowPostMessageTransport) instead of the React Native WebSocket transport.

Root Cause

The package resolution chain breaks on React Native:

  1. @metamask/connect-evm has no react-native export in package.json:

    // connect-evm/package.json exports
    ".": {
      "import": "...",
      "require": "...",
      "default": "..."
      // ❌ No "react-native" condition
    }
  2. @metamask/multichain-api-client also has no react-native export:

    // multichain-api-client/package.json exports
    ".": {
      "import": "...",
      "require": "..."
      // ❌ No "react-native" condition
    }
  3. @metamask/connect-multichain does have a react-native export with WebSocketTransport (using wss://mm-sdk-relay.api.cx.metamask.io), but it's never reached because:

  4. The DefaultTransport class in connect-multichain imports getDefaultTransport() from @metamask/multichain-api-client, which always returns windowPostMessageTransport — a browser-only transport using window.postMessage().

Result

On React Native:

  • client.connect() hangs indefinitely — window.postMessage() is a no-op
  • window.addEventListener('message', ...) never receives responses
  • MetaMask deep link is never triggered (the SDK never reaches that code path)
  • No error is thrown — the connection just silently hangs

Expected Behavior

createEVMClient() should use the WebSocketTransport (Centrifuge relay at wss://mm-sdk-relay.api.cx.metamask.io) when running on React Native, as shown in the React Native quickstart docs.

Environment

  • @metamask/connect-evm: 0.9.0
  • @metamask/connect-multichain: 0.11.0 (bundled)
  • @metamask/multichain-api-client: 0.3.0
  • @metamask/mobile-wallet-protocol-core: 0.4.0
  • React Native: 0.81.5
  • Expo: 54
  • Metro bundler
  • Android (Samsung Galaxy)

Suggested Fix

Add "react-native" condition to the exports field in both:

  1. @metamask/connect-evm/package.json
  2. @metamask/multichain-api-client/package.json

Or ensure DefaultTransport in connect-multichain checks the platform and uses WebSocketTransport when window.postMessage is not available (i.e., React Native environment).

Reproduction

npx expo init test-app
cd test-app
npm install @metamask/connect-evm react-native-get-random-values readable-stream
npx expo prebuild
import { createEVMClient } from '@metamask/connect-evm';

const client = await createEVMClient({
  dapp: { name: 'Test', url: 'https://test.com' },
  api: { supportedNetworks: { '0x1': 'https://eth.llamarpc.com' } },
  mobile: { preferredOpenLink: (url) => Linking.openURL(url) },
});

// This hangs forever — never opens MetaMask
await client.connect({ chainIds: ['0x1'] });

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions