From 905da0e8a21bb6be71bd032108e3a683222d5d61 Mon Sep 17 00:00:00 2001 From: Mohammad Shahbaz Alam Date: Wed, 10 Jun 2026 21:26:13 +0530 Subject: [PATCH 1/5] docs: update MetaMask Connect v2 guides & API Update docs for MetaMask Connect v2: document that @metamask/connect-evm and @metamask/connect-solana now require explicit @metamask/connect-multichain peer installation; update installation quickstarts and notes. Clarify client behaviors (async createEVMClient/createMultichainClient, singleton merging semantics and that the initial dapp object is never overwritten), add guidance on session restoration (wallet_sessionChanged) and forceRequest option for connect. Revise provider and JSON-RPC notes: provider auto-announcement (EIP-6963) with skipAutoAnnounce, new error codes (-32002, 4902, 1013), eth_coinbase returns a single address, and wallet_requestPermissions result shape. Misc: move/rename options (analytics.enabled, skipAutoAnnounce, ui.showInstallModal, debug), Solana changes (solana_signMessage + .signature result, testnet/devnet availability in extension only), polyfill notes for Event when using wagmi, and other small clarity/formatting fixes across reference and quickstart files. --- .../evm/guides/migrate-from-sdk.md | 58 ++++++++++--------- metamask-connect/evm/index.mdx | 2 +- metamask-connect/evm/quickstart/javascript.md | 6 +- metamask-connect/evm/quickstart/nodejs.md | 6 +- .../evm/quickstart/react-native.md | 10 +++- metamask-connect/evm/quickstart/wagmi.md | 6 +- .../reference/json-rpc-api/eth_coinbase.mdx | 2 +- .../wallet_requestPermissions.mdx | 9 ++- metamask-connect/evm/reference/methods.md | 16 +++++ .../evm/reference/provider-api.md | 13 +++++ metamask-connect/index.md | 3 +- metamask-connect/integration-options.md | 7 +++ .../multichain/concepts/scopes.md | 8 +-- .../multichain/guides/headless-mode.md | 7 +++ .../multichain/guides/send-transactions.md | 17 +++--- .../multichain/guides/sign-transactions.md | 9 +-- metamask-connect/multichain/index.mdx | 2 +- .../multichain/quickstart/javascript.md | 11 ++++ .../multichain/quickstart/nodejs.md | 20 ++++--- .../multichain/quickstart/react-native.md | 4 ++ .../multichain/reference/methods.md | 58 +++++++++++-------- .../tutorials/create-multichain-dapp.md | 9 ++- .../solana/guides/use-wallet-adapter.md | 26 ++++++--- metamask-connect/solana/index.mdx | 2 +- .../solana/quickstart/javascript.md | 11 +++- metamask-connect/solana/quickstart/nodejs.md | 26 +++++---- metamask-connect/solana/reference/methods.md | 38 ++++++------ metamask-connect/supported-platforms.md | 7 +++ metamask-connect/troubleshooting/index.md | 22 ++++--- .../troubleshooting/metro-polyfill-issues.md | 3 + 30 files changed, 284 insertions(+), 134 deletions(-) diff --git a/metamask-connect/evm/guides/migrate-from-sdk.md b/metamask-connect/evm/guides/migrate-from-sdk.md index 5843c90f677..e44e029294a 100644 --- a/metamask-connect/evm/guides/migrate-from-sdk.md +++ b/metamask-connect/evm/guides/migrate-from-sdk.md @@ -44,8 +44,8 @@ npm uninstall @metamask/sdk # For React Native, remove npm uninstall @metamask/sdk-react -# Install new (EVM only) -npm install @metamask/connect-evm +# Install new (EVM). @metamask/connect-multichain is a required peer dependency since @metamask/connect-evm 2.0.0. +npm install @metamask/connect-evm @metamask/connect-multichain ``` ### 2. Update imports @@ -82,8 +82,8 @@ initialization in a single async step. :::caution `createEVMClient` is async, so always `await` it before accessing the client. The client is also a -singleton. Calling `createEVMClient` multiple times merges options into the same instance. Do not -recreate it on every render. +singleton. Calling `createEVMClient` multiple times merges new options into the same instance, but +the `dapp` object from the first call is never overwritten. Do not recreate it on every render. ::: **Old:** @@ -150,7 +150,7 @@ options that MetaMask Connect EVM no longer exposes. | `openDeeplink` | `mobile.preferredOpenLink` | Same signature: `(deeplink: string) => void` | | `useDeeplink` | `mobile.useDeeplink` | Same behavior | | `timer` | Removed | No longer configurable | -| `enableAnalytics` | Removed | No longer available | +| `enableAnalytics` | `analytics.enabled` | Replaced by `analytics: { enabled: false }` to opt out | | `communicationServerUrl` | Removed | Managed internally | | `storage` | Removed | Managed internally | @@ -229,8 +229,9 @@ so read `.result` from the returned object to get the RPC response value. :::tip React Native polyfills Browser-based setups (Vite, Webpack) work without polyfills. If you are migrating a React Native -app and encounter errors referencing `Buffer`, `crypto`, `stream`, or `Event is not defined`, see -[React Native Metro polyfill issues](../../troubleshooting/metro-polyfill-issues.md). +app and encounter errors referencing `Buffer`, `crypto`, or `stream`, see +[React Native Metro polyfill issues](../../troubleshooting/metro-polyfill-issues.md). The +`Event is not defined` error only occurs when you also use wagmi, which dispatches DOM events. ::: ### 5. Update provider access @@ -345,6 +346,10 @@ If your dapp supports (or plans to support) both EVM and Solana, consider upgrad The EVM client is built on top of `createMultichainClient` internally, so the upgrade is straightforward: +```bash npm2yarn +npm install @metamask/connect-multichain +``` + ```typescript import { createMultichainClient } from '@metamask/connect-multichain' @@ -378,25 +383,26 @@ See the [multichain quickstart](../../multichain/quickstart/javascript.md) for a -| Old (`@metamask/sdk`) | New (`@metamask/connect-evm`) | Status | -| ------------------------ | ----------------------------------------------------------------------------------------------------------- | ------------------------------------- | -| `new MetaMaskSDK(opts)` | `await createEVMClient(opts)` | Renamed, async | -| `sdk.init` | Not needed | Init happens in `createEVMClient` | -| `sdk.connect` | `client.connect({ chainIds })` | Returns `{ accounts, chainId }` | -| `sdk.getProvider` | `client.getProvider` | Returns EIP-1193 provider | -| `sdk.disconnect` | `client.disconnect` | Same, plus partial disconnect support | -| `dappMetadata` | `dapp` | Renamed | -| `infuraAPIKey` | [`getInfuraRpcUrls({ infuraApiKey })`](../reference/methods.md#getinfurarpcurls) in `api.supportedNetworks` | Helper function | -| `readonlyRPCMap` | `api.supportedNetworks` | Merged with Infura URLs | -| `headless` | `ui.headless` | Moved to `ui` namespace | -| `extensionOnly` | `ui.preferExtension` | Renamed, slightly different semantics | -| `openDeeplink` | `mobile.preferredOpenLink` | Moved to `mobile` namespace | -| `useDeeplink` | `mobile.useDeeplink` | Moved to `mobile` namespace | -| `SDKProvider` | `EIP1193Provider` | Standard provider interface | -| `timer` | Removed | — | -| `enableAnalytics` | Removed | — | -| `communicationServerUrl` | Removed | — | -| `storage` | Removed | — | +| Old (`@metamask/sdk`) | New (`@metamask/connect-evm`) | Status | +| ------------------------ | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `new MetaMaskSDK(opts)` | `await createEVMClient(opts)` | Renamed, async | +| `sdk.init` | Not needed | Init happens in `createEVMClient` | +| `sdk.connect` | `client.connect({ chainIds })` | Returns `{ accounts, chainId }` | +| `sdk.getProvider` | `client.getProvider` | Returns EIP-1193 provider | +| `sdk.disconnect` | `client.disconnect` | Same for EVM; `disconnect(scopes)` enables partial disconnect | +| `sdk.terminate` | `client.disconnect` | `terminate` removed; `disconnect()` with no arguments revokes all scopes and ends the session | +| `dappMetadata` | `dapp` | Renamed | +| `infuraAPIKey` | [`getInfuraRpcUrls({ infuraApiKey })`](../reference/methods.md#getinfurarpcurls) in `api.supportedNetworks` | Helper function | +| `readonlyRPCMap` | `api.supportedNetworks` | Merged with Infura URLs | +| `headless` | `ui.headless` | Moved to `ui` namespace | +| `extensionOnly` | `ui.preferExtension` | Renamed, slightly different semantics | +| `openDeeplink` | `mobile.preferredOpenLink` | Moved to `mobile` namespace | +| `useDeeplink` | `mobile.useDeeplink` | Moved to `mobile` namespace | +| `SDKProvider` | `EIP1193Provider` | Standard provider interface | +| `timer` | Removed | — | +| `enableAnalytics` | `analytics.enabled` | Replaced by `analytics: { enabled: false }` to opt out | +| `communicationServerUrl` | Removed | — | +| `storage` | Removed | — | diff --git a/metamask-connect/evm/index.mdx b/metamask-connect/evm/index.mdx index fc6849caaae..416cabad4ce 100644 --- a/metamask-connect/evm/index.mdx +++ b/metamask-connect/evm/index.mdx @@ -99,7 +99,7 @@ We recommend using an Infura API key for production dapps. MetaMask Connect EVM To migrate: -- Replace `@metamask/sdk` with `@metamask/connect-evm` in your dependencies. +- Replace `@metamask/sdk` with `@metamask/connect-evm` in your dependencies, and add `@metamask/connect-multichain` (a required peer dependency since `@metamask/connect-evm` 2.0.0). - Update imports from `MetaMaskSDK` to `createEVMClient`. - Switch from synchronous to async initialization. - Update your provider access pattern. diff --git a/metamask-connect/evm/quickstart/javascript.md b/metamask-connect/evm/quickstart/javascript.md index 69fe4872b41..f7808a1005d 100644 --- a/metamask-connect/evm/quickstart/javascript.md +++ b/metamask-connect/evm/quickstart/javascript.md @@ -125,9 +125,13 @@ You've successfully set up MetaMask Connect EVM. Install the EVM client in an existing JavaScript project: ```bash npm2yarn -npm install @metamask/connect-evm +npm install @metamask/connect-evm @metamask/connect-multichain ``` +:::note +Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 2. Initialize MetaMask Connect EVM Initialize the EVM client using [`createEVMClient`](../reference/methods.md#createevmclient). diff --git a/metamask-connect/evm/quickstart/nodejs.md b/metamask-connect/evm/quickstart/nodejs.md index 775c4da11c6..e5476e4cd5f 100644 --- a/metamask-connect/evm/quickstart/nodejs.md +++ b/metamask-connect/evm/quickstart/nodejs.md @@ -42,9 +42,13 @@ polyfilling in browser or React Native environments. Install the EVM client in an existing Node.js project: ```bash npm2yarn -npm install @metamask/connect-evm +npm install @metamask/connect-evm @metamask/connect-multichain ``` +:::note +Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 2. Initialize MetaMask Connect EVM Create a file (`index.mjs`) and initialize the client using [`createEVMClient`](../reference/methods.md#createevmclient). diff --git a/metamask-connect/evm/quickstart/react-native.md b/metamask-connect/evm/quickstart/react-native.md index ee675946e42..8ccf21fa943 100644 --- a/metamask-connect/evm/quickstart/react-native.md +++ b/metamask-connect/evm/quickstart/react-native.md @@ -55,9 +55,13 @@ npx create-expo-app MyProject --template Install MetaMask Connect EVM and its required polyfill packages: ```bash -npm install @metamask/connect-evm react-native-get-random-values buffer @react-native-async-storage/async-storage readable-stream +npm install @metamask/connect-evm @metamask/connect-multichain react-native-get-random-values buffer @react-native-async-storage/async-storage readable-stream ``` +:::note +Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 3. Create polyfills Create `polyfills.ts` (at the project root or in `src/`) with all required global shims. @@ -142,6 +146,10 @@ if (typeof global.CustomEvent === 'undefined') { } ``` +:::note +The `Event` and `CustomEvent` polyfills above are only required if you also use wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. +::: + :::tip For detailed troubleshooting of polyfill issues, see [React Native Metro polyfill issues](../../troubleshooting/metro-polyfill-issues.md). ::: diff --git a/metamask-connect/evm/quickstart/wagmi.md b/metamask-connect/evm/quickstart/wagmi.md index c8277209e62..62a01b4e808 100644 --- a/metamask-connect/evm/quickstart/wagmi.md +++ b/metamask-connect/evm/quickstart/wagmi.md @@ -97,11 +97,11 @@ TOD0: Update with new screenshot and link Install MetaMask Connect EVM along with its peer dependencies to an existing React project: :::note Version requirements -This quickstart requires `wagmi@^3.6.0` and `wagmi/connectors@^8.0.0` +This quickstart requires `wagmi@^3.6.0`. The `metaMask` connector is imported from the `wagmi/connectors` subpath (part of the `wagmi` package), and requires `@metamask/connect-evm`, which in turn requires `@metamask/connect-multichain` as a peer dependency. ::: ```bash npm2yarn -npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query +npm install @metamask/connect-evm @metamask/connect-multichain wagmi@^3.6.0 viem@2.x @tanstack/react-query ``` ### 2. Import required dependencies @@ -320,7 +320,7 @@ If you previously used `@metamask/sdk` with Wagmi, the MetaMask connector now us ```bash npm2yarn npm uninstall @metamask/sdk - npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 + npm install @metamask/connect-evm @metamask/connect-multichain wagmi@^3.6.0 ``` 2. Update hook usage for wagmi v3: diff --git a/metamask-connect/evm/reference/json-rpc-api/eth_coinbase.mdx b/metamask-connect/evm/reference/json-rpc-api/eth_coinbase.mdx index 0a8fea64ca0..13158ec780b 100644 --- a/metamask-connect/evm/reference/json-rpc-api/eth_coinbase.mdx +++ b/metamask-connect/evm/reference/json-rpc-api/eth_coinbase.mdx @@ -11,7 +11,7 @@ import SimplifiedApiReference from '@site/src/components/SimplifiedApiReference' diff --git a/metamask-connect/evm/reference/methods.md b/metamask-connect/evm/reference/methods.md index a6c386e3288..855aedfbd2c 100644 --- a/metamask-connect/evm/reference/methods.md +++ b/metamask-connect/evm/reference/methods.md @@ -47,7 +47,11 @@ Creates a new EVM client instance. | `ui.preferExtension` | `boolean` | No | Directly connects through the MetaMask extension when it's installed. The default is `true`. | | `mobile.preferredOpenLink` | `(deeplink: string) => void` | No | A function that's called to open a deeplink to the MetaMask Mobile App. Required in React Native. | | `mobile.useDeeplink` | `boolean` | No | Controls use of deeplinks for mobile connection flows. | +| `ui.showInstallModal` | `boolean` | No | Shows the MetaMask install modal when the extension isn't detected. | | `eventHandlers` | `object` | No | Optional callbacks for connection lifecycle and [provider events](provider-api.md#events). | +| `debug` | `boolean` | No | Enables verbose SDK logging. The default is `false`. | +| `skipAutoAnnounce` | `boolean` | No | Opts out of automatic EIP-6963 provider announcement (default since `@metamask/connect-evm` 2.0.0). Call `client.announceProvider()` to announce manually. | +| `analytics.enabled` | `boolean` | No | Set to `false` to opt out of analytics. | ### Returns @@ -274,6 +278,13 @@ Switches the active chain on the EVM client. If the chain is not already added to the user's MetaMask wallet, the optional `chainConfiguration` parameter triggers a `wallet_addEthereumChain` request as a fallback. +:::note +Since `@metamask/connect-evm` 1.2.0, calling `switchChain` without `chainConfiguration` for an +unrecognized chain rejects with the wallet's raw `4902` error (not a "No chain configuration found." +message). Handle `4902` in a `catch` block by retrying with `chainConfiguration` or calling +`wallet_addEthereumChain`. +::: + ### Parameters | Name | Type | Required | Description | @@ -363,6 +374,11 @@ The EVM client exposes the following read-only properties: | `selectedChainId` | `Hex \| undefined` | Currently selected chain ID as a hex string. | | `status` | `ConnectEvmStatus` | Connection status: `'loaded'`, `'pending'`, `'connecting'`, `'connected'`, or `'disconnected'`. | +:::note +On the EVM client, `status` is a `ConnectEvmStatus`. Since `@metamask/connect-evm` 0.11.0 it +reflects the EVM client's own status and no longer proxies `MultichainClient.status`. +::: + ### Example ```javascript diff --git a/metamask-connect/evm/reference/provider-api.md b/metamask-connect/evm/reference/provider-api.md index 141ff80d261..5fb33482eae 100644 --- a/metamask-connect/evm/reference/provider-api.md +++ b/metamask-connect/evm/reference/provider-api.md @@ -36,6 +36,10 @@ Throughout this documentation, we refer to the selected provider using `provider When using MetaMask Connect EVM, you get the same EIP-1193 provider via `client.getProvider`. The provider returned by MetaMask Connect EVM is available immediately after `createEVMClient` resolves and supports the same methods, properties, and events documented below. + +Since `@metamask/connect-evm` 2.0.0, MetaMask Connect EVM announces its provider through EIP-6963 by +default when the native MetaMask extension hasn't already announced one. Pass `skipAutoAnnounce: true` +to `createEVMClient` to opt out, and call `client.announceProvider` to announce manually. ::: ## Properties @@ -203,6 +207,7 @@ provider // Or window.ethereum if you don't support EIP-6963. ``` The provider emits this event when the currently connected chain changes. +The `chainId` is a hex string (for example, `0x1`), not a decimal number. Listen to this event to [detect a user's network](../guides/manage-networks.md). ### `connect` @@ -329,8 +334,11 @@ You can use the error `code` property to determine why the request failed. Common codes and their meaning include: - `4001` - The request is rejected by the user. +- `-32002` - A request is already pending. Don't send another request; wait for the user to respond in MetaMask. +- `4902` - The chain isn't recognized by the wallet. Add it with `wallet_addEthereumChain`, or pass `chainConfiguration` to [`switchChain`](methods.md#switchchain). - `-32602` - The parameters are invalid. - `-32603` - Internal error. +- `1013` - An internal transport disconnect. The SDK retries automatically, so don't treat it as a user-facing disconnect. For the complete list of errors, see [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193#provider-errors) and [EIP-1474](https://eips.ethereum.org/EIPS/eip-1474#error-codes). @@ -340,6 +348,11 @@ The [`eth-rpc-errors`](https://npmjs.com/package/eth-rpc-errors) package impleme returned by the MetaMask provider, and can help you identify their meaning. ::: +:::note Typed errors +The multichain core exports typed error classes for `instanceof` checks: `ProtocolError`, +`StorageError`, and `RpcError` from `@metamask/connect-multichain`. +::: + ## Next steps - [JSON-RPC API reference](./json-rpc-api/index.md) diff --git a/metamask-connect/index.md b/metamask-connect/index.md index d973a379b83..468cbf5a63d 100644 --- a/metamask-connect/index.md +++ b/metamask-connect/index.md @@ -80,7 +80,7 @@ MetaMask Connect is a complete rewrite of the legacy SDK. Key differences include: - Async initialization with `createEVMClient`. -- A singleton client pattern. +- A singleton client pattern built on the shared `createMultichainClient` core (the EVM and Solana clients wrap it). - Built-in multichain support for both EVM and Solana. - CAIP-25 session management. - Improved relay server infrastructure. @@ -96,6 +96,7 @@ See [supported platforms](supported-platforms.md) for the full matrix. ### Which blockchain networks does MetaMask Connect support? MetaMask Connect supports Ethereum and all EVM-compatible networks (Polygon, Arbitrum, Optimism, Linea, Base, etc.) through `@metamask/connect-evm`, Solana through `@metamask/connect-solana`, and both simultaneously through `@metamask/connect-multichain`. +Since their 2.0.0 releases, `@metamask/connect-evm` and `@metamask/connect-solana` require `@metamask/connect-multichain` as an explicitly installed peer dependency. See [integration options](integration-options.md) to choose the right package. ### Do I need an Infura API key to use MetaMask Connect? diff --git a/metamask-connect/integration-options.md b/metamask-connect/integration-options.md index 83a09c4d3d8..681dd05b5b7 100644 --- a/metamask-connect/integration-options.md +++ b/metamask-connect/integration-options.md @@ -34,6 +34,7 @@ all ecosystems. If your dapp targets a single chain or you prefer per-chain provider interfaces, you can use the single-ecosystem or multi-ecosystem option. All options share the same underlying transport and session infrastructure, so you can start with the option that fits your dapp today and migrate later. +The EVM and Solana clients wrap the same `createMultichainClient` singleton core. ## Multichain (recommended) @@ -57,6 +58,12 @@ If your dapp supports both EVM and Solana, use [`@metamask/connect-evm`](evm/ind [`@metamask/connect-solana`](solana/index.mdx) together to support both ecosystems while keeping familiar provider interfaces for each. +:::note +The `@metamask/connect-evm` and `@metamask/connect-solana` packages require +`@metamask/connect-multichain` as an explicitly installed peer dependency since their 2.0.0 releases. +Install it alongside whichever single-ecosystem package you use. +::: + ## Compare options | | Multichain | Single-ecosystem | Multi-ecosystem | diff --git a/metamask-connect/multichain/concepts/scopes.md b/metamask-connect/multichain/concepts/scopes.md index ee15550288d..f7844ade6bf 100644 --- a/metamask-connect/multichain/concepts/scopes.md +++ b/metamask-connect/multichain/concepts/scopes.md @@ -62,10 +62,10 @@ const balance = await client.invokeMethod({ ## Supported scopes -| Ecosystem | Format | Examples | -| --------- | ---------------------- | ------------------------------------------------------------------------------------------------------- | -| EVM | `eip155:` | `eip155:1` (Ethereum), `eip155:59144` (Linea), `eip155:137` (Polygon) | -| Solana | `solana:` | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` (Mainnet), `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` (Devnet) | +| Ecosystem | Format | Examples | +| --------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| EVM | `eip155:` | `eip155:1` (Ethereum), `eip155:59144` (Linea), `eip155:137` (Polygon) | +| Solana | `solana:` | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` (Mainnet), `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` (Devnet), `solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z` (Testnet) | ## Common EVM scopes diff --git a/metamask-connect/multichain/guides/headless-mode.md b/metamask-connect/multichain/guides/headless-mode.md index 0254a941a21..2c6661ac245 100644 --- a/metamask-connect/multichain/guides/headless-mode.md +++ b/metamask-connect/multichain/guides/headless-mode.md @@ -65,6 +65,11 @@ You **must** register the listener before calling `connect`, or you may miss the client.on('display_uri', uri => { showCustomQrModal(uri) }) + +// Register a session listener too, so restored sessions are captured. +client.on('wallet_sessionChanged', session => { + // Update your app state with the new session +}) ``` ### 3. Connect and handle the result @@ -79,6 +84,8 @@ try { hideCustomQrModal() if (err.code === 4001) { // User rejected — show retry UI + } else if (err.code === -32002) { + // A request is already pending — wait for the user to respond, don't call connect again } else { console.error('Connection failed:', err) } diff --git a/metamask-connect/multichain/guides/send-transactions.md b/metamask-connect/multichain/guides/send-transactions.md index 0f8ef4bf2d7..0a313f6d05c 100644 --- a/metamask-connect/multichain/guides/send-transactions.md +++ b/metamask-connect/multichain/guides/send-transactions.md @@ -61,10 +61,10 @@ await client.connect( The multichain client routes EVM methods based on type: -| Route | Methods | Transport | -| ------------ | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | -| **RPC node** | `eth_call`, `eth_getBalance`, `eth_blockNumber`, `eth_getTransactionReceipt`, `eth_estimateGas`, `eth_getCode`, `eth_getLogs` | Infura / custom RPC URL from `supportedNetworks` | -| **Wallet** | `eth_sendTransaction`, `personal_sign`, `eth_signTypedData_v4`, `wallet_switchEthereumChain`, `wallet_addEthereumChain` | MetaMask (extension or mobile) | +| Route | Methods | Transport | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | +| **RPC node** | `eth_call`, `eth_getBalance`, `eth_getTransactionCount`, `eth_blockNumber`, `eth_getTransactionReceipt`, `eth_estimateGas`, `eth_getCode`, `eth_getLogs` | Infura / custom RPC URL from `supportedNetworks` | +| **Wallet** | `eth_sendTransaction`, `personal_sign`, `eth_signTypedData_v4`, `wallet_switchEthereumChain`, `wallet_addEthereumChain` | MetaMask (extension or mobile) | All Solana methods route through the MetaMask wallet. There is no RPC node fallback for Solana. @@ -196,10 +196,11 @@ console.log('Transaction ID:', txId) ## Error handling -| Error code | Description | Action | -| ---------- | ------------------------- | ---------------------------------------------------------- | -| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | -| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | +| Error code | Description | Action | +| ---------- | ----------------------------- | -------------------------------------------------------------------------- | +| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | +| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | +| `1013` | Internal transport disconnect | The SDK retries automatically. Don't treat it as a user-facing disconnect. |
diff --git a/metamask-connect/multichain/guides/sign-transactions.md b/metamask-connect/multichain/guides/sign-transactions.md index 3d1cd287f91..a6a51466953 100644 --- a/metamask-connect/multichain/guides/sign-transactions.md +++ b/metamask-connect/multichain/guides/sign-transactions.md @@ -151,10 +151,11 @@ console.log('Signature:', result.signature) ## Error handling -| Error code | Description | Action | -| ---------- | ------------------------- | ---------------------------------------------------------- | -| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | -| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | +| Error code | Description | Action | +| ---------- | ----------------------------- | -------------------------------------------------------------------------- | +| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | +| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | +| `1013` | Internal transport disconnect | The SDK retries automatically. Don't treat it as a user-facing disconnect. |
diff --git a/metamask-connect/multichain/index.mdx b/metamask-connect/multichain/index.mdx index fba3bcab5f0..2d8a5a2cb52 100644 --- a/metamask-connect/multichain/index.mdx +++ b/metamask-connect/multichain/index.mdx @@ -104,7 +104,7 @@ If you're adding MetaMask Connect Multichain to an existing dapp and want minima ### What chains does the multichain client support? -MetaMask Connect Multichain supports all EVM-compatible networks (Ethereum, Polygon, Arbitrum, Optimism, Linea, Base, and any chain with a [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) scope) and Solana (mainnet and devnet). +MetaMask Connect Multichain supports all EVM-compatible networks (Ethereum, Polygon, Arbitrum, Optimism, Linea, Base, and any chain with a [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) scope) and Solana (mainnet, devnet, and testnet; devnet and testnet are supported only in the MetaMask browser extension). Future ecosystems will be supported as they are added to MetaMask. Specify which chains to connect to using CAIP-2 scopes (for example, `eip155:1` for Ethereum Mainnet or `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for Solana Mainnet). diff --git a/metamask-connect/multichain/quickstart/javascript.md b/metamask-connect/multichain/quickstart/javascript.md index 7375863ea76..3e19cc5ab2c 100644 --- a/metamask-connect/multichain/quickstart/javascript.md +++ b/metamask-connect/multichain/quickstart/javascript.md @@ -113,6 +113,11 @@ Install the multichain client in an existing JavaScript (Vite) project: npm install @metamask/connect-multichain ``` +:::note +`@metamask/connect-multichain` (`^1.0.0`) is the multichain core. It's also the explicit peer +dependency that `@metamask/connect-evm` and `@metamask/connect-solana` 2.x require. +::: + ### 2. Initialize MetaMask Connect Multichain Initialize the multichain client using [`createMultichainClient`](../reference/methods.md#createmultichainclient). @@ -172,6 +177,12 @@ if (ethAccounts.length > 0) { The user sees a single approval prompt for all requested chains. Use [`invokeMethod`](../reference/methods.md#invokemethod) to call RPC methods on any chain in the session by specifying a [scope](../concepts/scopes.md). +:::tip Restore sessions +Register a [`wallet_sessionChanged`](../reference/methods.md#events) listener before calling `connect`, +and skip `connect` when [`getSession`](../reference/methods.md#getsession) already returns a session +(for example, after a page reload). See [sessions](../concepts/sessions.md). +::: + ## Multichain client methods at a glance | Method | Description | diff --git a/metamask-connect/multichain/quickstart/nodejs.md b/metamask-connect/multichain/quickstart/nodejs.md index 9a4946d74ae..f5b93b98a2b 100644 --- a/metamask-connect/multichain/quickstart/nodejs.md +++ b/metamask-connect/multichain/quickstart/nodejs.md @@ -47,6 +47,11 @@ Install the multichain client in an existing Node.js project: npm install @metamask/connect-multichain ``` +:::note +`@metamask/connect-multichain` (`^1.0.0`) is the multichain core. It's also the explicit peer +dependency that `@metamask/connect-evm` and `@metamask/connect-solana` 2.x require. +::: + ### 2. Initialize MetaMask Connect Multichain Create a file (`index.mjs`) and initialize the client using [`createMultichainClient`](../reference/methods.md#createmultichainclient). @@ -71,7 +76,8 @@ const client = await createMultichainClient({ :::info Async client `createMultichainClient` returns a promise. Always `await` it before using the client. -The client is a singleton; calling it again returns the same instance with merged options. +The client is a singleton; calling it again returns the same instance with merged options, except the +`dapp` object from the first call, which is never overwritten. ::: ### 3. Connect to MetaMask @@ -137,14 +143,14 @@ const solMsg = Buffer.from('Hello Solana!', 'utf8').toString('base64') const solSig = await client.invokeMethod({ scope: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', request: { - method: 'signMessage', + method: 'solana_signMessage', params: { - account: { address: solAddress }, message: solMsg, + pubkey: solAddress, }, }, }) -console.log('SOL signature:', solSig) +console.log('SOL signature:', solSig.signature) ``` ### 6. Disconnect @@ -250,14 +256,14 @@ const solMsg = Buffer.from('Hello Solana!', 'utf8').toString('base64') const solSig = await client.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'signMessage', + method: 'solana_signMessage', params: { - account: { address: solAddress }, message: solMsg, + pubkey: solAddress, }, }, }) -console.log('SOL signature:', solSig) +console.log('SOL signature:', solSig.signature) // Disconnect await client.disconnect() diff --git a/metamask-connect/multichain/quickstart/react-native.md b/metamask-connect/multichain/quickstart/react-native.md index 86847d4d3fc..06c32fa8810 100644 --- a/metamask-connect/multichain/quickstart/react-native.md +++ b/metamask-connect/multichain/quickstart/react-native.md @@ -147,6 +147,10 @@ if (typeof global.CustomEvent === 'undefined') { } ``` +:::note +The `Event` and `CustomEvent` polyfills above are only required if you also use wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. +::: + Create the empty module stub used by the Metro config: ```javascript title="src/empty-module.js" diff --git a/metamask-connect/multichain/reference/methods.md b/metamask-connect/multichain/reference/methods.md index a63c6f8e6ab..ff828750482 100644 --- a/metamask-connect/multichain/reference/methods.md +++ b/metamask-connect/multichain/reference/methods.md @@ -40,26 +40,29 @@ Use those standard methods if you're building your own client or need lower-leve ## `createMultichainClient` -Creates a new multichain client instance. +Creates the multichain client. The client is a singleton: the first call creates the instance, and +subsequent calls return that same instance. ### Parameters -| Name | Type | Required | Description | -| -------------------------- | ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dapp.name` | `string` | Yes | Name of your dapp. | -| `dapp.url` | `string` | No | URL of your dapp. In browsers this is often set automatically; required in Node.js and React Native. | -| `dapp.iconUrl` | `string` | No | URL of your dapp icon. | -| `dapp.base64Icon` | `string` | No | Base64-encoded icon when a hosted URL is unavailable (for example, some React Native setups). | -| `api.supportedNetworks` | `Record` | No | Map of [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) chain IDs to RPC URLs. Use [`getInfuraRpcUrls`](#getinfurarpcurls) to generate Infura URLs, then merge custom endpoints. | -| `ui.headless` | `boolean` | No | Enables or disables [headless mode](../guides/headless-mode.md). The default is `false`. | -| `ui.preferExtension` | `boolean` | No | Directly connects through the MetaMask extension when it's installed. The default is `true`. | -| `mobile.preferredOpenLink` | `(deeplink: string) => void` | No | A function that's called to open a deeplink to the MetaMask Mobile App. Required in React Native. | -| `mobile.useDeeplink` | `boolean` | No | Controls use of deeplinks for mobile connection flows. | +| Name | Type | Required | Description | +| -------------------------- | ---------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dapp.name` | `string` | Yes | Name of your dapp. | +| `dapp.url` | `string` | Conditional | URL of your dapp. In browsers this is often set automatically; required in Node.js and React Native (no `window.location`). | +| `dapp.iconUrl` | `string` | No | URL of your dapp icon. | +| `dapp.base64Icon` | `string` | No | Base64-encoded icon when a hosted URL is unavailable (for example, some React Native setups). | +| `api.supportedNetworks` | `Record` | No | Map of [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) chain IDs to RPC URLs. Use [`getInfuraRpcUrls`](#getinfurarpcurls) to generate Infura URLs, then merge custom endpoints. | +| `ui.headless` | `boolean` | No | Enables or disables [headless mode](../guides/headless-mode.md). The default is `false`. | +| `ui.preferExtension` | `boolean` | No | Directly connects through the MetaMask extension when it's installed. The default is `true`. | +| `mobile.preferredOpenLink` | `(deeplink: string) => void` | No | A function that's called to open a deeplink to the MetaMask Mobile App. Required in React Native. | +| `mobile.useDeeplink` | `boolean` | No | Controls use of deeplinks for mobile connection flows. | ### Returns -Returns a promise that resolves to a multichain client instance. -The client is a singleton; calling `createMultichainClient` again returns the same instance. +Returns a promise that resolves to the multichain client instance. +The client is a singleton: calling `createMultichainClient` again returns the same instance and merges +any new options, except the `dapp` object from the first call, which is never overwritten. The +`api.supportedNetworks` map merges additively across calls. ### Example @@ -105,6 +108,13 @@ A promise that resolves when the connection is established. await client.connect(['eip155:1', 'eip155:137', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'], []) ``` +To force a fresh connection prompt even when a session already exists, pass `forceRequest` as the +fourth argument: + +```javascript +await client.connect(['eip155:1'], [], undefined, true) +``` + ## `getSession` Returns the current multichain session, including the approved scopes and accounts. @@ -135,11 +145,11 @@ Use this to interact with any chain the user has approved, without switching con ### Parameters -| Name | Type | Required | Description | -| ------------------------ | ----------- | -------- | ---------------------------------------------------------------------------------------------- | -| `options.scope` | `Scope` | Yes | The [CAIP-2](https://chainagnostic.org/CAIPs/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. | +| Name | Type | Required | Description | +| ------------------------ | --------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | +| `options.scope` | `Scope` | Yes | The [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) chain identifier to invoke the method on. | +| `options.request.method` | `string` | Yes | The RPC method name. | +| `options.request.params` | `unknown[] \| object` | No | The method parameters. EVM methods take an array; Solana methods take an object (for example, `{ message, pubkey }`). | ### Returns @@ -361,11 +371,11 @@ const client = await createMultichainClient({ Register event handlers using [`on`](#on) and remove them with [`off`](#off). -| Event | Payload | Description | -| ----------------------- | ------------------ | -------------------------------------------------------------------- | -| `wallet_sessionChanged` | `Session` | Fired when session scopes or accounts change. | -| `display_uri` | `string` | Fired with a URI for custom QR code implementations (headless mode). | -| `stateChanged` | `ConnectionStatus` | Fired when the connection status changes. | +| Event | Payload | Description | +| ----------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `wallet_sessionChanged` | `Session` | Fired when the session changes: on connect, when scopes or accounts are added or removed, and during asynchronous session restoration. Register it before calling `connect` so restored sessions are captured. | +| `display_uri` | `string` | Fired with a URI for custom QR code implementations (headless mode). | +| `stateChanged` | `ConnectionStatus` | Fired when the connection status changes. | ### Example diff --git a/metamask-connect/multichain/tutorials/create-multichain-dapp.md b/metamask-connect/multichain/tutorials/create-multichain-dapp.md index 096bc3d11ff..940c9c39e74 100644 --- a/metamask-connect/multichain/tutorials/create-multichain-dapp.md +++ b/metamask-connect/multichain/tutorials/create-multichain-dapp.md @@ -137,6 +137,12 @@ const client = await getClient() await client.connect([SCOPES.ETHEREUM, SCOPES.LINEA, SCOPES.BASE, SCOPES.SOLANA], []) ``` +:::tip Restore existing sessions +Register a [`wallet_sessionChanged`](../reference/methods.md#events) listener before calling `connect`, +and skip `connect` when [`getSession`](../reference/methods.md#getsession) already returns a session +(for example, after a page reload). +::: + The second argument is an optional array of [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) account preferences. Pass an empty array to let the user choose their own accounts. @@ -597,7 +603,8 @@ export default function App() { - **Leverage session persistence.** Sessions survive page reloads and new tabs. - Check for an existing session on startup with `getSession` before prompting the user to connect + Register a `wallet_sessionChanged` listener before calling `connect` to capture restored sessions, + and check for an existing session on startup with `getSession` before prompting the user to connect again. - **Show chain context clearly.** diff --git a/metamask-connect/solana/guides/use-wallet-adapter.md b/metamask-connect/solana/guides/use-wallet-adapter.md index 0f44d270e66..ac303154274 100644 --- a/metamask-connect/solana/guides/use-wallet-adapter.md +++ b/metamask-connect/solana/guides/use-wallet-adapter.md @@ -43,6 +43,7 @@ Install MetaMask Connect Solana and the Wallet Adapter packages: ```bash npm install @metamask/connect-solana \ + @metamask/connect-multichain \ @solana/web3.js \ @solana/wallet-adapter-base \ @solana/wallet-adapter-react \ @@ -50,6 +51,10 @@ npm install @metamask/connect-solana \ @solana/wallet-adapter-wallets ``` +:::note +Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 2. Create the Solana provider Create a `SolanaProvider` component that initializes MetaMask Connect Solana and wraps the Wallet Adapter @@ -58,7 +63,7 @@ providers: ```typescript title='components/SolanaProvider.tsx' 'use client'; -import React, { FC, ReactNode, useEffect, useMemo } from 'react'; +import React, { FC, ReactNode, useEffect, useMemo, useState } from 'react'; import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'; import { WalletAdapterNetwork } from '@solana/wallet-adapter-base'; import { WalletModalProvider } from '@solana/wallet-adapter-react-ui'; @@ -74,6 +79,7 @@ interface SolanaProviderProps { export const SolanaProvider: FC = ({ children }) => { const network = WalletAdapterNetwork.Devnet; const endpoint = useMemo(() => clusterApiUrl(network), [network]); + const [ready, setReady] = useState(false); useEffect(() => { createSolanaClient({ @@ -81,9 +87,15 @@ export const SolanaProvider: FC = ({ children }) => { name: 'My Solana Dapp', url: window.location.origin, }, - }); + }).then(() => setReady(true)); }, []); + // Wait for createSolanaClient to resolve before mounting WalletProvider, so MetaMask + // is registered with the Wallet Standard registry before the wallet list renders. + if (!ready) { + return null; + } + return ( @@ -99,12 +111,10 @@ the [Wallet Standard](https://github.com/wallet-standard/wallet-standard) regist This displays MetaMask as a connection option in the wallet modal, even if the user doesn't have MetaMask installed. -:::tip Timing -The `useEffect` pattern above works because `createSolanaClient` typically resolves before the user -opens the wallet modal. -If MetaMask does not appear in the wallet list, ensure `createSolanaClient` has resolved before the -`WalletProvider` renders. -One approach is to await the client in your app's entry point before calling `createRoot().render()`. +:::warning Timing +MetaMask only appears in the wallet modal if `createSolanaClient` has resolved before the +`WalletProvider` mounts. The example above gates rendering on a `ready` flag to guarantee this. +As an alternative, await the client in your app's entry point before calling `createRoot().render()`. See [Troubleshooting: MetaMask wallet not appearing](../../troubleshooting/index.md#metamask-wallet-not-appearing-in-solana-wallet-adapter) for details. ::: diff --git a/metamask-connect/solana/index.mdx b/metamask-connect/solana/index.mdx index 45bcbf84035..c08c0181645 100644 --- a/metamask-connect/solana/index.mdx +++ b/metamask-connect/solana/index.mdx @@ -93,4 +93,4 @@ Yes. When you call `createSolanaClient`, MetaMask is automatically registered wi ### Which Solana networks does MetaMask Connect support? -MetaMask Connect Solana supports mainnet, devnet, and testnet. You can configure custom RPC URLs for each network using the `api.supportedNetworks` option in `createSolanaClient`. If your dapp also targets EVM networks, use [`@metamask/connect-multichain`](../multichain/index.mdx) to manage both ecosystems in a single session. +MetaMask Connect Solana supports mainnet, devnet, and testnet. Devnet and testnet are supported only in the MetaMask browser extension; on mobile, only mainnet is supported. You can configure custom RPC URLs for each network using the `api.supportedNetworks` option in `createSolanaClient`. If your dapp also targets EVM networks, use [`@metamask/connect-multichain`](../multichain/index.mdx) to manage both ecosystems in a single session. diff --git a/metamask-connect/solana/quickstart/javascript.md b/metamask-connect/solana/quickstart/javascript.md index 7a102f14d76..917d5afd67d 100644 --- a/metamask-connect/solana/quickstart/javascript.md +++ b/metamask-connect/solana/quickstart/javascript.md @@ -105,9 +105,13 @@ You've successfully set up MetaMask Connect Solana. Install the Solana Client in an existing JavaScript project: ```bash npm2yarn -npm install @metamask/connect-solana +npm install @metamask/connect-solana @metamask/connect-multichain ``` +:::note +Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 2. Initialize MetaMask Connect Solana Initialize the Solana client using [`createSolanaClient`](../reference/methods.md#createsolanaclient). @@ -155,6 +159,11 @@ console.log('Connected account:', accounts[0].address) The client handles cross-platform connection (desktop and mobile), including deeplinking. +:::note +This example uses devnet. Devnet and testnet are supported only in the MetaMask browser extension. +On mobile, only Solana mainnet is supported. +::: + ## Solana client methods at a glance | Method | Description | diff --git a/metamask-connect/solana/quickstart/nodejs.md b/metamask-connect/solana/quickstart/nodejs.md index 39250f92c9c..ea0621927b9 100644 --- a/metamask-connect/solana/quickstart/nodejs.md +++ b/metamask-connect/solana/quickstart/nodejs.md @@ -45,9 +45,13 @@ In Node.js, use the multichain core directly via `client.core.connect` and Install the Solana client in an existing Node.js project: ```bash npm2yarn -npm install @metamask/connect-solana +npm install @metamask/connect-solana @metamask/connect-multichain ``` +:::note +Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. +::: + ### 2. Initialize MetaMask Connect Solana Create a file (`index.mjs`) and initialize the client using [`createSolanaClient`](../reference/methods.md#createsolanaclient). @@ -107,19 +111,19 @@ const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64') const result = await solanaClient.core.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'signMessage', + method: 'solana_signMessage', params: { - account: { address }, message, + pubkey: address, }, }, }) -console.log('Signature:', result) +console.log('Signature:', result.signature) ``` ### 5. Disconnect -Use [`disconnect`](../reference/methods.md#disconnect) to disconnect all scopes and end the session. +Use [`disconnect`](../reference/methods.md#disconnect) to revoke the Solana scopes. Any EVM or other scopes in the same multichain session stay active. ```javascript await solanaClient.disconnect() @@ -147,10 +151,12 @@ solanaClient.core.on('wallet_sessionChanged', session => { | ------- | ----------------------------------------- | | Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | | Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | +| Testnet | `solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z` | :::note -Devnet and testnet require [MetaMask Flask](https://metamask.io/flask/). -Production MetaMask only supports Solana mainnet. +Devnet and testnet are supported only in the MetaMask browser extension (such as +[MetaMask Flask](https://metamask.io/flask/)). On mobile—including the QR code flow in this +quickstart—only Solana mainnet is supported. ::: ## Full example @@ -191,14 +197,14 @@ const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64') const result = await solanaClient.core.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'signMessage', + method: 'solana_signMessage', params: { - account: { address }, message, + pubkey: address, }, }, }) -console.log('Signature:', result) +console.log('Signature:', result.signature) // Disconnect await solanaClient.disconnect() diff --git a/metamask-connect/solana/reference/methods.md b/metamask-connect/solana/reference/methods.md index 9422138eb15..43e31dd6fd1 100644 --- a/metamask-connect/solana/reference/methods.md +++ b/metamask-connect/solana/reference/methods.md @@ -196,14 +196,15 @@ The wallet returned by [`getWallet`](#getwallet) implements the following [Wallet Standard](https://github.com/wallet-standard/wallet-standard) features. Access them via `wallet.features['']`. -| Feature | Description | -| ------------------------------- | ------------------------------------------------------ | -| `standard:connect` | Connect to the wallet and receive the user's accounts. | -| `standard:disconnect` | Disconnect from the wallet. | -| `standard:events` | Subscribe to account and chain change events. | -| `solana:signMessage` | Sign an arbitrary message (returns a signature). | -| `solana:signTransaction` | Sign a transaction without broadcasting it. | -| `solana:signAndSendTransaction` | Sign a transaction and broadcast it to the network. | +| Feature | Description | +| ----------------------------------- | ------------------------------------------------------------- | +| `standard:connect` | Connect to the wallet and receive the user's accounts. | +| `standard:disconnect` | Disconnect from the wallet. | +| `standard:events` | Subscribe to account and chain change events. | +| `solana:signMessage` | Sign an arbitrary message (returns a signature). | +| `solana:signTransaction` | Sign a transaction without broadcasting it. | +| `solana:signAndSendTransaction` | Sign a transaction and broadcast it to the network. | +| `solana:signAndSendAllTransactions` | Sign multiple transactions and broadcast them in one request. | ### Example @@ -239,16 +240,17 @@ type SolanaSupportedNetworks = Partial> Configuration options passed to [`createSolanaClient`](#createsolanaclient). -| Field | Type | Required | Description | -| ----------------------- | ------------------------- | -------- | -------------------------------------------------------------------------- | -| `dapp` | `object` | Yes | Dapp identification and branding settings. | -| `dapp.name` | `string` | Yes | Name of your dapp. | -| `dapp.url` | `string` | No | URL of your dapp. | -| `dapp.iconUrl` | `string` | No | URL of your dapp icon. | -| `api` | `object` | No | Optional API configuration. | -| `api.supportedNetworks` | `SolanaSupportedNetworks` | No | Map of network names (`mainnet`, `devnet`, `testnet`) to RPC URLs. | -| `debug` | `boolean` | No | Reserved for future use; not currently forwarded to the underlying client. | -| `skipAutoRegister` | `boolean` | No | Skips auto-registering the wallet during creation. The default is `false`. | +| Field | Type | Required | Description | +| --------------------------- | ------------------------- | -------- | -------------------------------------------------------------------------- | +| `dapp` | `object` | Yes | Dapp identification and branding settings. | +| `dapp.name` | `string` | Yes | Name of your dapp. | +| `dapp.url` | `string` | No | URL of your dapp. | +| `dapp.iconUrl` | `string` | No | URL of your dapp icon. | +| `api` | `object` | No | Optional API configuration. | +| `api.supportedNetworks` | `SolanaSupportedNetworks` | No | Map of network names (`mainnet`, `devnet`, `testnet`) to RPC URLs. | +| `analytics.integrationType` | `string` | No | Identifies your integration in analytics events. | +| `debug` | `boolean` | No | Reserved for future use; not currently forwarded to the underlying client. | +| `skipAutoRegister` | `boolean` | No | Skips auto-registering the wallet during creation. The default is `false`. | :::note `createSolanaClient` does not accept `eventHandlers`. diff --git a/metamask-connect/supported-platforms.md b/metamask-connect/supported-platforms.md index 72c74d98660..bbac78a7c9a 100644 --- a/metamask-connect/supported-platforms.md +++ b/metamask-connect/supported-platforms.md @@ -87,9 +87,16 @@ Select a ✅ to jump to the relevant quickstart or guide. :::note Node.js support uses QR code connections via the MetaMask mobile app. +In Node.js and React Native there's no `window.location`, so you must set `dapp.url` explicitly when +creating the client. See the [Node.js playground](https://github.com/MetaMask/connect-monorepo/tree/main/playground/node-playground) for a working example. ::: +:::note +On React Native and mobile, Solana supports mainnet only. Devnet and testnet are supported only in +the MetaMask browser extension. +::: + ## Next steps - [Explore integration options.](./integration-options.md) diff --git a/metamask-connect/troubleshooting/index.md b/metamask-connect/troubleshooting/index.md index 37c2e1afe1f..75a8c23ad75 100644 --- a/metamask-connect/troubleshooting/index.md +++ b/metamask-connect/troubleshooting/index.md @@ -26,7 +26,9 @@ The SDK handles its transport and crypto needs internally using browser-native A **React Native** is the exception. The React Native runtime lacks certain Web and Node.js APIs (`Buffer`, `crypto.getRandomValues`, -`stream`, `Event`, `CustomEvent`), so polyfills and Metro configuration are required. +`stream`, `window`), so polyfills and Metro configuration are required. +The `Event` and `CustomEvent` globals aren't needed by the `@metamask/connect-*` packages (which use +`eventemitter3` internally); polyfill them only if you also use wagmi. See the [React Native Metro polyfill guide](metro-polyfill-issues.md) for step-by-step setup instructions. @@ -36,14 +38,15 @@ The following error codes appear in `err.code` on rejected promises from `connec `invokeMethod`, and `provider.request` calls. Always check `err.code` before `err.message` for reliable error categorization. -| Code | Meaning | Recommended handling | -| -------- | --------------------------------- | ------------------------------------------------------------------------------------------ | -| `4001` | User rejected the request | Show a retry button. Do not log this to error-tracking services. | -| `-32002` | Request already pending | Show "Check MetaMask to approve the pending request." Do **not** call `connect()` again. | -| `-32602` | Invalid parameters | Verify that parameters match the expected types (for example, hex chain IDs, not decimal). | -| `-32603` | Internal error | Unexpected server-side error. Retry with exponential backoff. | -| `-32000` | Execution reverted / server error | Transaction would fail onchain. Check contract inputs and sender balance. | -| `1013` | Internal transport disconnect | The SDK handles reconnection internally. Do not treat this as a user-facing disconnect. | +| Code | Meaning | Recommended handling | +| -------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `4001` | User rejected the request | Show a retry button. Do not log this to error-tracking services. | +| `-32002` | Request already pending | Show "Check MetaMask to approve the pending request." Do **not** call `connect()` again. | +| `-32602` | Invalid parameters | Verify that parameters match the expected types (for example, hex chain IDs, not decimal). | +| `-32603` | Internal error | Unexpected server-side error. Retry with exponential backoff. | +| `4902` | Unrecognized chain ID | The chain isn't added to the wallet. Add it with `wallet_addEthereumChain`, or pass `chainConfiguration` to `switchChain`. See [Chain not configured](#chain-not-configured-in-supportednetworks). | +| `-32000` | Execution reverted / server error | Transaction would fail onchain. Check contract inputs and sender balance. | +| `1013` | Internal transport disconnect | The SDK handles reconnection internally. Do not treat this as a user-facing disconnect. | For the complete list of provider errors, see [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193#provider-errors) and @@ -121,6 +124,7 @@ Do **not** call `connect` again; the original promise resolves once the user act The chain ID passed to `connect` or `wallet_switchEthereumChain` is not listed in the `api.supportedNetworks` configuration. +The wallet rejects the request with `err.code === 4902` (unrecognized chain ID). Add every chain the dapp needs to `supportedNetworks` with a valid RPC URL: diff --git a/metamask-connect/troubleshooting/metro-polyfill-issues.md b/metamask-connect/troubleshooting/metro-polyfill-issues.md index ccc9e844beb..94aea1fc519 100644 --- a/metamask-connect/troubleshooting/metro-polyfill-issues.md +++ b/metamask-connect/troubleshooting/metro-polyfill-issues.md @@ -48,6 +48,9 @@ npm install react-native-get-random-values buffer readable-stream @react-native- ``` `react-native-get-random-values` provides `crypto.getRandomValues`, which MetaMask Connect requires. +React Native versions before 0.72 have no native `crypto.getRandomValues`; later versions may include +one, but this polyfill remains the reliable cross-version default. It must be the first import, before +any other module. `readable-stream` provides a `stream` shim for Metro. `buffer` provides the `Buffer` global. `@react-native-async-storage/async-storage` is needed for session persistence. From 5c7a605a8e29ec364da2313639b0447157088cb6 Mon Sep 17 00:00:00 2001 From: Mohammad Shahbaz Alam Date: Mon, 15 Jun 2026 09:41:14 +0400 Subject: [PATCH 2/5] Docs: update multichain peer-dep and Solana APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove guidance to explicitly install @metamask/connect-multichain for single-ecosystem packages and simplify install commands across EVM and Solana quickstarts. Rename Solana methods and Wallet Standard features (solana_signMessage → signMessage, solana_signAndSendTransaction/signAndSendAllTransactions → signAndSendTransaction) and update batch guidance to use the variadic signAndSendTransaction call. Revise error handling docs to use the new multichain error classes (RPCInvokeMethodErr, RPCHttpErr, RPCReadonlyResponseErr, RPCReadonlyRequestErr) and expose wallet RPC codes on err.rpcCode; remove the internal transport 1013 note from provider docs. Misc: update Wagmi quickstart to require @metamask/connect-evm@^2.1.0 and adjust examples/usages across multichain, evm, solana, reference, and troubleshooting pages to match the new APIs and patterns. --- .../evm/guides/migrate-from-sdk.md | 8 +-- metamask-connect/evm/index.mdx | 2 +- metamask-connect/evm/quickstart/javascript.md | 6 +- metamask-connect/evm/quickstart/nodejs.md | 6 +- .../evm/quickstart/react-native.md | 6 +- metamask-connect/evm/quickstart/wagmi.md | 6 +- .../evm/reference/provider-api.md | 8 ++- metamask-connect/index.md | 1 - metamask-connect/integration-options.md | 6 -- .../multichain/guides/send-transactions.md | 19 ++--- .../multichain/guides/sign-transactions.md | 17 +++-- .../multichain/quickstart/javascript.md | 5 -- .../multichain/quickstart/nodejs.md | 13 ++-- .../multichain/quickstart/react-native.md | 4 +- .../multichain/reference/methods.md | 41 ++++++----- .../tutorials/create-multichain-dapp.md | 18 ++--- .../solana/guides/send-transactions/batch.md | 72 ++++++++++++------- .../solana/guides/use-wallet-adapter.md | 13 ++-- .../solana/quickstart/javascript.md | 6 +- metamask-connect/solana/quickstart/nodejs.md | 14 ++-- .../solana/quickstart/react-native.md | 4 +- metamask-connect/solana/reference/methods.md | 17 +++-- metamask-connect/troubleshooting/index.md | 24 ++++--- 23 files changed, 152 insertions(+), 164 deletions(-) diff --git a/metamask-connect/evm/guides/migrate-from-sdk.md b/metamask-connect/evm/guides/migrate-from-sdk.md index e44e029294a..50d00573a6f 100644 --- a/metamask-connect/evm/guides/migrate-from-sdk.md +++ b/metamask-connect/evm/guides/migrate-from-sdk.md @@ -44,8 +44,8 @@ npm uninstall @metamask/sdk # For React Native, remove npm uninstall @metamask/sdk-react -# Install new (EVM). @metamask/connect-multichain is a required peer dependency since @metamask/connect-evm 2.0.0. -npm install @metamask/connect-evm @metamask/connect-multichain +# Install new (EVM only) +npm install @metamask/connect-evm ``` ### 2. Update imports @@ -346,10 +346,6 @@ If your dapp supports (or plans to support) both EVM and Solana, consider upgrad The EVM client is built on top of `createMultichainClient` internally, so the upgrade is straightforward: -```bash npm2yarn -npm install @metamask/connect-multichain -``` - ```typescript import { createMultichainClient } from '@metamask/connect-multichain' diff --git a/metamask-connect/evm/index.mdx b/metamask-connect/evm/index.mdx index 416cabad4ce..fc6849caaae 100644 --- a/metamask-connect/evm/index.mdx +++ b/metamask-connect/evm/index.mdx @@ -99,7 +99,7 @@ We recommend using an Infura API key for production dapps. MetaMask Connect EVM To migrate: -- Replace `@metamask/sdk` with `@metamask/connect-evm` in your dependencies, and add `@metamask/connect-multichain` (a required peer dependency since `@metamask/connect-evm` 2.0.0). +- Replace `@metamask/sdk` with `@metamask/connect-evm` in your dependencies. - Update imports from `MetaMaskSDK` to `createEVMClient`. - Switch from synchronous to async initialization. - Update your provider access pattern. diff --git a/metamask-connect/evm/quickstart/javascript.md b/metamask-connect/evm/quickstart/javascript.md index f7808a1005d..69fe4872b41 100644 --- a/metamask-connect/evm/quickstart/javascript.md +++ b/metamask-connect/evm/quickstart/javascript.md @@ -125,13 +125,9 @@ You've successfully set up MetaMask Connect EVM. Install the EVM client in an existing JavaScript project: ```bash npm2yarn -npm install @metamask/connect-evm @metamask/connect-multichain +npm install @metamask/connect-evm ``` -:::note -Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 2. Initialize MetaMask Connect EVM Initialize the EVM client using [`createEVMClient`](../reference/methods.md#createevmclient). diff --git a/metamask-connect/evm/quickstart/nodejs.md b/metamask-connect/evm/quickstart/nodejs.md index e5476e4cd5f..775c4da11c6 100644 --- a/metamask-connect/evm/quickstart/nodejs.md +++ b/metamask-connect/evm/quickstart/nodejs.md @@ -42,13 +42,9 @@ polyfilling in browser or React Native environments. Install the EVM client in an existing Node.js project: ```bash npm2yarn -npm install @metamask/connect-evm @metamask/connect-multichain +npm install @metamask/connect-evm ``` -:::note -Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 2. Initialize MetaMask Connect EVM Create a file (`index.mjs`) and initialize the client using [`createEVMClient`](../reference/methods.md#createevmclient). diff --git a/metamask-connect/evm/quickstart/react-native.md b/metamask-connect/evm/quickstart/react-native.md index 8ccf21fa943..020091067f2 100644 --- a/metamask-connect/evm/quickstart/react-native.md +++ b/metamask-connect/evm/quickstart/react-native.md @@ -55,13 +55,9 @@ npx create-expo-app MyProject --template Install MetaMask Connect EVM and its required polyfill packages: ```bash -npm install @metamask/connect-evm @metamask/connect-multichain react-native-get-random-values buffer @react-native-async-storage/async-storage readable-stream +npm install @metamask/connect-evm react-native-get-random-values buffer @react-native-async-storage/async-storage readable-stream ``` -:::note -Since `@metamask/connect-evm` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 3. Create polyfills Create `polyfills.ts` (at the project root or in `src/`) with all required global shims. diff --git a/metamask-connect/evm/quickstart/wagmi.md b/metamask-connect/evm/quickstart/wagmi.md index 62a01b4e808..1792b2dd2a8 100644 --- a/metamask-connect/evm/quickstart/wagmi.md +++ b/metamask-connect/evm/quickstart/wagmi.md @@ -97,11 +97,11 @@ TOD0: Update with new screenshot and link Install MetaMask Connect EVM along with its peer dependencies to an existing React project: :::note Version requirements -This quickstart requires `wagmi@^3.6.0`. The `metaMask` connector is imported from the `wagmi/connectors` subpath (part of the `wagmi` package), and requires `@metamask/connect-evm`, which in turn requires `@metamask/connect-multichain` as a peer dependency. +This quickstart requires `wagmi@^3.6.0`. The `metaMask` connector is imported from the `wagmi/connectors` subpath (part of the `wagmi` package) and requires `@metamask/connect-evm@^2.1.0`. ::: ```bash npm2yarn -npm install @metamask/connect-evm @metamask/connect-multichain wagmi@^3.6.0 viem@2.x @tanstack/react-query +npm install @metamask/connect-evm@^2.1.0 wagmi@^3.6.0 viem@2.x @tanstack/react-query ``` ### 2. Import required dependencies @@ -320,7 +320,7 @@ If you previously used `@metamask/sdk` with Wagmi, the MetaMask connector now us ```bash npm2yarn npm uninstall @metamask/sdk - npm install @metamask/connect-evm @metamask/connect-multichain wagmi@^3.6.0 + npm install @metamask/connect-evm@^2.1.0 wagmi@^3.6.0 ``` 2. Update hook usage for wagmi v3: diff --git a/metamask-connect/evm/reference/provider-api.md b/metamask-connect/evm/reference/provider-api.md index 5fb33482eae..7dae5233b20 100644 --- a/metamask-connect/evm/reference/provider-api.md +++ b/metamask-connect/evm/reference/provider-api.md @@ -338,7 +338,6 @@ Common codes and their meaning include: - `4902` - The chain isn't recognized by the wallet. Add it with `wallet_addEthereumChain`, or pass `chainConfiguration` to [`switchChain`](methods.md#switchchain). - `-32602` - The parameters are invalid. - `-32603` - Internal error. -- `1013` - An internal transport disconnect. The SDK retries automatically, so don't treat it as a user-facing disconnect. For the complete list of errors, see [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193#provider-errors) and [EIP-1474](https://eips.ethereum.org/EIPS/eip-1474#error-codes). @@ -349,8 +348,11 @@ returned by the MetaMask provider, and can help you identify their meaning. ::: :::note Typed errors -The multichain core exports typed error classes for `instanceof` checks: `ProtocolError`, -`StorageError`, and `RpcError` from `@metamask/connect-multichain`. +When you use the multichain client, the core (`@metamask/connect-multichain`) exports typed error +classes for `instanceof` checks: `RPCInvokeMethodErr` (wraps wallet `invokeMethod` errors—read the +wallet's original code from `err.rpcCode`), `RPCHttpErr`, `RPCReadonlyResponseErr`, and +`RPCReadonlyRequestErr`. The EVM provider itself rejects with a standard EIP-1193 `ProviderRpcError` +(use `err.code`). ::: ## Next steps diff --git a/metamask-connect/index.md b/metamask-connect/index.md index 468cbf5a63d..7ce9e74476e 100644 --- a/metamask-connect/index.md +++ b/metamask-connect/index.md @@ -96,7 +96,6 @@ See [supported platforms](supported-platforms.md) for the full matrix. ### Which blockchain networks does MetaMask Connect support? MetaMask Connect supports Ethereum and all EVM-compatible networks (Polygon, Arbitrum, Optimism, Linea, Base, etc.) through `@metamask/connect-evm`, Solana through `@metamask/connect-solana`, and both simultaneously through `@metamask/connect-multichain`. -Since their 2.0.0 releases, `@metamask/connect-evm` and `@metamask/connect-solana` require `@metamask/connect-multichain` as an explicitly installed peer dependency. See [integration options](integration-options.md) to choose the right package. ### Do I need an Infura API key to use MetaMask Connect? diff --git a/metamask-connect/integration-options.md b/metamask-connect/integration-options.md index 681dd05b5b7..523e7cf39bc 100644 --- a/metamask-connect/integration-options.md +++ b/metamask-connect/integration-options.md @@ -58,12 +58,6 @@ If your dapp supports both EVM and Solana, use [`@metamask/connect-evm`](evm/ind [`@metamask/connect-solana`](solana/index.mdx) together to support both ecosystems while keeping familiar provider interfaces for each. -:::note -The `@metamask/connect-evm` and `@metamask/connect-solana` packages require -`@metamask/connect-multichain` as an explicitly installed peer dependency since their 2.0.0 releases. -Install it alongside whichever single-ecosystem package you use. -::: - ## Compare options | | Multichain | Single-ecosystem | Multi-ecosystem | diff --git a/metamask-connect/multichain/guides/send-transactions.md b/metamask-connect/multichain/guides/send-transactions.md index 0a313f6d05c..127a2642f36 100644 --- a/metamask-connect/multichain/guides/send-transactions.md +++ b/metamask-connect/multichain/guides/send-transactions.md @@ -133,7 +133,7 @@ console.log('Estimated gas:', gasEstimate) ## Build and send a Solana transaction -Build a transaction with `@solana/web3.js`, serialize it to base64, then send it with `solana_signAndSendTransaction`. +Build a transaction with `@solana/web3.js`, serialize it to base64, then send it with `signAndSendTransaction`. This signs and broadcasts the transaction in one step: ```javascript @@ -163,8 +163,9 @@ const base64Transaction = Buffer.from(serialized).toString('base64') const result = await client.invokeMethod({ scope: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', request: { - method: 'solana_signAndSendTransaction', + method: 'signAndSendTransaction', params: { + account: { address: fromPubkey.toBase58() }, transaction: base64Transaction, }, }, @@ -174,15 +175,16 @@ console.log('SOL tx signature:', result.signature) ## Sign a Solana transaction without sending -Use `solana_signTransaction` to get the signed transaction back without broadcasting it. +Use `signTransaction` to get the signed transaction back without broadcasting it. This is useful when you need to inspect or modify the signed output before submitting: ```javascript const signResult = await client.invokeMethod({ scope: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', request: { - method: 'solana_signTransaction', + method: 'signTransaction', params: { + account: { address: fromPubkey.toBase58() }, transaction: base64Transaction, }, }, @@ -196,11 +198,10 @@ console.log('Transaction ID:', txId) ## Error handling -| Error code | Description | Action | -| ---------- | ----------------------------- | -------------------------------------------------------------------------- | -| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | -| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | -| `1013` | Internal transport disconnect | The SDK retries automatically. Don't treat it as a user-facing disconnect. | +| Error code | Description | Action | +| ---------- | ------------------------- | ---------------------------------------------------------- | +| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | +| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. |
diff --git a/metamask-connect/multichain/guides/sign-transactions.md b/metamask-connect/multichain/guides/sign-transactions.md index a6a51466953..65c3bbd177d 100644 --- a/metamask-connect/multichain/guides/sign-transactions.md +++ b/metamask-connect/multichain/guides/sign-transactions.md @@ -128,9 +128,9 @@ The `EIP712Domain` type must be declared in `types` even though `primaryType` is Chain IDs in the typed data `domain.chainId` are integers (for example, `1`), not hex strings. ::: -## Sign a Solana message (`solana_signMessage`) +## Sign a Solana message (`signMessage`) -Use [`invokeMethod`](../reference/methods.md#invokemethod) with `solana_signMessage` to sign an arbitrary message on Solana. +Use [`invokeMethod`](../reference/methods.md#invokemethod) with `signMessage` to sign an arbitrary message on Solana. The message must be base64-encoded: ```javascript @@ -139,10 +139,10 @@ const message = btoa('Hello from Solana!') const result = await client.invokeMethod({ scope: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // Solana Mainnet request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: 'YourSolanaPublicKeyBase58' }, message, - pubkey: 'YourSolanaPublicKeyBase58', }, }, }) @@ -151,11 +151,10 @@ console.log('Signature:', result.signature) ## Error handling -| Error code | Description | Action | -| ---------- | ----------------------------- | -------------------------------------------------------------------------- | -| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | -| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. | -| `1013` | Internal transport disconnect | The SDK retries automatically. Don't treat it as a user-facing disconnect. | +| Error code | Description | Action | +| ---------- | ------------------------- | ---------------------------------------------------------- | +| `4001` | User rejected the request | Show a retry option. Do not treat as an application error. | +| `-32002` | Request already pending | Wait for the user to respond in MetaMask before retrying. |
diff --git a/metamask-connect/multichain/quickstart/javascript.md b/metamask-connect/multichain/quickstart/javascript.md index 3e19cc5ab2c..81f4ec30ae3 100644 --- a/metamask-connect/multichain/quickstart/javascript.md +++ b/metamask-connect/multichain/quickstart/javascript.md @@ -113,11 +113,6 @@ Install the multichain client in an existing JavaScript (Vite) project: npm install @metamask/connect-multichain ``` -:::note -`@metamask/connect-multichain` (`^1.0.0`) is the multichain core. It's also the explicit peer -dependency that `@metamask/connect-evm` and `@metamask/connect-solana` 2.x require. -::: - ### 2. Initialize MetaMask Connect Multichain Initialize the multichain client using [`createMultichainClient`](../reference/methods.md#createmultichainclient). diff --git a/metamask-connect/multichain/quickstart/nodejs.md b/metamask-connect/multichain/quickstart/nodejs.md index f5b93b98a2b..b4563804471 100644 --- a/metamask-connect/multichain/quickstart/nodejs.md +++ b/metamask-connect/multichain/quickstart/nodejs.md @@ -47,11 +47,6 @@ Install the multichain client in an existing Node.js project: npm install @metamask/connect-multichain ``` -:::note -`@metamask/connect-multichain` (`^1.0.0`) is the multichain core. It's also the explicit peer -dependency that `@metamask/connect-evm` and `@metamask/connect-solana` 2.x require. -::: - ### 2. Initialize MetaMask Connect Multichain Create a file (`index.mjs`) and initialize the client using [`createMultichainClient`](../reference/methods.md#createmultichainclient). @@ -143,10 +138,10 @@ const solMsg = Buffer.from('Hello Solana!', 'utf8').toString('base64') const solSig = await client.invokeMethod({ scope: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: solAddress }, message: solMsg, - pubkey: solAddress, }, }, }) @@ -256,10 +251,10 @@ const solMsg = Buffer.from('Hello Solana!', 'utf8').toString('base64') const solSig = await client.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: solAddress }, message: solMsg, - pubkey: solAddress, }, }, }) diff --git a/metamask-connect/multichain/quickstart/react-native.md b/metamask-connect/multichain/quickstart/react-native.md index 06c32fa8810..bcacb482b8e 100644 --- a/metamask-connect/multichain/quickstart/react-native.md +++ b/metamask-connect/multichain/quickstart/react-native.md @@ -366,8 +366,8 @@ export default function App() { const result = await client.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'solana_signMessage', - params: { message, pubkey }, + method: 'signMessage', + params: { account: { address: pubkey }, message }, }, }) Alert.alert('Signed', result.signature.slice(0, 40) + '...') diff --git a/metamask-connect/multichain/reference/methods.md b/metamask-connect/multichain/reference/methods.md index ff828750482..56da397dc8b 100644 --- a/metamask-connect/multichain/reference/methods.md +++ b/metamask-connect/multichain/reference/methods.md @@ -145,11 +145,11 @@ Use this to interact with any chain the user has approved, without switching con ### Parameters -| Name | Type | Required | Description | -| ------------------------ | --------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | -| `options.scope` | `Scope` | Yes | The [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) chain identifier to invoke the method on. | -| `options.request.method` | `string` | Yes | The RPC method name. | -| `options.request.params` | `unknown[] \| object` | No | The method parameters. EVM methods take an array; Solana methods take an object (for example, `{ message, pubkey }`). | +| Name | Type | Required | Description | +| ------------------------ | --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| `options.scope` | `Scope` | Yes | The [CAIP-2](https://chainagnostic.org/CAIPs/caip-2) chain identifier to invoke the method on. | +| `options.request.method` | `string` | Yes | The RPC method name. | +| `options.request.params` | `unknown[] \| object` | No | The method parameters. EVM methods take an array; Solana methods take an object (for example, `{ account: { address }, message }`). | ### Returns @@ -396,28 +396,31 @@ client.on('stateChanged', status => { ## Error classes -`@metamask/connect-multichain` exports typed error classes for granular error handling: +`@metamask/connect-multichain` exports typed error classes (all extending a common `BaseErr`) for granular error handling: -| Class | Description | -| --------------- | ------------------------------------------------------------- | -| `RpcError` | JSON-RPC errors from the wallet (includes `code` and `data`). | -| `ProtocolError` | Connection protocol failures (transport, pairing, handshake). | -| `StorageError` | Session persistence issues (read/write failures). | +| Class | Code | Description | +| ------------------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `RPCInvokeMethodErr` | 53 | A wallet `invokeMethod` call failed. Wraps the wallet's error: read `rpcCode`, `rpcMessage`, and `rpcData` for the original JSON-RPC / EIP-1193 details, and `reason` for the normalized message. | +| `RPCHttpErr` | 50 | An HTTP-level failure calling a read-only RPC endpoint (exposes `rpcEndpoint`, `method`, and `httpStatus`). | +| `RPCReadonlyResponseErr` | 51 | A read-only RPC endpoint returned an error response (exposes `reason`). | +| `RPCReadonlyRequestErr` | 52 | A read-only RPC request couldn't be issued (exposes `reason`). | ### Example ```javascript -import { ProtocolError, RpcError, StorageError } from '@metamask/connect-multichain' +import { RPCInvokeMethodErr } from '@metamask/connect-multichain' try { - await client.connect(['eip155:1'], []) + await client.invokeMethod({ + scope: 'eip155:1', + request: { method: 'personal_sign', params: [message, address] }, + }) } catch (err) { - if (err instanceof RpcError) { - // Check err.code for specific RPC error codes (4001, -32002, etc.) - } else if (err instanceof ProtocolError) { - // Connection protocol failure - } else if (err instanceof StorageError) { - // Session persistence issue + if (err instanceof RPCInvokeMethodErr) { + // The wallet's original code is on err.rpcCode (for example, 4001 when the user rejects). + if (err.rpcCode === 4001) { + // User rejected — show retry UI + } } } ``` diff --git a/metamask-connect/multichain/tutorials/create-multichain-dapp.md b/metamask-connect/multichain/tutorials/create-multichain-dapp.md index 940c9c39e74..62bebe7822c 100644 --- a/metamask-connect/multichain/tutorials/create-multichain-dapp.md +++ b/metamask-connect/multichain/tutorials/create-multichain-dapp.md @@ -267,19 +267,19 @@ const signature = await client.invokeMethod({ console.log('EVM signature:', signature) ``` -#### Solana (`solana_signMessage`) +#### Solana (`signMessage`) -Use [`invokeMethod`](../reference/methods.md#invokemethod) with `solana_signMessage` to sign a message on Solana: +Use [`invokeMethod`](../reference/methods.md#invokemethod) with `signMessage` to sign a message on Solana: ```typescript const solAddress = extractAddress(solAccounts[0]) const signature = await client.invokeMethod({ scope: SCOPES.SOLANA, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: solAddress }, message: btoa('Hello from my multichain dapp!'), - pubkey: solAddress, }, }, }) @@ -316,14 +316,16 @@ The same address format and RPC method works across all EVM chains. #### Solana transaction -Use [`invokeMethod`](../reference/methods.md#invokemethod) with `solana_signAndSendTransaction` to send a Solana base64-encoded transaction: +Use [`invokeMethod`](../reference/methods.md#invokemethod) with `signAndSendTransaction` to send a Solana base64-encoded transaction: ```typescript +const solAddress = extractAddress(solAccounts[0]) const result = await client.invokeMethod({ scope: SCOPES.SOLANA, request: { - method: 'solana_signAndSendTransaction', + method: 'signAndSendTransaction', params: { + account: { address: solAddress }, transaction: '', }, }, @@ -503,10 +505,10 @@ export default function App() { const sig = await client.invokeMethod({ scope: SCOPES.SOLANA, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: solAddress }, message: btoa('Hello from my multichain dapp!'), - pubkey: solAddress, }, }, }) diff --git a/metamask-connect/solana/guides/send-transactions/batch.md b/metamask-connect/solana/guides/send-transactions/batch.md index 26e4d5ed69f..54de12118db 100644 --- a/metamask-connect/solana/guides/send-transactions/batch.md +++ b/metamask-connect/solana/guides/send-transactions/batch.md @@ -1,12 +1,12 @@ --- title: 'Send Batch Solana Transactions - MetaMask Connect' sidebar_label: Send batch transactions -description: Sign and send multiple Solana transactions in a single wallet interaction using the signAndSendAllTransactions Wallet Standard feature. +description: Sign and send multiple Solana transactions by passing several inputs to the variadic signAndSendTransaction Wallet Standard feature. keywords: [ solana, batch transactions, - signAndSendAllTransactions, + signAndSendTransaction, wallet-standard, MetaMask, Connect, @@ -16,11 +16,17 @@ keywords: # Send batch transactions -The `solana:signAndSendAllTransactions` Wallet Standard feature lets you sign and send multiple -Solana transactions in a single wallet interaction. +The [`solana:signAndSendTransaction`](../../reference/methods.md#supported-wallet-standard-features) +Wallet Standard feature is variadic: you can pass multiple transaction inputs to a single call to +sign and send them, and it resolves to one result per transaction. This is useful for operations that span several transactions, such as initializing multiple accounts, batch token transfers, or multi-step program interactions. +:::note +There is no separate `signAndSendAllTransactions` feature. Send a batch by passing several inputs to +`signAndSendTransaction`. +::: + ## Prerequisites Follow Step 1 of the [quickstart](../../quickstart/javascript.md) to install the Solana client. @@ -80,29 +86,40 @@ const serializedTransactions = recipients.map(recipient => { }) ``` -### 3. Sign and send all transactions +### 3. Sign and send the transactions -Use the [`solana:signAndSendAllTransactions`](../../reference/methods.md#supported-wallet-standard-features) feature to submit the batch: +Pass each serialized transaction as a separate input to +[`signAndSendTransaction`](../../reference/methods.md#supported-wallet-standard-features). +The feature accepts one or more inputs and resolves to an array with one result per transaction: ```javascript -const batchFeature = wallet.features['solana:signAndSendAllTransactions'] +const sendFeature = wallet.features['solana:signAndSendTransaction'] -const results = await batchFeature.signAndSendAllTransactions({ - account, - transactions: serializedTransactions, - chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', -}) +const results = await sendFeature.signAndSendTransaction( + ...serializedTransactions.map(transaction => ({ + account, + transaction, + chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', + })) +) ``` +Each result contains a `signature` as a `Uint8Array`, in the same order as the inputs. + ### 4. Confirm each transaction -Always confirm transactions before updating the UI: +Always confirm transactions before updating the UI. +The Wallet Standard returns each signature as bytes, so encode it to base58 for +`confirmTransaction`: ```javascript +import bs58 from 'bs58' + for (const { signature } of results) { + const signatureStr = bs58.encode(signature) const confirmation = await connection.confirmTransaction( { - signature, + signature: signatureStr, blockhash, lastValidBlockHeight: (await connection.getLatestBlockhash()).lastValidBlockHeight, }, @@ -112,26 +129,31 @@ for (const { signature } of results) { if (confirmation.value.err) { console.error('Transaction failed on-chain:', confirmation.value.err) } else { - console.log('Transaction confirmed:', signature) + console.log('Transaction confirmed:', signatureStr) } } ``` ## Error handling -When sending batch transactions, handle common errors: +When sending batch transactions, handle common errors. +Wallet calls reject with an `RPCInvokeMethodErr`, which exposes the wallet's original code on +`rpcCode`: ```javascript try { - const results = await batchFeature.signAndSendAllTransactions({ - account, - transactions: serializedTransactions, - chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', - }) + const results = await sendFeature.signAndSendTransaction( + ...serializedTransactions.map(transaction => ({ + account, + transaction, + chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', + })) + ) } catch (err) { - if (err.code === 4001) { - // User rejected the batch — show retry UI - } else if (err.code === -32002) { + const walletCode = err.rpcCode ?? err.code + if (walletCode === 4001) { + // User rejected — show retry UI + } else if (walletCode === -32002) { // Request already pending — ask user to check MetaMask } else { console.error('Batch transaction error:', err) @@ -145,6 +167,8 @@ try { Call `getLatestBlockhash` immediately before building the batch. - **Transaction size:** Each individual transaction is limited to 1,232 bytes. If a single transaction exceeds this limit, split it into smaller transactions. +- **Sequential processing:** Inputs are processed in order, and the call resolves with one result per + transaction once all are submitted. - **Confirmation:** A submitted transaction is not finalized until `confirmTransaction` returns. Always confirm before reporting success to the user. - **Devnet and testnet** are only supported in the MetaMask browser extension, not the mobile wallet. diff --git a/metamask-connect/solana/guides/use-wallet-adapter.md b/metamask-connect/solana/guides/use-wallet-adapter.md index ac303154274..20ee17af663 100644 --- a/metamask-connect/solana/guides/use-wallet-adapter.md +++ b/metamask-connect/solana/guides/use-wallet-adapter.md @@ -43,18 +43,13 @@ Install MetaMask Connect Solana and the Wallet Adapter packages: ```bash npm install @metamask/connect-solana \ - @metamask/connect-multichain \ - @solana/web3.js \ - @solana/wallet-adapter-base \ - @solana/wallet-adapter-react \ - @solana/wallet-adapter-react-ui \ + @solana/web3.js \ + @solana/wallet-adapter-base \ + @solana/wallet-adapter-react \ + @solana/wallet-adapter-react-ui \ @solana/wallet-adapter-wallets ``` -:::note -Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 2. Create the Solana provider Create a `SolanaProvider` component that initializes MetaMask Connect Solana and wraps the Wallet Adapter diff --git a/metamask-connect/solana/quickstart/javascript.md b/metamask-connect/solana/quickstart/javascript.md index 917d5afd67d..374cffcce5f 100644 --- a/metamask-connect/solana/quickstart/javascript.md +++ b/metamask-connect/solana/quickstart/javascript.md @@ -105,13 +105,9 @@ You've successfully set up MetaMask Connect Solana. Install the Solana Client in an existing JavaScript project: ```bash npm2yarn -npm install @metamask/connect-solana @metamask/connect-multichain +npm install @metamask/connect-solana ``` -:::note -Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 2. Initialize MetaMask Connect Solana Initialize the Solana client using [`createSolanaClient`](../reference/methods.md#createsolanaclient). diff --git a/metamask-connect/solana/quickstart/nodejs.md b/metamask-connect/solana/quickstart/nodejs.md index ea0621927b9..4182521538f 100644 --- a/metamask-connect/solana/quickstart/nodejs.md +++ b/metamask-connect/solana/quickstart/nodejs.md @@ -45,13 +45,9 @@ In Node.js, use the multichain core directly via `client.core.connect` and Install the Solana client in an existing Node.js project: ```bash npm2yarn -npm install @metamask/connect-solana @metamask/connect-multichain +npm install @metamask/connect-solana ``` -:::note -Since `@metamask/connect-solana` 2.0.0, `@metamask/connect-multichain` is a required peer dependency that you must install explicitly. -::: - ### 2. Initialize MetaMask Connect Solana Create a file (`index.mjs`) and initialize the client using [`createSolanaClient`](../reference/methods.md#createsolanaclient). @@ -111,10 +107,10 @@ const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64') const result = await solanaClient.core.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address }, message, - pubkey: address, }, }, }) @@ -197,10 +193,10 @@ const message = Buffer.from('Hello from Node.js!', 'utf8').toString('base64') const result = await solanaClient.core.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address }, message, - pubkey: address, }, }, }) diff --git a/metamask-connect/solana/quickstart/react-native.md b/metamask-connect/solana/quickstart/react-native.md index 975665c99e8..023e4f3d2f7 100644 --- a/metamask-connect/solana/quickstart/react-native.md +++ b/metamask-connect/solana/quickstart/react-native.md @@ -335,10 +335,10 @@ export default function App() { const result = await client.invokeMethod({ scope: SOLANA_MAINNET, request: { - method: 'solana_signMessage', + method: 'signMessage', params: { + account: { address: accounts[0] }, message, - pubkey: accounts[0], }, }, }) diff --git a/metamask-connect/solana/reference/methods.md b/metamask-connect/solana/reference/methods.md index 43e31dd6fd1..2e455afb779 100644 --- a/metamask-connect/solana/reference/methods.md +++ b/metamask-connect/solana/reference/methods.md @@ -196,15 +196,14 @@ The wallet returned by [`getWallet`](#getwallet) implements the following [Wallet Standard](https://github.com/wallet-standard/wallet-standard) features. Access them via `wallet.features['']`. -| Feature | Description | -| ----------------------------------- | ------------------------------------------------------------- | -| `standard:connect` | Connect to the wallet and receive the user's accounts. | -| `standard:disconnect` | Disconnect from the wallet. | -| `standard:events` | Subscribe to account and chain change events. | -| `solana:signMessage` | Sign an arbitrary message (returns a signature). | -| `solana:signTransaction` | Sign a transaction without broadcasting it. | -| `solana:signAndSendTransaction` | Sign a transaction and broadcast it to the network. | -| `solana:signAndSendAllTransactions` | Sign multiple transactions and broadcast them in one request. | +| Feature | Description | +| ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `standard:connect` | Connect to the wallet and receive the user's accounts. | +| `standard:disconnect` | Disconnect from the wallet. | +| `standard:events` | Subscribe to account and chain change events. | +| `solana:signMessage` | Sign an arbitrary message (returns a signature). | +| `solana:signTransaction` | Sign one or more transactions without broadcasting them (variadic). | +| `solana:signAndSendTransaction` | Sign one or more transactions and broadcast them to the network. Pass multiple inputs to send a batch (variadic). | ### Example diff --git a/metamask-connect/troubleshooting/index.md b/metamask-connect/troubleshooting/index.md index 75a8c23ad75..8a040f226ea 100644 --- a/metamask-connect/troubleshooting/index.md +++ b/metamask-connect/troubleshooting/index.md @@ -46,30 +46,34 @@ Always check `err.code` before `err.message` for reliable error categorization. | `-32603` | Internal error | Unexpected server-side error. Retry with exponential backoff. | | `4902` | Unrecognized chain ID | The chain isn't added to the wallet. Add it with `wallet_addEthereumChain`, or pass `chainConfiguration` to `switchChain`. See [Chain not configured](#chain-not-configured-in-supportednetworks). | | `-32000` | Execution reverted / server error | Transaction would fail onchain. Check contract inputs and sender balance. | -| `1013` | Internal transport disconnect | The SDK handles reconnection internally. Do not treat this as a user-facing disconnect. | For the complete list of provider errors, see [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193#provider-errors) and [EIP-1474](https://eips.ethereum.org/EIPS/eip-1474#error-codes). -MetaMask Connect Multichain also exports typed error classes for granular `instanceof` checks: +MetaMask Connect Multichain also exports typed error classes for granular `instanceof` checks. The +class most relevant to wallet calls is `RPCInvokeMethodErr`, which wraps the wallet's response and +exposes the wallet's original error code on `err.rpcCode`: ```typescript -import { ProtocolError, RpcError, StorageError } from '@metamask/connect-multichain' +import { RPCInvokeMethodErr } from '@metamask/connect-multichain' try { - await client.connect(['eip155:1'], []) + await client.invokeMethod({ + scope: 'eip155:1', + request: { method: 'personal_sign', params: [message, address] }, + }) } catch (err) { - if (err instanceof RpcError) { - console.log('RPC error code:', err.code) - } else if (err instanceof ProtocolError) { - console.log('Protocol failure:', err.message) - } else if (err instanceof StorageError) { - console.log('Session persistence issue:', err.message) + if (err instanceof RPCInvokeMethodErr) { + // The wallet's original JSON-RPC / EIP-1193 code is on err.rpcCode (for example, 4001). + console.log('Wallet error code:', err.rpcCode) } } ``` +The core also exports `RPCHttpErr`, `RPCReadonlyResponseErr`, and `RPCReadonlyRequestErr` for +read-only RPC failures. + ## Common issues ### Connection hangs after `connect()` From d3f7fe0dcecb50d3a0f5acce0287e098e2f40506 Mon Sep 17 00:00:00 2001 From: Mohammad Shahbaz Alam Date: Mon, 15 Jun 2026 10:01:51 +0400 Subject: [PATCH 3/5] Standardize Wagmi capitalization in docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a terminology rule for Wagmi and update docs for consistent capitalization. Changes touch the terminology rules and multiple MetaMask Connect docs (quickstarts, guides, troubleshooting, supported-platforms, and references) to use “Wagmi” consistently and include small copy/formatting fixes (polyfill guidance and minor punctuation/lineflow adjustments). --- .cursor/rules/terminology.mdc | 1 + metamask-connect/evm/guides/migrate-from-sdk.md | 2 +- metamask-connect/evm/quickstart/react-native.md | 2 +- metamask-connect/evm/quickstart/wagmi.md | 6 +++--- metamask-connect/evm/reference/provider-api.md | 2 +- metamask-connect/integration-options.md | 2 +- metamask-connect/multichain/quickstart/react-native.md | 2 +- metamask-connect/solana/quickstart/nodejs.md | 4 ++-- metamask-connect/supported-platforms.md | 2 +- metamask-connect/troubleshooting/index.md | 4 ++-- .../troubleshooting/metro-polyfill-issues.md | 10 +++++----- 11 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.cursor/rules/terminology.mdc b/.cursor/rules/terminology.mdc index 013da003e45..f541c028c58 100644 --- a/.cursor/rules/terminology.mdc +++ b/.cursor/rules/terminology.mdc @@ -22,6 +22,7 @@ listed on the right unless they appear in code, URLs, or direct quotations from | sign-in / sign-out (noun or adjective) | log-in, log-out, login, logout (as nouns/adj) | | onchain / offchain | on-chain, off-chain | | Wallet Standard, Wallet Adapter | wallet-standard, wallet-adapter (except in URLs) | +| Wagmi | wagmi (except in code, package names, imports, URLs, and file paths) | | MetaMask Agent Wallet | Agentic CLI, Agentic Wallet (except in code/URLs where `agentic` appears) | | Agent Wallet (short form) | agent wallet (lowercase product name) | | Guard Mode | guard mode (capitalize Mode) | diff --git a/metamask-connect/evm/guides/migrate-from-sdk.md b/metamask-connect/evm/guides/migrate-from-sdk.md index 50d00573a6f..59c47944dec 100644 --- a/metamask-connect/evm/guides/migrate-from-sdk.md +++ b/metamask-connect/evm/guides/migrate-from-sdk.md @@ -231,7 +231,7 @@ so read `.result` from the returned object to get the RPC response value. Browser-based setups (Vite, Webpack) work without polyfills. If you are migrating a React Native app and encounter errors referencing `Buffer`, `crypto`, or `stream`, see [React Native Metro polyfill issues](../../troubleshooting/metro-polyfill-issues.md). The -`Event is not defined` error only occurs when you also use wagmi, which dispatches DOM events. +`Event is not defined` error only occurs when you also use Wagmi, which dispatches DOM events. ::: ### 5. Update provider access diff --git a/metamask-connect/evm/quickstart/react-native.md b/metamask-connect/evm/quickstart/react-native.md index 020091067f2..9154dc584f8 100644 --- a/metamask-connect/evm/quickstart/react-native.md +++ b/metamask-connect/evm/quickstart/react-native.md @@ -143,7 +143,7 @@ if (typeof global.CustomEvent === 'undefined') { ``` :::note -The `Event` and `CustomEvent` polyfills above are only required if you also use wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. +The `Event` and `CustomEvent` polyfills above are only required if you also use Wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. ::: :::tip diff --git a/metamask-connect/evm/quickstart/wagmi.md b/metamask-connect/evm/quickstart/wagmi.md index 1792b2dd2a8..53ec5212017 100644 --- a/metamask-connect/evm/quickstart/wagmi.md +++ b/metamask-connect/evm/quickstart/wagmi.md @@ -27,7 +27,7 @@ Get started with MetaMask Connect EVM in a React and Wagmi dapp. [Download the quickstart template](#set-up-using-a-template) or [manually set up MetaMask Connect EVM](#set-up-manually) in an existing dapp. :::tip Migrating from `@metamask/sdk`? -If you are upgrading an existing wagmi project that used `@metamask/sdk`, see the +If you are upgrading an existing Wagmi project that used `@metamask/sdk`, see the [Wagmi connector migration reference](#migrate-from-metamasksdk) at the bottom of this page for a parameter mapping table. ::: @@ -323,9 +323,9 @@ If you previously used `@metamask/sdk` with Wagmi, the MetaMask connector now us npm install @metamask/connect-evm@^2.1.0 wagmi@^3.6.0 ``` -2. Update hook usage for wagmi v3: +2. Update hook usage for Wagmi v3: - | Old (wagmi v2) | New (wagmi v3) | Notes | + | Old (Wagmi v2) | New (Wagmi v3) | Notes | | --------------------------------- | -------------------------------------- | ------------------------------------------- | | `useAccount` | `useConnection` | Returns `address`, `isConnected`, `chainId` | | `useConnect` returns `connectors` | `useConnectors` hook | Connectors are a separate hook | diff --git a/metamask-connect/evm/reference/provider-api.md b/metamask-connect/evm/reference/provider-api.md index 7dae5233b20..5bf69f5bfde 100644 --- a/metamask-connect/evm/reference/provider-api.md +++ b/metamask-connect/evm/reference/provider-api.md @@ -349,7 +349,7 @@ returned by the MetaMask provider, and can help you identify their meaning. :::note Typed errors When you use the multichain client, the core (`@metamask/connect-multichain`) exports typed error -classes for `instanceof` checks: `RPCInvokeMethodErr` (wraps wallet `invokeMethod` errors—read the +classes for `instanceof` checks: `RPCInvokeMethodErr` (wraps wallet `invokeMethod` errors; read the wallet's original code from `err.rpcCode`), `RPCHttpErr`, `RPCReadonlyResponseErr`, and `RPCReadonlyRequestErr`. The EVM provider itself rejects with a standard EIP-1193 `ProviderRpcError` (use `err.code`). diff --git a/metamask-connect/integration-options.md b/metamask-connect/integration-options.md index 523e7cf39bc..1dd2bca968f 100644 --- a/metamask-connect/integration-options.md +++ b/metamask-connect/integration-options.md @@ -98,7 +98,7 @@ Choose **multi-ecosystem** (both single-ecosystem packages) if you want per-chai Yes. All three options share the same underlying transport and session infrastructure, so you can start with a single-ecosystem client and migrate to multichain later without changing your backend or connection logic. The migration involves updating your client initialization code and adopting scope-based RPC routing. -### Does MetaMask Connect work with wagmi, ethers.js, and viem? +### Does MetaMask Connect work with Wagmi, ethers.js, and viem? Yes. The EVM client (`@metamask/connect-evm`) provides an EIP-1193 compatible provider that works directly with viem's `custom` transport, ethers.js `BrowserProvider`, and web3.js `Web3` constructor. The Solana client provides a Wallet Standard compatible wallet that works with the Solana Wallet Adapter ecosystem. diff --git a/metamask-connect/multichain/quickstart/react-native.md b/metamask-connect/multichain/quickstart/react-native.md index bcacb482b8e..977e9679753 100644 --- a/metamask-connect/multichain/quickstart/react-native.md +++ b/metamask-connect/multichain/quickstart/react-native.md @@ -148,7 +148,7 @@ if (typeof global.CustomEvent === 'undefined') { ``` :::note -The `Event` and `CustomEvent` polyfills above are only required if you also use wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. +The `Event` and `CustomEvent` polyfills above are only required if you also use Wagmi, which dispatches DOM events. The `@metamask/connect-*` packages use `eventemitter3` internally and don't need them. ::: Create the empty module stub used by the Metro config: diff --git a/metamask-connect/solana/quickstart/nodejs.md b/metamask-connect/solana/quickstart/nodejs.md index 4182521538f..e4b37eaf0bd 100644 --- a/metamask-connect/solana/quickstart/nodejs.md +++ b/metamask-connect/solana/quickstart/nodejs.md @@ -151,8 +151,8 @@ solanaClient.core.on('wallet_sessionChanged', session => { :::note Devnet and testnet are supported only in the MetaMask browser extension (such as -[MetaMask Flask](https://metamask.io/flask/)). On mobile—including the QR code flow in this -quickstart—only Solana mainnet is supported. +[MetaMask Flask](https://metamask.io/flask/)). On mobile (including the QR code flow in this +quickstart), only Solana mainnet is supported. ::: ## Full example diff --git a/metamask-connect/supported-platforms.md b/metamask-connect/supported-platforms.md index bbac78a7c9a..c4a06c73e2d 100644 --- a/metamask-connect/supported-platforms.md +++ b/metamask-connect/supported-platforms.md @@ -79,7 +79,7 @@ Select a ✅ to jump to the relevant quickstart or guide. | Browser (vanilla JS/TS) | [✅](/metamask-connect/evm/quickstart/javascript) | [✅](/metamask-connect/solana/quickstart/javascript) | [✅](/metamask-connect/multichain/quickstart/javascript) | | React | [✅](/metamask-connect/evm/quickstart/javascript) | [✅](/metamask-connect/solana/guides/use-wallet-adapter) | [✅](/metamask-connect/multichain/quickstart/javascript) | | React Native | [✅](/metamask-connect/evm/quickstart/react-native) | [✅](/metamask-connect/solana) | [✅](/metamask-connect/multichain/quickstart/javascript) | -| wagmi | [✅](/metamask-connect/evm) | — | — | +| Wagmi | [✅](/metamask-connect/evm) | — | — | | Wallet Standard | — | [✅](/metamask-connect/solana/guides/use-wallet-adapter/) | — | | Node.js | ✅ | — | ✅ | diff --git a/metamask-connect/troubleshooting/index.md b/metamask-connect/troubleshooting/index.md index 8a040f226ea..1f921094871 100644 --- a/metamask-connect/troubleshooting/index.md +++ b/metamask-connect/troubleshooting/index.md @@ -28,7 +28,7 @@ The SDK handles its transport and crypto needs internally using browser-native A The React Native runtime lacks certain Web and Node.js APIs (`Buffer`, `crypto.getRandomValues`, `stream`, `window`), so polyfills and Metro configuration are required. The `Event` and `CustomEvent` globals aren't needed by the `@metamask/connect-*` packages (which use -`eventemitter3` internally); polyfill them only if you also use wagmi. +`eventemitter3` internally); polyfill them only if you also use Wagmi. See the [React Native Metro polyfill guide](metro-polyfill-issues.md) for step-by-step setup instructions. @@ -315,7 +315,7 @@ When any MetaMask Connect integration is misbehaving, ensure the following are t - Chain IDs are hex strings for EVM (`'0x1'`, not `1` or `'1'`). - In React Native dapps: - Polyfills are loaded: `react-native-get-random-values` is the first entry-file - import; `window` shim is present; `Event`/`CustomEvent` shims are present **only if using wagmi**; + import; `window` shim is present; `Event`/`CustomEvent` shims are present **only if using Wagmi**; `Buffer` is set as a safety net for peer dependencies. - `preferredOpenLink` is set for deeplinks to open MetaMask Mobile (see [Deeplinks not opening MetaMask app](metro-polyfill-issues.md#deeplinks-not-opening-metamask-app)). - Import order is correct: polyfills before SDK imports; `react-native-get-random-values` is the diff --git a/metamask-connect/troubleshooting/metro-polyfill-issues.md b/metamask-connect/troubleshooting/metro-polyfill-issues.md index 94aea1fc519..caa3f0903b6 100644 --- a/metamask-connect/troubleshooting/metro-polyfill-issues.md +++ b/metamask-connect/troubleshooting/metro-polyfill-issues.md @@ -29,7 +29,7 @@ import TabItem from "@theme/TabItem"; React Native uses the Metro bundler, which cannot resolve Node.js built-in modules. MetaMask Connect packages and their dependencies reference modules like `stream`, `crypto`, `buffer`, and `http`. Some code paths expect a browser-like `window` object, which React Native does not provide. -MetaMask Connect uses `eventemitter3` internally and does not require DOM `Event` or `CustomEvent` globals; if you use **wagmi**, you may need to polyfill those separately. +MetaMask Connect uses `eventemitter3` internally and does not require DOM `Event` or `CustomEvent` globals; if you use **Wagmi**, you may need to polyfill those separately. This guide walks through the required polyfills, Metro configuration, and related React Native setup (including deeplinks to MetaMask Mobile). @@ -174,9 +174,9 @@ if (typeof global !== 'undefined') { } ``` -#### Optional wagmi polyfills for Event and CustomEvent +#### Optional Wagmi polyfills for Event and CustomEvent -If you use **wagmi**, add the following to `polyfills.ts` after the `window` shim (React Native does not provide DOM `Event` or `CustomEvent`, which wagmi-related code may expect): +If you use **Wagmi**, add the following to `polyfills.ts` after the `window` shim (React Native does not provide DOM `Event` or `CustomEvent`, which Wagmi-related code may expect): ```typescript // Polyfill Event if missing @@ -294,9 +294,9 @@ Use the same `mobile.preferredOpenLink` pattern with [`createMultichainClient`]( ### `Event is not defined` or `CustomEvent is not defined` -**Cause**: React Native does not provide browser `Event` or `CustomEvent` classes. This typically appears when using **wagmi** (or another dependency that expects DOM events). MetaMask Connect uses `eventemitter3` internally and does not require these globals. +**Cause**: React Native does not provide browser `Event` or `CustomEvent` classes. This typically appears when using **Wagmi** (or another dependency that expects DOM events). MetaMask Connect uses `eventemitter3` internally and does not require these globals. -**Fix**: If you use wagmi, append the `Event` and `CustomEvent` polyfills from [Optional wagmi polyfills for Event and CustomEvent](#optional-wagmi-polyfills-for-event-and-customevent) to your `polyfills.ts` after the base `window` shim. +**Fix**: If you use Wagmi, append the `Event` and `CustomEvent` polyfills from [Optional Wagmi polyfills for Event and CustomEvent](#optional-wagmi-polyfills-for-event-and-customevent) to your `polyfills.ts` after the base `window` shim. ### Expo Go not working From 962328a22acfebf2f682faa33a542e0384168b79 Mon Sep 17 00:00:00 2001 From: Mohammad Shahbaz Alam Date: Mon, 15 Jun 2026 10:07:08 +0400 Subject: [PATCH 4/5] Clarify Solana network support notes Update Solana quickstart docs to clarify network support: state that Devnet and Testnet are supported only in the MetaMask browser extension and that on mobile (including QR flows) only Solana mainnet is supported. Remove the explicit reference and link to MetaMask Flask. Changes applied to nodejs.md and react-native.md. --- metamask-connect/solana/quickstart/nodejs.md | 5 ++--- metamask-connect/solana/quickstart/react-native.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/metamask-connect/solana/quickstart/nodejs.md b/metamask-connect/solana/quickstart/nodejs.md index e4b37eaf0bd..28dfa75d9f0 100644 --- a/metamask-connect/solana/quickstart/nodejs.md +++ b/metamask-connect/solana/quickstart/nodejs.md @@ -150,9 +150,8 @@ solanaClient.core.on('wallet_sessionChanged', session => { | Testnet | `solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z` | :::note -Devnet and testnet are supported only in the MetaMask browser extension (such as -[MetaMask Flask](https://metamask.io/flask/)). On mobile (including the QR code flow in this -quickstart), only Solana mainnet is supported. +Devnet and testnet are supported only in the MetaMask browser extension. On mobile (including the +QR code flow in this quickstart), only Solana mainnet is supported. ::: ## Full example diff --git a/metamask-connect/solana/quickstart/react-native.md b/metamask-connect/solana/quickstart/react-native.md index 023e4f3d2f7..2f84c3150e3 100644 --- a/metamask-connect/solana/quickstart/react-native.md +++ b/metamask-connect/solana/quickstart/react-native.md @@ -429,7 +429,7 @@ npx expo run:ios | Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | :::note -Devnet and testnet require [MetaMask Flask](https://metamask.io/flask/). Production MetaMask only supports Solana mainnet. +Devnet and testnet are supported only in the MetaMask browser extension. On mobile, only Solana mainnet is supported. ::: ## Next steps From 4a0281dd9e8fccd6865817a2b9404723afca9dab Mon Sep 17 00:00:00 2001 From: Mohammad Shahbaz Alam Date: Mon, 15 Jun 2026 10:32:05 +0400 Subject: [PATCH 5/5] Vale fixes --- .../solana/guides/send-transactions/batch.md | 6 +++--- metamask-connect/solana/reference/methods.md | 16 ++++++++-------- .../troubleshooting/metro-polyfill-issues.md | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/metamask-connect/solana/guides/send-transactions/batch.md b/metamask-connect/solana/guides/send-transactions/batch.md index 54de12118db..02cba047c02 100644 --- a/metamask-connect/solana/guides/send-transactions/batch.md +++ b/metamask-connect/solana/guides/send-transactions/batch.md @@ -1,7 +1,7 @@ --- title: 'Send Batch Solana Transactions - MetaMask Connect' sidebar_label: Send batch transactions -description: Sign and send multiple Solana transactions by passing several inputs to the variadic signAndSendTransaction Wallet Standard feature. +description: Sign and send multiple Solana transactions by passing several inputs to the signAndSendTransaction Wallet Standard feature. keywords: [ solana, @@ -17,13 +17,13 @@ keywords: # Send batch transactions The [`solana:signAndSendTransaction`](../../reference/methods.md#supported-wallet-standard-features) -Wallet Standard feature is variadic: you can pass multiple transaction inputs to a single call to +Wallet Standard feature accepts multiple inputs: you can pass several transactions to a single call to sign and send them, and it resolves to one result per transaction. This is useful for operations that span several transactions, such as initializing multiple accounts, batch token transfers, or multi-step program interactions. :::note -There is no separate `signAndSendAllTransactions` feature. Send a batch by passing several inputs to +No separate `signAndSendAllTransactions` feature exists. Send a batch by passing several inputs to `signAndSendTransaction`. ::: diff --git a/metamask-connect/solana/reference/methods.md b/metamask-connect/solana/reference/methods.md index 2e455afb779..9179cf21821 100644 --- a/metamask-connect/solana/reference/methods.md +++ b/metamask-connect/solana/reference/methods.md @@ -196,14 +196,14 @@ The wallet returned by [`getWallet`](#getwallet) implements the following [Wallet Standard](https://github.com/wallet-standard/wallet-standard) features. Access them via `wallet.features['']`. -| Feature | Description | -| ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| `standard:connect` | Connect to the wallet and receive the user's accounts. | -| `standard:disconnect` | Disconnect from the wallet. | -| `standard:events` | Subscribe to account and chain change events. | -| `solana:signMessage` | Sign an arbitrary message (returns a signature). | -| `solana:signTransaction` | Sign one or more transactions without broadcasting them (variadic). | -| `solana:signAndSendTransaction` | Sign one or more transactions and broadcast them to the network. Pass multiple inputs to send a batch (variadic). | +| Feature | Description | +| ------------------------------- | ------------------------------------------------------------------------------------------------------ | +| `standard:connect` | Connect to the wallet and receive the user's accounts. | +| `standard:disconnect` | Disconnect from the wallet. | +| `standard:events` | Subscribe to account and chain change events. | +| `solana:signMessage` | Sign an arbitrary message (returns a signature). | +| `solana:signTransaction` | Sign one or more transactions without broadcasting them. | +| `solana:signAndSendTransaction` | Sign one or more transactions and broadcast them to the network. Pass multiple inputs to send a batch. | ### Example diff --git a/metamask-connect/troubleshooting/metro-polyfill-issues.md b/metamask-connect/troubleshooting/metro-polyfill-issues.md index caa3f0903b6..842c2836681 100644 --- a/metamask-connect/troubleshooting/metro-polyfill-issues.md +++ b/metamask-connect/troubleshooting/metro-polyfill-issues.md @@ -29,7 +29,7 @@ import TabItem from "@theme/TabItem"; React Native uses the Metro bundler, which cannot resolve Node.js built-in modules. MetaMask Connect packages and their dependencies reference modules like `stream`, `crypto`, `buffer`, and `http`. Some code paths expect a browser-like `window` object, which React Native does not provide. -MetaMask Connect uses `eventemitter3` internally and does not require DOM `Event` or `CustomEvent` globals; if you use **Wagmi**, you may need to polyfill those separately. +MetaMask Connect uses `eventemitter3` internally and does not require DOM `Event` or `CustomEvent` globals; if you use **Wagmi**, you may need to polyfill those. This guide walks through the required polyfills, Metro configuration, and related React Native setup (including deeplinks to MetaMask Mobile).