# @metamask/connect-multichain

> MetaMask Connect multichain client — CAIP multichain API, session management, and transport negotiation

Latest version **1.2.0** (published 2026-07-08) · SEE LICENSE IN LICENSE license · 0 weekly downloads

## Install

```sh
npm install @metamask/connect-multichain
pnpm add @metamask/connect-multichain
yarn add @metamask/connect-multichain
bun add @metamask/connect-multichain
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 1.2.0 |
| Published | 2026-07-08 |
| First published | 2025-10-24 |
| Weekly downloads | 0 |
| License | SEE LICENSE IN LICENSE |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20.19.0 |
| Dependencies | 17 |
| Unpacked size | 8 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 12 |
| Maintainers | kumavis, frederikbolding, metamaskbot, gudahtt, mrten, mcmire, naugtur |
| Keywords | MetaMask, Ethereum |

## Links

- npm: https://www.npmjs.com/package/@metamask/connect-multichain
- Repository: https://github.com/MetaMask/connect-monorepo
- Homepage: https://github.com/MetaMask/connect-monorepo/tree/main/packages/multichain#readme
- Issues: https://github.com/MetaMask/connect-monorepo/issues
- npm.io page: https://npm.io/package/@metamask/connect-multichain

## Dependencies (17)

- [ws](https://npm.io/package/ws.md) ^8.18.3
- [pako](https://npm.io/package/pako.md) ^2.1.0
- [uuid](https://npm.io/package/uuid.md) ^11.1.0
- [bowser](https://npm.io/package/bowser.md) ^2.11.0
- [buffer](https://npm.io/package/buffer.md) ^6.0.3
- [eciesjs](https://npm.io/package/eciesjs.md) 0.4.17
- [cross-fetch](https://npm.io/package/cross-fetch.md) ^4.1.0
- [@paulmillr/qr](https://npm.io/package/@paulmillr/qr.md) ^0.2.1
- [eventemitter3](https://npm.io/package/eventemitter3.md) ^5.0.1
- [@metamask/utils](https://npm.io/package/@metamask/utils.md) ^11.8.1
- [@metamask/analytics](https://npm.io/package/@metamask/analytics.md) ^0.6.0
- [@metamask/onboarding](https://npm.io/package/@metamask/onboarding.md) ^1.0.1
- [@metamask/rpc-errors](https://npm.io/package/@metamask/rpc-errors.md) ^7.0.3
- [@metamask/multichain-ui](https://npm.io/package/@metamask/multichain-ui.md) ^0.4.1
- [@metamask/multichain-api-client](https://npm.io/package/@metamask/multichain-api-client.md) ^0.10.1
- [@metamask/mobile-wallet-protocol-core](https://npm.io/package/@metamask/mobile-wallet-protocol-core.md) ^0.4.0
- [@metamask/mobile-wallet-protocol-dapp-client](https://npm.io/package/@metamask/mobile-wallet-protocol-dapp-client.md) ^0.3.0

## Recent versions

- 1.2.0 (latest) — 2026-07-08
- 1.1.0 — 2026-06-11
- 1.0.0 — 2026-06-05
- 0.15.0 — 2026-05-26
- 0.14.0 — 2026-05-15
- 0.13.0 — 2026-05-05
- 0.12.1 — 2026-04-20
- 0.12.0 — 2026-04-15
- 0.11.1 — 2026-04-02
- 0.11.0 — 2026-03-19
- 0.10.0 — 2026-03-13
- 0.9.0 — 2026-03-12
- 0.8.0 — 2026-03-10
- 0.7.0 — 2026-03-09
- 0.6.0 — 2026-02-24
- … 11 more at https://npm.io/package/@metamask/connect-multichain/versions

## README

# `@metamask/connect-multichain`

> Core multichain connectivity library for MetaMask Connect SDK. Supports multiple blockchain networks including EVM chains (Ethereum, Polygon, etc.) and non-EVM chains (Solana, etc.).

This package provides support for connecting to MetaMask and using the [CAIP Multichain API](https://github.com/MetaMask/metamask-improvement-proposals/blob/main/MIPs/mip-5.md) which agnostically supports making requests to multiple blockchain ecosystems simultaneously.

## Installation

```bash
yarn add @metamask/connect-multichain
```

or

```bash
npm install @metamask/connect-multichain
```

## Quick Start

```typescript
import {
  createMultichainClient,
  getInfuraRpcUrls,
} from '@metamask/connect-multichain';

