Skip to content

Migrate to @metamask/connect-evm#2390

Merged
0xFirekeeper merged 4 commits into
developfrom
firekeeper/metamask-connect
May 25, 2026
Merged

Migrate to @metamask/connect-evm#2390
0xFirekeeper merged 4 commits into
developfrom
firekeeper/metamask-connect

Conversation

@0xFirekeeper
Copy link
Copy Markdown
Member

@0xFirekeeper 0xFirekeeper commented May 4, 2026

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

    • Rebranded to MetaMask Connect EVM and prioritized when a MetaMask browser wallet is present.
    • Added optional config: headless, showInstallModal, infuraAPIKey, readonlyRPCMap, openDeeplink, useDeeplink; dappMetadata is now optional and supports iconUrl.
    • Legacy MetaMask options remain accepted for backwards compatibility.
  • Documentation

    • Updated README and usage example to show Connect EVM integration and option mappings.
  • Chores

    • Package version bumped to 2.3.0.

Review Change Stack

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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Walkthrough

Replaces legacy @metamask/sdk with @metamask/connect-evm, adds cached dynamic imports and exported MetaMaskSDKOptions, maps legacy options to Connect EVM fields (including RPC merging and dapp icon handling), changes disconnect to client.disconnect(), bumps package version, and updates README/usage guidance.

Changes

MetaMask Connect EVM Migration

Layer / File(s) Summary
Public types & dynamic import surface
packages/metamask/src/index.ts
Introduce FALLBACK_MAINNET_RPC; export MetaMaskSDKOptions; declare Connect EVM import/client types; implement cached dynamic loading of @metamask/connect-evm with ESM/CJS shape handling and error cache-reset.
Client creation, caching & getInterface
packages/metamask/src/index.ts
getInterface reuses cached Connect EVM client/provider or loads imports, maps legacy options, creates a new client, attaches disconnect shim, and returns provider + instance.
Provider disconnect shim
packages/metamask/src/index.ts
attachDisconnectShim() makes provider.disconnect() call client.disconnect() instead of terminating the legacy SDK.
Chain, RPC & input normalization helpers
packages/metamask/src/index.ts
Add chainsToRpcMap, toHexChainId, isHttpUrl, and normalizeReadonlyRPCMap to turn web3-onboard chains and readonlyRPCMap into hex-ID → RPC maps and validate icon URLs.
Legacy-to-ConnectEVM option mapping
packages/metamask/src/index.ts
mapLegacyOptions() merges Infura RPCs (when provided), chain RPCs, and readonlyRPCMap into api.supportedNetworks (fallback to hardcoded mainnet); conditionally sets dapp.base64Icon/dapp.iconUrl; maps headless/extensionOnlyui, openDeeplink/useDeeplinkmobile; defaults showInstallModal to false.
Package Metadata
packages/metamask/package.json
Version bumped to 2.3.0; description updated to reference MetaMask Connect EVM; dependency swapped from @metamask/sdk@metamask/connect-evm@^1.3.1.
Docs / Usage
packages/metamask/README.md
README updated to reference Connect EVM as the successor SDK, document optional/new MetaMaskSDKOptions fields and mappings, refine extensionOnly semantics, reorder injected-wallets guidance, and reformat the usage example.
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
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description lacks a completed checklist as required by the template; it is entirely missing the implementation and documentation verification steps. Complete the required checklist by checking off verification items (version bump, local testing, yarn check-all, Circle CI, documentation updates) and Docs Checklist items relevant to this SDK wallet module update.
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Migrate to @metamask/connect-evm' clearly and concisely describes the main change in the PR—replacing the legacy @metamask/sdk with the new @metamask/connect-evm client.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch firekeeper/metamask-connect

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between e3b8623 and 70c2d0e.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • packages/metamask/README.md
  • packages/metamask/package.json
  • packages/metamask/src/index.ts

Comment thread packages/metamask/src/index.ts Outdated
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.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 70c2d0e and 734c77e.

📒 Files selected for processing (3)
  • packages/metamask/README.md
  • packages/metamask/package.json
  • packages/metamask/src/index.ts

Comment thread packages/metamask/README.md
Comment thread packages/metamask/README.md
Comment thread packages/metamask/src/index.ts
Comment thread packages/metamask/src/index.ts
@wenfix
Copy link
Copy Markdown

wenfix commented May 19, 2026

Hey, great work on the migration to our new SDK. I've pulled, tested it and found a couple issues:

  1. Can you bump @metamask/connect-evm to 1.3.1 and regenerate the relevant yarn.lock files?

    1.3.1 includes a provider fix that Web3-Onboard needs for account requests. Web3-Onboard calls:

    provider.request({ method: 'eth_requestAccounts' })

    and expects the standard EIP-1193 response shape, which is an array of connected accounts. With 1.3.1, intercepted account requests return the expected method-specific values: eth_requestAccounts returns the accounts array, and eth_coinbase returns the selected account.

  2. I think the QR rendering issue is coming from the icon metadata being passed into Connect EVM.

    The current implementation appears to take Web3-Onboard's appMetadata.icon, base64 encode it, and pass it as dapp.base64Icon. In Web3-Onboard, appMetadata.icon can be a raw SVG string, and the demo app uses a fairly large inline SVG there.

    Connect EVM includes dapp metadata in the mobile connection request, which then gets compressed into the QR/deeplink payload. When the inline SVG is included as base64Icon, the payload gets too large and QR generation can fail with Capacity overflow.

    I would avoid automatically mapping appMetadata.icon to base64Icon. Safer options would be:

    • use an explicit options.dappMetadata.iconUrl when provided
    • only pass options.dappMetadata.base64Icon if the integrator explicitly provides it
    • if no explicit Connect EVM icon metadata is provided, omit the icon and let Connect fall back to favicon/default behavior
    • if appMetadata.icon is already an HTTP(S) URL, forwarding it as iconUrl seems reasonable, but raw SVG strings should not be inlined into the QR payload

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.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Clear the cached client on disconnect.

provider.disconnect() tears down the session but leaves the module-level client populated. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 734c77e and 65c7c4b.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • packages/metamask/README.md
  • packages/metamask/package.json
  • packages/metamask/src/index.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/metamask/package.json

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 65c7c4b and eb175f4.

📒 Files selected for processing (1)
  • packages/metamask/package.json

Comment thread packages/metamask/package.json
@0xFirekeeper 0xFirekeeper merged commit f3eadfb into develop May 25, 2026
4 checks passed
@0xFirekeeper 0xFirekeeper deleted the firekeeper/metamask-connect branch May 25, 2026 10:01
0xFirekeeper added a commit that referenced this pull request May 25, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants