Migrate to @metamask/connect-evm#2390
Conversation
Swap out the legacy @metamask/sdk for the new @metamask/connect-evm client and update package metadata (version bump to 2.3.0). Code changes load connect-evm (handling ESM/CJS shapes), reuse a single client instance, attach a disconnect shim to the provider, and map legacy MetaMask SDK options to the new connect-evm option shape (including Infura/custom RPC merging via getInfuraRpcUrls). README updated to reflect the Connect EVM integration and backwards compatibility notes; package.json dependency updated accordingly.
WalkthroughReplaces legacy ChangesMetaMask Connect EVM Migration
sequenceDiagram
participant Dapp as Dapp (web3-onboard)
participant Module as metamask module
participant Importer as `@metamask/connect-evm` (dynamic)
participant Client as ConnectEVM client
participant Infura as Infura/RPC
Dapp->>Module: init metamask({ options })
Module->>Importer: loadImports() (dynamic)
Importer-->>Module: createEVMClient, getInfuraRpcUrls
Module->>Module: mapLegacyOptions(...) (merge Infura, chains, readonlyRPCMap)
Module->>Client: createEVMClient(mappedOptions)
Client-->>Module: client instance + provider
Module->>Client: attachDisconnectShim(provider.disconnect -> client.disconnect)
Module->>Infura: (if needed) resolve RPC URLs via getInfuraRpcUrls
Module-->>Dapp: return provider + instance
🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/metamask/src/index.ts`:
- Around line 72-74: The cached importPromise created via importPromise =
importPromise ?? loadImports().catch(error => { throw error }) can become
permanently rejected and poison future getInterface calls; update the catch
handler on loadImports() so that on rejection it clears importPromise (e.g., set
importPromise = undefined) before rethrowing the error, ensuring subsequent
calls to getInterface will retry loadImports().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bbd073ca-0a0b-4209-8b25-f09792507d9d
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
packages/metamask/README.mdpackages/metamask/package.jsonpackages/metamask/src/index.ts
Bump @web3-onboard/metamask to v2.4.0 and enhance SDK initialization. - Add a fallback Mainnet RPC and ensure api.supportedNetworks is always non-empty by deriving RPCs in priority order: Infura, readonlyRPCMap, web3-onboard chains, then public fallback. - Accept and normalize web3-onboard chains (toHexChainId + chainsToRpcMap) and thread them into getInterface/mapLegacyOptions so the client can use configured chains. - Improve dynamic import caching with retry semantics to avoid permanently failing on transient import errors. - Add showInstallModal option (defaults to false) and update legacy options handling (extensionOnly only maps to preferExtension when true; headless preserved). - Minor README formatting and example tweaks.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/metamask/README.md`:
- Around line 37-47: Add documentation for the missing showInstallModal option
to the options interface in the README: declare the property showInstallModal?:
boolean and document it as mapped to mobile.showInstallModal (or the equivalent
runtime option name) so the README matches the implementation that supports
showInstallModal; update the options block where headless, infuraAPIKey,
readonlyRPCMap, openDeeplink, and useDeeplink are documented to include this new
entry.
- Around line 57-60: The README example sets extensionOnly: false which is a
no-op because the code only maps extensionOnly when true; either remove
extensionOnly from the example or set it to extensionOnly: true to demonstrate
the behavior — update the metamaskSDK(...) call (the
metamaskSDKWallet/options/dappMetadata block) to reflect one of these changes so
the example matches actual mapping logic.
In `@packages/metamask/src/index.ts`:
- Around line 57-62: The types use `typeof` on type-only imports
(CreateEVMClientFn, GetInfuraRpcUrlsFn) which is invalid; update the type
aliases so they reference the imported types directly (e.g., use
CreateEVMClientFn and GetInfuraRpcUrlsFn rather than typeof
CreateEVMClientFn/GetInfuraRpcUrlsFn) and adjust ConnectEvmImports and
EvmClientOptions to use those direct type names; ensure any other occurrences
(e.g., the similar case around line 199) are changed the same way so all
type-only imports are not wrapped with typeof.
- Around line 217-221: supportedNetworks currently merges readonlyRPCMap raw
while fromChains uses chainsToRpcMap/toHexChainId to normalize chain IDs to hex;
normalize readonlyRPCMap keys the same way before merging so
api.supportedNetworks only contains hex chain IDs. Update the merge to transform
options.readonlyRPCMap (if present) by mapping each key through toHexChainId
(and skip or log invalid conversions) producing a normalizedReadonlyRPCMap, then
use {...fromInfura, ...fromChains, ...normalizedReadonlyRPCMap} when building
supportedNetworks; reference supportedNetworks, readonlyRPCMap, chainsToRpcMap,
and toHexChainId to locate the code to change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8de51b8e-b670-45a0-a206-8b15a2d34cf8
📒 Files selected for processing (3)
packages/metamask/README.mdpackages/metamask/package.jsonpackages/metamask/src/index.ts
|
Hey, great work on the migration to our new SDK. I've pulled, tested it and found a couple issues:
Let me know if you have questions or need further help! 🙏 |
Handle dapp icon metadata more safely and normalize readonly RPC keys. Forward http(s) icon URLs to @metamask/connect-evm instead of always base64-encoding app icons (only pass base64Icon when explicitly provided) to avoid overflowing QR/deeplink payloads. Added isHttpUrl and icon selection logic so raw SVG strings are dropped and a fallback URL may be used. Introduced normalizeReadonlyRPCMap to convert readonlyRPCMap keys to hex and ignore invalid IDs, and merged the normalized readonly RPCs after chain-derived RPCs (priority: Infura → chains → readonlyRPCMap → fallback). Documented showInstallModal and clarified extensionOnly behavior in the README, and bumped @metamask/connect-evm to ^1.3.1 in package.json.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/metamask/src/index.ts (1)
118-125:⚠️ Potential issue | 🟠 Major | ⚡ Quick winClear the cached client on disconnect.
provider.disconnect()tears down the session but leaves the module-levelclientpopulated. On the next connect attempt, Line 118 takes the reuse path and returns that disconnected provider instead of creating a fresh Connect EVM client.Suggested fix
function attachDisconnectShim(provider: unknown): void { // Web3-Onboard expects a `disconnect` method on the provider so it can // tear down the wallet session when the user disconnects from the dapp. // The MetaMask Connect EVM client exposes this via `client.disconnect()`. ;(provider as { disconnect?: () => void }).disconnect = () => { - void client?.disconnect() + const activeClient = client + client = null + void activeClient?.disconnect() } }Also applies to: 165-166
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/metamask/src/index.ts` around lines 118 - 125, The cached module-level client is not cleared when a provider disconnects, so subsequent calls reuse a disconnected provider; update the logic in the connect/reuse path that checks client (the block using client, client.getProvider(), attachDisconnectShim) to clear the module-level client when the provider's disconnect event is observed or when provider.disconnect() is invoked — i.e., attach a disconnect handler (or enhance attachDisconnectShim) to call something like client = undefined (clear the cached client and any related state) so future connect attempts create a fresh Connect EVM client; apply the same change to the other reuse-return site that returns { provider: existingProvider, instance: client } as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@packages/metamask/src/index.ts`:
- Around line 118-125: The cached module-level client is not cleared when a
provider disconnects, so subsequent calls reuse a disconnected provider; update
the logic in the connect/reuse path that checks client (the block using client,
client.getProvider(), attachDisconnectShim) to clear the module-level client
when the provider's disconnect event is observed or when provider.disconnect()
is invoked — i.e., attach a disconnect handler (or enhance attachDisconnectShim)
to call something like client = undefined (clear the cached client and any
related state) so future connect attempts create a fresh Connect EVM client;
apply the same change to the other reuse-return site that returns { provider:
existingProvider, instance: client } as well.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 00ab20ab-ef56-4db8-951a-985313d23b55
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (3)
packages/metamask/README.mdpackages/metamask/package.jsonpackages/metamask/src/index.ts
✅ Files skipped from review due to trivial changes (1)
- packages/metamask/package.json
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/metamask/package.json`:
- Line 3: The package.json currently downgrades "version" from 2.4.0 to 2.3.0;
update the "version" field in packages/metamask/package.json to a semver greater
than the published baseline (e.g., "2.4.1" or "2.5.0") to avoid a
rollback—change the "version" key value accordingly and ensure it follows your
release policy.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0b86f52d-ec54-48f0-9d77-425a2fbe2974
📒 Files selected for processing (1)
packages/metamask/package.json
* Setting up GitHub CI for packages * Pin github ci version * update node version for all packages (#2367) * update node version for all packages * update * chore: optimize onekey logo (#2369) * fix: revert @web3-onboard/para in docs to 1.0.0 (#2372) * fix: revert @web3-onboard/para in docs to 1.0.0 * add missing thirdweb icon * Chore: update git pages action (#2375) * fix: revert @web3-onboard/para in docs to 1.0.0 * chore: update git pages * remove auto trigger * rename blocknative URLs to thirdweb * chore: git action to push to main + docs (#2378) * chore: git action to push to main + docs * lint * chore: fix footer size/colors (#2379) * chore: fix footer size/colors * remove push to prod action * chore: remove blocknative links from header (#2381) * chore: upgrade WalletConnect dependencies (#2385) * chore: upgrade WalletConnect dependencies * chore: upgrade version * bump version --------- Co-authored-by: Joaquim Verges <joaquim.verges@gmail.com> * Migrate to @metamask/connect-evm (#2390) * Migrate to @metamask/connect-evm Swap out the legacy @metamask/sdk for the new @metamask/connect-evm client and update package metadata (version bump to 2.3.0). Code changes load connect-evm (handling ESM/CJS shapes), reuse a single client instance, attach a disconnect shim to the provider, and map legacy MetaMask SDK options to the new connect-evm option shape (including Infura/custom RPC merging via getInfuraRpcUrls). README updated to reflect the Connect EVM integration and backwards compatibility notes; package.json dependency updated accordingly. * metamask: add chain RPC fallback & options Bump @web3-onboard/metamask to v2.4.0 and enhance SDK initialization. - Add a fallback Mainnet RPC and ensure api.supportedNetworks is always non-empty by deriving RPCs in priority order: Infura, readonlyRPCMap, web3-onboard chains, then public fallback. - Accept and normalize web3-onboard chains (toHexChainId + chainsToRpcMap) and thread them into getInterface/mapLegacyOptions so the client can use configured chains. - Improve dynamic import caching with retry semantics to avoid permanently failing on transient import errors. - Add showInstallModal option (defaults to false) and update legacy options handling (extensionOnly only maps to preferExtension when true; headless preserved). - Minor README formatting and example tweaks. * metamask: forward icon URL & normalize RPC keys Handle dapp icon metadata more safely and normalize readonly RPC keys. Forward http(s) icon URLs to @metamask/connect-evm instead of always base64-encoding app icons (only pass base64Icon when explicitly provided) to avoid overflowing QR/deeplink payloads. Added isHttpUrl and icon selection logic so raw SVG strings are dropped and a fallback URL may be used. Introduced normalizeReadonlyRPCMap to convert readonlyRPCMap keys to hex and ignore invalid IDs, and merged the normalized readonly RPCs after chain-derived RPCs (priority: Infura → chains → readonlyRPCMap → fallback). Documented showInstallModal and clarified extensionOnly behavior in the README, and bumped @metamask/connect-evm to ^1.3.1 in package.json. * ver --------- Co-authored-by: Jake Loo <2171134+jakeloo@users.noreply.github.com> Co-authored-by: Joaquim Verges <joaquim.verges@gmail.com> Co-authored-by: ByteZhang <ByteZhang@protonmail.com> Co-authored-by: Phillip Ho <arcoraven@gmail.com> Co-authored-by: Derek <alexanderderekrein@gmail.com>
Swap out the legacy @metamask/sdk for the new @metamask/connect-evm client and update package metadata (version bump to 2.3.0). Code changes load connect-evm (handling ESM/CJS shapes), reuse a single client instance, attach a disconnect shim to the provider, and map legacy MetaMask SDK options to the new connect-evm option shape (including Infura/custom RPC merging via getInfuraRpcUrls). README updated to reflect the Connect EVM integration and backwards compatibility notes; package.json dependency updated accordingly.
Summary by CodeRabbit
New Features
Documentation
Chores