const client = await createMultichainClient({
  dapp: {
    name: 'My DApp',
    url: 'https://mydapp.com',
  },
  api: {
    supportedNetworks: {
      // use the `getInfuraRpcUrls` helper to generate a map of Infura RPC endpoints
      ...getInfuraRpcUrls({ infuraApiKey: INFURA_API_KEY }),
      // or specify your own CAIP Chain ID to rpc endpoint mapping
      'eip155:1': 'https://mainnet.example.io/rpc',
      'eip155:137': 'https://polygon-mainnet.example.io/rpc',
    },
  },
});

// Connect to MetaMask with specific chain scopes
await client.connect(['eip155:1', 'eip155:137'], []);

// Invoke methods on specific chains
const blockNumber = await client.invokeMethod({
  scope: 'eip155:1',
  request: {
    method: 'eth_blockNumber',
    params: [],
  },
});
```

## Usage

### Browser (Web)

```typescript
import { createMultichainClient } from '@metamask/connect-multichain';

const client = await createMultichainClient({
  dapp: {
    name: 'My Web DApp',
    url: 'https://mydapp.com',
    iconUrl: 'https://mydapp.com/icon.png',
  },
  api: {
    supportedNetworks: {
      'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
    },
  },
  ui: {
    preferExtension: true, // Prefer browser extension over mobile QR
    showInstallModal: false, // Show modal to install extension
    headless: false, // Set true for custom QR UI
  },
});
```

### Node.js

```typescript
import { createMultichainClient } from '@metamask/connect-multichain';

const client = await createMultichainClient({
  dapp: {
    name: 'My Node App',
    url: 'https://mydapp.com',
  },
  api: {
    supportedNetworks: {
      'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
    },
  },
});

// Connect will display QR code in terminal
await client.connect(['eip155:1'], []);
```

### React Native

```typescript
import { Linking } from 'react-native';
import { createMultichainClient } from '@metamask/connect-multichain';

const client = await createMultichainClient({
  dapp: {
    name: 'My RN App',
    url: 'https://mydapp.com',
  },
  api: {
    supportedNetworks: {
      'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
    },
  },
  mobile: {
    preferredOpenLink: (deeplink) => {
      Linking.openURL(deeplink);
    },
  },
});
```

## TypeScript

This package is written in TypeScript and includes full type definitions. No additional `@types` package is required.

## API Reference

### `createMultichainClient(options)`

Factory function to create a new Multichain SDK instance.

> **Singleton:** `createMultichainClient` returns a single shared instance per global context. Calling it a second time with different options will merge the new `api.supportedNetworks`, `versions`, `ui.*`, `mobile.*`, `transport.extensionId`, and `debug` values into the existing instance rather than creating a new one. The `dapp` value is never overwritten on subsequent calls.

#### Parameters

| Option                      | Type                                          | Required | Description                                                                                                                  |
| --------------------------- | --------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `dapp.name`                 | `string`                                      | Yes      | Name of your dApp                                                                                                            |
| `api.supportedNetworks`     | `RpcUrlsMap`                                  | Yes      | Map of [CAIP-2 chain IDs](https://chainagnostic.org/CAIPs/caip-2) to RPC URLs                                                |
| `dapp.url`                  | `string`                                      | No       | URL of your dApp                                                                                                             |
| `dapp.iconUrl`              | `string`                                      | No       | Icon URL for your dApp                                                                                                       |
| `dapp.base64Icon`           | `string`                                      | No       | Base64-encoded icon (alternative to iconUrl)                                                                                 |
| `storage`                   | `StoreClient`                                 | No       | Custom storage adapter                                                                                                       |
| `ui.factory`                | `BaseModalFactory`                            | No       | Custom modal factory                                                                                                         |
| `ui.headless`               | `boolean`                                     | No       | Run without UI (for custom QR implementations)                                                                               |
| `ui.preferExtension`        | `boolean`                                     | No       | Prefer browser extension (default: true)                                                                                     |
| `ui.showInstallModal`       | `boolean`                                     | No       | Show installation modal                                                                                                      |
| `mobile.preferredOpenLink`  | `(deeplink: string, target?: string) => void` | No       | Custom deeplink handler                                                                                                      |
| `mobile.useDeeplink`        | `boolean`                                     | No       | Use `metamask://` instead of universal links                                                                                 |
| `analytics.enabled`         | `boolean`                                     | No       | Enables dapp-side analytics. Defaults to `true`; set to `false` to disable analytics events and wallet correlation metadata. |
| `analytics.integrationType` | `string`                                      | No       | Integration type for analytics                                                                                               |
| `transport.extensionId`     | `string`                                      | No       | Custom extension ID                                                                                                          |
| `versions`                  | `Partial<ConnectVersions>`                    | No       | Internal: set automatically by `createEVMClient` / `createSolanaClient`. Consumers do not need to provide this.              |
| `debug`                     | `boolean`                                     | No       | Enable debug logging                                                                                                         |

#### Returns

`Promise<MetaMaskConnectMultichain>` - A fully initialized SDK instance.

```typescript
const client = await createMultichainClient({
  dapp: { name: 'My DApp', url: 'https://mydapp.com' },
  api: {
    supportedNetworks: {
      'eip155:1': 'https://mainnet.infura.io/v3/KEY',
      'eip155:137': 'https://polygon-mainnet.infura.io/v3/KEY',
    },
  },
});
```

---

### `MetaMaskConnectMultichain`

The main SDK class extending `MultichainCore`.

#### Methods

##### `connect(scopes, caipAccountIds, sessionProperties?, forceRequest?)`

Connects to MetaMask with specified chain scopes.

**Parameters**

| Name                | Type                | Required | Description                                                                                             |
| ------------------- | ------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `scopes`            | `Scope[]`           | Yes      | Array of CAIP-2 chain identifiers to request permission for                                             |
| `caipAccountIds`    | `CaipAccountId[]`   | Yes      | Array of CAIP-10 account identifiers to request (pass `[]` if no specific accounts should be requested) |
| `sessionProperties` | `SessionProperties` | No       | Additional session properties                                                                           |
| `forceRequest`      | `boolean`           | No       | Force a new connection request even if already connected                                                |

**Returns**

`Promise<void>`

```typescript
await client.connect(
  ['eip155:1', 'eip155:137'], // Chain scopes to request
  ['eip155:1:0x...'], // Specific accounts to request
);
```

##### `disconnect(scopes?)`

Disconnects from the wallet. If `scopes` are provided, only the specified scopes are revoked; if there are remaining scopes, the connection stays alive. If omitted or empty, all scopes are revoked and the connection is fully torn down.

**Parameters**

| Name     | Type      | Required | Description                                                          |
| -------- | --------- | -------- | -------------------------------------------------------------------- |
| `scopes` | `Scope[]` | No       | Array of CAIP-2 chain identifiers to revoke (defaults to all scopes) |

**Returns**

`Promise<void>`

```typescript
// Fully disconnect
await client.disconnect();

// Disconnect only specific scopes
await client.disconnect(['eip155:1']);
```

##### `invokeMethod(options)`

Invokes an RPC method on a specific chain.

**Parameters**

| Name                     | Type        | Required | Description                                         |
| ------------------------ | ----------- | -------- | --------------------------------------------------- |
| `options.scope`          | `Scope`     | Yes      | The CAIP-2 chain identifier to invoke the method on |
| `options.request.method` | `string`    | Yes      | The RPC method name                                 |
| `options.request.params` | `unknown[]` | No       | The method parameters                               |

**Returns**

`Promise<Json>` - The result of the RPC method call.

```typescript
const result = await client.invokeMethod({
  scope: 'eip155:1',
  request: {
    method: 'eth_getBalance',
    params: ['0x...', 'latest'],
  },
});
```

#### Properties

| Property    | Type                  | Description                                                                                   |
| ----------- | --------------------- | --------------------------------------------------------------------------------------------- |
| `status`    | `ConnectionStatus`    | Connection status ( `'loaded'`, `'pending'`, `'connecting'`, `'connected'`, `'disconnected'`) |
| `provider`  | `MultichainApiClient` | Multichain API client                                                                         |
| `transport` | `ExtendedTransport`   | Active transport layer                                                                        |

#### Events

```typescript
// Session changes
client.on('wallet_sessionChanged', (session) => {
  console.log('Session updated:', session);
});

// QR code display (for custom UI)
client.on('display_uri', (uri) => {
  console.log('Display QR code:', uri);
});

// Connection state changes
client.on('stateChanged', (status) => {
  console.log('Status:', status);
});
```

---

### `MultichainCore`

Abstract base class providing core multichain functionality.

#### Methods

##### `on(event, handler)`

Registers an event handler.

**Parameters**

| Name      | Type       | Required | Description                                               |
| --------- | ---------- | -------- | --------------------------------------------------------- |
| `event`   | `string`   | Yes      | The event name to listen for                              |
| `handler` | `Function` | Yes      | The callback function to invoke when the event is emitted |

**Returns**

`void`

##### `off(event, handler)`

Removes an event handler.

**Parameters**

| Name      | Type       | Required | Description                          |
| --------- | ---------- | -------- | ------------------------------------ |
| `event`   | `string`   | Yes      | The event name to stop listening for |
| `handler` | `Function` | Yes      | The callback function to remove      |

**Returns**

`void`

##### `emit(event, args)`

Emits an event to all registered handlers.

**Parameters**

| Name    | Type     | Required | Description                             |
| ------- | -------- | -------- | --------------------------------------- |
| `event` | `string` | Yes      | The event name to emit                  |
| `args`  | `any`    | No       | Arguments to pass to the event handlers |

**Returns**

`void`

---

### Utilities

#### `getInfuraRpcUrls(options)`

Generates Infura RPC URLs for common networks keyed by CAIP Chain ID.

**Parameters**

| Name           | Type            | Required | Description                           |
| -------------- | --------------- | -------- | ------------------------------------- |
| `infuraApiKey` | `string`        | Yes      | Your Infura API key                   |
| `caipChainIds` | `CaipChainId[]` | No       | CAIP-2 chain IDs to filter the output |

**Returns**

A map of [CAIP-2 chain IDs](https://chainagnostic.org/CAIPs/caip-2) to Infura RPC URLs. See https://docs.metamask.io/services

```typescript
import { getInfuraRpcUrls } from '@metamask/connect-multichain';

// Get all supported Infura RPC URLs
const rpcUrls = getInfuraRpcUrls({ infuraApiKey: 'YOUR_INFURA_KEY' });
// {
//   'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
//   'eip155:137': 'https://polygon-mainnet.infura.io/v3/YOUR_KEY',
//   'eip155:11155111': 'https://sepolia.infura.io/v3/YOUR_KEY',
//   ...
// }

// Filter to specific chains
const filtered = getInfuraRpcUrls({
  infuraApiKey: 'YOUR_INFURA_KEY',
  caipChainIds: ['eip155:1', 'eip155:137'],
});
// {
//   'eip155:1': 'https://mainnet.infura.io/v3/YOUR_KEY',
//   'eip155:137': 'https://polygon-mainnet.infura.io/v3/YOUR_KEY',
// }
```

---

### Errors

The package exports various error classes for handling specific error conditions:

- `ProtocolError` - Base protocol error
- `StorageError` - Storage operation errors
- `RpcError` - RPC request errors

```typescript
import { ProtocolError } from '@metamask/connect-multichain';

try {
  await client.connect(['eip155:1'], []);
} catch (error) {
  if (error instanceof ProtocolError) {
    console.log('Protocol error:', error.code, error.message);
  }
}
```

---

## Headless Mode

For custom QR code implementations, use headless mode:

```typescript
const client = await createMultichainClient({
  dapp: { name: 'My DApp' },
  api: { supportedNetworks: { 'eip155:1': 'https://...' } },
  ui: { headless: true },
});

// Listen for QR code URIs
client.on('display_uri', (uri) => {
  // Display your custom QR code with this URI
  displayMyCustomQRCode(uri);
});

await client.connect(['eip155:1'], []);
```

## Standards

- [CAIP-25](https://chainagnostic.org/CAIPs/caip-25) (please see CAIP Multichain API)
- [CAIP-27](https://chainagnostic.org/CAIPs/caip-27)
- [CAIP-2](https://chainagnostic.org/CAIPs/caip-2)
- [CAIP-10](https://chainagnostic.org/CAIPs/caip-10)
- [CAIP-217](https://chainagnostic.org/CAIPs/caip-217)
- [CAIP-316](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-316.md)
- [CAIP-312](https://chainagnostic.org/CAIPs/caip-312)
- [CAIP-311](https://chainagnostic.org/CAIPs/caip-311)
- [CAIP-285](https://chainagnostic.org/CAIPs/caip-285)
- [CAIP Multichain API](https://github.com/MetaMask/metamask-improvement-proposals/blob/main/MIPs/mip-5.md)

## Contributing

This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/connect-monorepo#readme).

## License

MIT

---
_Source: https://npm.io/package/@metamask/connect-multichain · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
