feat(wallet): replace metamaskSDK with @metamask/connect-evm + mobile enablement#7236
feat(wallet): replace metamaskSDK with @metamask/connect-evm + mobile enablement#7236adaOctopus wants to merge 6 commits intocowprotocol:developfrom
Conversation
|
@adaOctopus is attempting to deploy a commit to the cow-dev Team on Vercel. A member of the Team first needs to authorize it. |
|
All contributors have signed the CLA ✍️ ✅ |
WalkthroughReplaces the MetaMask SDK integration with a MetaMask Connect (connect-evm) implementation across connector, UI, and exports; adds a new MetaMaskConnect connector and option; removes the legacy MetaMask SDK connector and option; updates detection logic, wagmi config, and package dependency. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as UI (MetaMaskConnectOption)
participant Conn as Connection (metaMaskConnectConnection)
participant Connector as MetaMaskConnect
participant EVM as `@metamask/connect-evm` (EVM Client)
participant MM as MetaMask Wallet
User->>UI: click MetaMask tile
UI->>Conn: tryActivation(connector)
Conn->>Connector: activate()
Connector->>EVM: lazy-load & createEVMClient(dappMetadata, readonlyRPCMap)
EVM->>MM: init/connect (deeplink or popup)
MM-->>EVM: provider / user approves
EVM-->>Connector: { accounts, chainId }
Connector->>Conn: update accounts/chainId (activation success)
Connector->>Connector: bind provider events (accountsChanged, chainChanged, disconnect)
Conn-->>UI: mark active
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
libs/wallet/src/web3-react/connection/metaMaskConnect.tsx (1)
19-22: Avoid hardcoding the dapp URL in connector metadata.Using a fixed origin here can desync metadata in non-production hosts. Prefer the same runtime-origin fallback pattern used in the wagmi config.
As per coding guidelines: "Use shared config/enums instead of hardcoding environment-specific lists/toggles".Suggested patch
dappMetadata: { name: 'CoW Swap', - url: 'https://swap.cow.fi', + url: typeof window === 'undefined' ? 'https://swap.cow.fi' : window.location.origin, },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@libs/wallet/src/web3-react/connection/metaMaskConnect.tsx` around lines 19 - 22, The dappMetadata.url is hardcoded ("https://swap.cow.fi"); update the connector setup (where dappMetadata is defined in metaMaskConnect) to use the runtime-origin fallback pattern instead of a fixed URL — e.g., derive the URL from window.location.origin (or the same helper/constant used in your wagmi config) so non-production hosts inherit their actual origin; replace the hardcoded string in dappMetadata with that runtime-derived value.libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts (1)
261-263: Remove unnecessary catch-rethrow block.The
catch (error) { throw error }pattern adds no value—it catches and immediately rethrows without any error transformation or logging. Remove the try-catch wrapper or add meaningful error handling.Proposed fix
- try { - await this.client.switchChain({ - chainId: chainIdHex, - chainConfiguration: - desiredChain !== undefined - ? { - chainName: desiredChain.chainName, - nativeCurrency: desiredChain.nativeCurrency, - rpcUrls: desiredChain.rpcUrls, - blockExplorerUrls: desiredChain.blockExplorerUrls, - } - : undefined, - }) - } catch (error) { - throw error - } + await this.client.switchChain({ + chainId: chainIdHex, + chainConfiguration: + desiredChain !== undefined + ? { + chainName: desiredChain.chainName, + nativeCurrency: desiredChain.nativeCurrency, + rpcUrls: desiredChain.rpcUrls, + blockExplorerUrls: desiredChain.blockExplorerUrls, + } + : undefined, + })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts` around lines 261 - 263, There is an unnecessary catch-and-rethrow block that wraps an async operation (the pattern `catch (error) { throw error }`); remove the try/catch wrapper around that operation (or replace it with meaningful handling such as logging via processLogger or wrapping with a custom Error) so the function (in the metaMaskConnect connector where the `catch (error) { throw error }` appears) relies on natural propagation or emits helpful context; update any tests/callers if they relied on the previous try/catch behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@libs/wallet/src/api/hooks.ts`:
- Around line 173-177: Replace the hardcoded 'metaMaskSDK' string by relying on
the upstream connector symbol: import the MetaMask connector (e.g.,
MetaMaskConnector) or use the connector's reported name instead of a literal;
then compute isMetaMaskConnectorId by checking the connector instance/type
(e.g., connector instanceof MetaMaskConnector or connector.id ===
MetaMaskConnector.id or connector.name === 'MetaMask') and keep
isMetamaskConnection and isInjectedConnection using that variable and
ConnectorType.INJECTED; update the import and the isMetaMaskConnectorId
assignment so we no longer depend on the 'metaMaskSDK' literal.
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts`:
- Around line 88-91: The dappMetadata fallback sets the name to 'wagmi'
incorrectly; update the default dapp name in the dappMetadata object (the code
that computes options?.dappMetadata ?? { url: defaultUrl, name: defaultUrl !==
'' ? undefined : 'wagmi' }) to use 'CoW Swap' instead of 'wagmi' so the
connector's dapp name falls back to "CoW Swap" when defaultUrl is empty.
- Around line 166-180: The connectEagerly method starts an activation with const
cancelActivation = this.actions.startActivation() but the catch block only calls
this.actions.resetState(), leaving the activation pending; update the catch (or
use a finally) to call cancelActivation() before resetting state (i.e., invoke
cancelActivation() in the catch/finally of connectEagerly so the activation
started by this.actions.startActivation() is always cancelled, then call
this.actions.resetState()).
- Around line 115-128: The call to createEVMClient includes an unsupported
mobile.useDeeplink option that is misleading; remove the entire mobile block
(the object setting useDeeplink) from the createEVMClient invocation in index.ts
so only the documented keys (dapp, api, eventHandlers) are passed, keeping the
dapp metadata assembly (this.options.dappMetadata.name/url/iconUrl) and the api
supportedNetworks code unchanged.
---
Nitpick comments:
In `@libs/wallet/src/web3-react/connection/metaMaskConnect.tsx`:
- Around line 19-22: The dappMetadata.url is hardcoded ("https://swap.cow.fi");
update the connector setup (where dappMetadata is defined in metaMaskConnect) to
use the runtime-origin fallback pattern instead of a fixed URL — e.g., derive
the URL from window.location.origin (or the same helper/constant used in your
wagmi config) so non-production hosts inherit their actual origin; replace the
hardcoded string in dappMetadata with that runtime-derived value.
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts`:
- Around line 261-263: There is an unnecessary catch-and-rethrow block that
wraps an async operation (the pattern `catch (error) { throw error }`); remove
the try/catch wrapper around that operation (or replace it with meaningful
handling such as logging via processLogger or wrapping with a custom Error) so
the function (in the metaMaskConnect connector where the `catch (error) { throw
error }` appears) relies on natural propagation or emits helpful context; update
any tests/callers if they relied on the previous try/catch behavior.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: d7093e6e-dfd9-4e17-a41d-c2a269b94f01
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (12)
apps/cowswap-frontend/src/modules/wallet/containers/ConnectWalletOptions.tsxlibs/wallet/package.jsonlibs/wallet/src/api/hooks.tslibs/wallet/src/index.tslibs/wallet/src/wagmi/config.tslibs/wallet/src/web3-react/connection/metaMaskConnect.tsxlibs/wallet/src/web3-react/connection/metaMaskConnectOption.tsxlibs/wallet/src/web3-react/connection/metaMaskSdk.tsxlibs/wallet/src/web3-react/connectors/metaMaskConnect/README.mdlibs/wallet/src/web3-react/connectors/metaMaskConnect/index.tslibs/wallet/src/web3-react/connectors/metaMaskSdk/index.tslibs/wallet/src/web3-react/utils/getWeb3ReactConnection.ts
💤 Files with no reviewable changes (2)
- libs/wallet/src/web3-react/connection/metaMaskSdk.tsx
- libs/wallet/src/web3-react/connectors/metaMaskSdk/index.ts
Made-with: Cursor
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
I have read the CLA Document and I hereby sign the CLA |
…back + Cow Swap fallback
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts`:
- Around line 137-148: The disconnect listener attached in
provider.on('disconnect') can reject because the fallback probe
(this.provider.request({ method: 'eth_accounts' })) may fail; modify the async
listener (the anonymous function passed to provider.on) to wrap the eth_accounts
probe in a try/catch so probe failures are swallowed and execution falls through
to the teardown logic: call getOriginalRpcError(error) as before, attempt the
accounts probe inside try { const accounts = await this.provider.request(...) }
catch { /* treat as no accounts; continue */ }, keep the existing short-circuit
return when accounts.length > 0, and ensure this.actions.resetState() and
this.onError?.(error) always run on real disconnects.
- Around line 109-163: The isomorphicInitialize() path currently does "if
(this.eagerConnection) return" which returns undefined instead of the shared
promise and never clears the memo on errors; change that to return
this.eagerConnection so callers await the in-flight init, and wrap the
import(...).then(...) chain with a .catch(err => { this.eagerConnection =
undefined; throw err }) so a transient failure clears this.eagerConnection;
update the block that assigns this.eagerConnection (the Promise that imports
'@metamask/connect-evm' and calls createEVMClient/getProvider and provider.on
handlers) to return the Promise and ensure rejections reset
this.eagerConnection.
- Around line 33-40: Update the MetaMaskConnectOptions.readonlyRPCMap type to
require hex-prefixed chain IDs (use Record<`0x${string}`, string>) and remove
any misleading runtime casts; then add/ensure validation at the call site that
builds readonlyRPCMap (the place currently casting keys to hex) so only
hex-prefixed keys are passed into the connector. Refer to the
MetaMaskConnectOptions type and the readonlyRPCMap usage/cast in the connector
to locate the changes and ensure the type and runtime validation are consistent.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 92b213a1-b99c-4f57-aebe-2bb97046546c
📒 Files selected for processing (3)
libs/wallet/src/api/hooks.tslibs/wallet/src/api/types.tslibs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts
| type MetaMaskConnectOptions = { | ||
| dappMetadata: { | ||
| name?: string | ||
| url?: string | ||
| iconUrl?: string | ||
| } | ||
| readonlyRPCMap?: Record<string, string> | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd -type f -name "*.ts" -path "*metaMaskConnect*"Repository: cowprotocol/cowswap
Length of output: 233
🏁 Script executed:
fd -type f "metaMaskConnect" -o -path "*web3-react*" | grep -i metamaskRepository: cowprotocol/cowswap
Length of output: 233
🏁 Script executed:
ls -la libs/wallet/src/web3-react/connectors/metaMaskConnect/Repository: cowprotocol/cowswap
Length of output: 291
🏁 Script executed:
rg "metaMaskConnect" --type ts --filesRepository: cowprotocol/cowswap
Length of output: 118
🏁 Script executed:
git ls-files | grep -i metamaskRepository: cowprotocol/cowswap
Length of output: 451
🏁 Script executed:
git ls-files "libs/wallet/*" | head -30Repository: cowprotocol/cowswap
Length of output: 1236
🏁 Script executed:
find . -name "index.ts" -type f | xargs grep -l "MetaMaskConnectOptions" 2>/dev/nullRepository: cowprotocol/cowswap
Length of output: 127
🏁 Script executed:
rg "MetaMaskConnectOptions" --type ts -lRepository: cowprotocol/cowswap
Length of output: 125
🏁 Script executed:
rg "readonlyRPCMap" --type ts -lRepository: cowprotocol/cowswap
Length of output: 183
🏁 Script executed:
rg "supportedNetworks" --type ts -B 2 -A 2Repository: cowprotocol/cowswap
Length of output: 15274
🏁 Script executed:
find . -type f -name "*.ts" | xargs grep -l "supportedNetworks" 2>/dev/null | head -5Repository: cowprotocol/cowswap
Length of output: 284
🏁 Script executed:
rg "0x.*string" --type ts | grep supportedNetworks | head -5Repository: cowprotocol/cowswap
Length of output: 226
🏁 Script executed:
rg "supportedNetworks.*readonlyRPCMap" --type ts -A 5 -B 5Repository: cowprotocol/cowswap
Length of output: 1316
🏁 Script executed:
rg "RPC_URLS" --type ts -lRepository: cowprotocol/cowswap
Length of output: 599
🏁 Script executed:
git ls-files | grep -E "\.ts$" | head -20Repository: cowprotocol/cowswap
Length of output: 793
🏁 Script executed:
git log --oneline -1 -- "libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts"Repository: cowprotocol/cowswap
Length of output: 166
🏁 Script executed:
cat libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts 2>/dev/null | head -150 || echo "File not found; listing repo structure:"Repository: cowprotocol/cowswap
Length of output: 5339
🏁 Script executed:
find . -maxdepth 3 -type d -name wallet 2>/dev/nullRepository: cowprotocol/cowswap
Length of output: 76
🏁 Script executed:
find . -type d -name connectors 2>/dev/null | head -5Repository: cowprotocol/cowswap
Length of output: 102
🏁 Script executed:
find . -type f -name "index.ts" 2>/dev/null | wc -lRepository: cowprotocol/cowswap
Length of output: 66
🏁 Script executed:
rg "readonlyRPCMap|MetaMaskConnectOptions" --type ts --max-count 20Repository: cowprotocol/cowswap
Length of output: 740
🏁 Script executed:
pwdRepository: cowprotocol/cowswap
Length of output: 81
🏁 Script executed:
rg "chainId.*toString.*16|0x.*Number.*toString" --type ts | head -10Repository: cowprotocol/cowswap
Length of output: 999
🏁 Script executed:
rg "SupportedChainId" --type ts | grep Record | head -10Repository: cowprotocol/cowswap
Length of output: 1574
🏁 Script executed:
rg "getAddressKey|chainToHex|toHex" --type ts -l | head -10Repository: cowprotocol/cowswap
Length of output: 599
🏁 Script executed:
rg "supportedNetworks" --type ts -B 5 -A 2 | head -50Repository: cowprotocol/cowswap
Length of output: 3993
🏁 Script executed:
rg "0x[0-9a-f]+.*string" --type ts | head -10Repository: cowprotocol/cowswap
Length of output: 378
🏁 Script executed:
rg "as Record.*0x" --type tsRepository: cowprotocol/cowswap
Length of output: 226
🏁 Script executed:
git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -i metamaskRepository: cowprotocol/cowswap
Length of output: 45
🏁 Script executed:
git log --oneline -5 2>/dev/null || echo "Not a git repo or git unavailable"Repository: cowprotocol/cowswap
Length of output: 166
🏁 Script executed:
cat -n libs/wallet/src/web3-react/connection/metaMaskConnect.tsx | head -50Repository: cowprotocol/cowswap
Length of output: 1437
🏁 Script executed:
rg "RPC_URLS" --type ts -l | head -10Repository: cowprotocol/cowswap
Length of output: 565
🏁 Script executed:
rg "export.*RPC_URLS" --type ts -B 2 -A 5Repository: cowprotocol/cowswap
Length of output: 696
🏁 Script executed:
rg "RPC_URLS\[" --type ts -B 1 -A 1Repository: cowprotocol/cowswap
Length of output: 1986
🏁 Script executed:
rg "RPC_URLS.*=" --type ts | head -5Repository: cowprotocol/cowswap
Length of output: 353
🏁 Script executed:
rg "RPC_URLS" --type ts | grep "Record\|Map\|{" | head -10Repository: cowprotocol/cowswap
Length of output: 1172
🏁 Script executed:
cat libs/wallet/src/web3-react/connection/metaMaskConnect.tsxRepository: cowprotocol/cowswap
Length of output: 1192
🏁 Script executed:
rg "const metaMaskConnectInitializedAtom|export.*metaMaskConnect" --type ts -A 10 libs/wallet/src/web3-react/connection/Repository: cowprotocol/cowswap
Length of output: 506
🏁 Script executed:
grep -n "readonlyRPCMap" libs/wallet/src/web3-react/connection/metaMaskConnect.tsxRepository: cowprotocol/cowswap
Length of output: 109
🏁 Script executed:
grep -n "Object.fromEntries" libs/wallet/src/web3-react/connection/metaMaskConnect.tsx -A 3 -B 3Repository: cowprotocol/cowswap
Length of output: 328
🏁 Script executed:
sed -n '1,100p' libs/wallet/src/web3-react/connection/metaMaskConnect.tsx | cat -nRepository: cowprotocol/cowswap
Length of output: 1437
🏁 Script executed:
head -100 libs/wallet/src/web3-react/connection/metaMaskConnect.tsxRepository: cowprotocol/cowswap
Length of output: 1192
🏁 Script executed:
rg "fromEntries.*chainId.*0x" libs/wallet/src/web3-react/ -B 3 -A 3Repository: cowprotocol/cowswap
Length of output: 45
🏁 Script executed:
rg "0x.*Number.*toString.*16" --type ts -B 5 -A 2 | grep -A 7 "readonlyRPCMap\|metaMaskConnect"Repository: cowprotocol/cowswap
Length of output: 795
🏁 Script executed:
grep -A 5 -B 5 "readonlyRPCMap:" libs/wallet/src/web3-react/connection/metaMaskConnect.tsxRepository: cowprotocol/cowswap
Length of output: 371
🏁 Script executed:
rg "MetaMaskConnectOptions" --type ts -B 2 -A 2Repository: cowprotocol/cowswap
Length of output: 1516
Strengthen the type definition to document the hex-format requirement.
While the call site correctly transforms RPC_URLS keys to hex format before passing readonlyRPCMap, the type definition Record<string, string> doesn't enforce this contract. The cast at line 121 is a no-op at runtime and misleads developers into thinking the transformation happens in the connector rather than at the call site. If another caller is added without the transformation, the connector would silently receive malformed chain IDs.
Either update the type to Record<0x${string}, string> with matching validation at the call site, or document the hex-format requirement explicitly in the type definition's JSDoc comment.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts` around lines
33 - 40, Update the MetaMaskConnectOptions.readonlyRPCMap type to require
hex-prefixed chain IDs (use Record<`0x${string}`, string>) and remove any
misleading runtime casts; then add/ensure validation at the call site that
builds readonlyRPCMap (the place currently casting keys to hex) so only
hex-prefixed keys are passed into the connector. Refer to the
MetaMaskConnectOptions type and the readonlyRPCMap usage/cast in the connector
to locate the changes and ensure the type and runtime validation are consistent.
| if (this.eagerConnection) return | ||
|
|
||
| this.eagerConnection = import('@metamask/connect-evm').then(async (module) => { | ||
| if (!this.client) { | ||
| // Library entry point: builds the multichain client, | ||
| // wires mobile deeplinks when not shown in the extension. | ||
| this.client = await module.createEVMClient({ | ||
| dapp: { | ||
| name: this.options.dappMetadata.name ?? 'CoW Swap', | ||
| url: this.options.dappMetadata.url ?? '', | ||
| ...(this.options.dappMetadata.iconUrl !== undefined ? { iconUrl: this.options.dappMetadata.iconUrl } : {}), | ||
| }, | ||
| api: { | ||
| supportedNetworks: (this.options.readonlyRPCMap ?? {}) as Record<`0x${string}`, string>, | ||
| }, | ||
| // createEVMClient is typed to accept MultichainOptions.mobile (see @metamask/connect-evm connect.d.ts). | ||
| mobile: { | ||
| useDeeplink: true, | ||
| }, | ||
| }) | ||
| } | ||
|
|
||
| this.provider = this.client.getProvider() as unknown as MetaMaskProvider | ||
|
|
||
| this.provider.on('connect', (({ chainId }: ProviderConnectInfo): void => { | ||
| this.actions.update({ chainId: parseChainId(chainId) }) | ||
| }) as Listener) | ||
|
|
||
| this.provider.on('disconnect', (async (error: ProviderRpcError): Promise<void> => { | ||
| const originalError = getOriginalRpcError(error) | ||
|
|
||
| // MetaMask may emit transient disconnects; keep session if accounts still available. | ||
| if (error && originalError.code === 1013 && this.provider) { | ||
| const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[] | ||
| if (accounts.length > 0) return | ||
| } | ||
|
|
||
| this.actions.resetState() | ||
| this.onError?.(error) | ||
| }) as Listener) | ||
|
|
||
| this.provider.on('chainChanged', ((chainId: string): void => { | ||
| this.actions.update({ chainId: parseChainId(chainId) }) | ||
| }) as Listener) | ||
|
|
||
| this.provider.on('accountsChanged', ((accounts: string[]): void => { | ||
| if (accounts.length === 0) { | ||
| this.actions.resetState() | ||
| } else { | ||
| this.actions.update({ accounts }) | ||
| } | ||
| }) as Listener) | ||
| }) | ||
|
|
||
| return this.eagerConnection |
There was a problem hiding this comment.
Return the shared init promise instead of early-resolving.
Line 109 currently exits isomorphicInitialize() without awaiting the in-flight initialization. Since connectEagerly() is started from libs/wallet/src/web3-react/Web3Provider/hooks/useEagerlyConnect.ts:24-38, a user-triggered activate() can overlap with it and observe this.provider as unset even though the SDK import/client setup is still running. The memoized promise is also never cleared after a rejection, so one transient init failure bricks the connector for the rest of the session.
Suggested fix
private async isomorphicInitialize(): Promise<void> {
- if (this.eagerConnection) return
+ if (this.eagerConnection) return this.eagerConnection
this.eagerConnection = import('@metamask/connect-evm')
.then(async (module) => {
// existing initialization body
})
+ .catch((error) => {
+ this.eagerConnection = undefined
+ throw error
+ })
return this.eagerConnection
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts` around lines
109 - 163, The isomorphicInitialize() path currently does "if
(this.eagerConnection) return" which returns undefined instead of the shared
promise and never clears the memo on errors; change that to return
this.eagerConnection so callers await the in-flight init, and wrap the
import(...).then(...) chain with a .catch(err => { this.eagerConnection =
undefined; throw err }) so a transient failure clears this.eagerConnection;
update the block that assigns this.eagerConnection (the Promise that imports
'@metamask/connect-evm' and calls createEVMClient/getProvider and provider.on
handlers) to return the Promise and ensure rejections reset
this.eagerConnection.
| this.provider.on('disconnect', (async (error: ProviderRpcError): Promise<void> => { | ||
| const originalError = getOriginalRpcError(error) | ||
|
|
||
| // MetaMask may emit transient disconnects; keep session if accounts still available. | ||
| if (error && originalError.code === 1013 && this.provider) { | ||
| const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[] | ||
| if (accounts.length > 0) return | ||
| } | ||
|
|
||
| this.actions.resetState() | ||
| this.onError?.(error) | ||
| }) as Listener) |
There was a problem hiding this comment.
Catch probe failures inside the disconnect handler.
On a real disconnect, the fallback eth_accounts request can fail too. When that happens, this async listener rejects before Lines 146-147 run, so wallet state is never reset on the disconnect path. Catch the probe locally and fall through to the normal teardown branch.
Suggested fix
if (error && originalError.code === 1013 && this.provider) {
- const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[]
- if (accounts.length > 0) return
+ try {
+ const accounts = (await this.provider.request({ method: 'eth_accounts' })) as string[]
+ if (accounts.length > 0) return
+ } catch {
+ // fall through to reset state when the probe itself fails
+ }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@libs/wallet/src/web3-react/connectors/metaMaskConnect/index.ts` around lines
137 - 148, The disconnect listener attached in provider.on('disconnect') can
reject because the fallback probe (this.provider.request({ method:
'eth_accounts' })) may fail; modify the async listener (the anonymous function
passed to provider.on) to wrap the eth_accounts probe in a try/catch so probe
failures are swallowed and execution falls through to the teardown logic: call
getOriginalRpcError(error) as before, attempt the accounts probe inside try {
const accounts = await this.provider.request(...) } catch { /* treat as no
accounts; continue */ }, keep the existing short-circuit return when
accounts.length > 0, and ensure this.actions.resetState() and
this.onError?.(error) always run on real disconnects.
|
Hi! Thanks a lot for your contribution! |
@metamask/connect-evm integration (replace metamaskSdk)
This PR replaces @metamask/sdk with @metamask/connect-evm for the web3-react MetaMask path. The app still uses ConnectionType.METAMASK and the same activation flow; only the underlying wallet client changes.
Implementation
MetaMaskConnect connector: lazy-loads@metamask/connect-evm, calls createEVMClient with dapp metadata, api.supportedNetworks (from existing RPC_URLS), and mobile: { useDeeplink: true } for mobile app opens.client.getProvider()is wired into web3-react with the usual event handlers (chainChanged, accountsChanged, etc.).getWeb3ReactConnectionstill maps ConnectionType.METAMASK to metaMaskConnectConnection.metaMask()from @wagmi/connectors for the viem migration path (separate from this connector).Docs
Quick overview of changes: libs/wallet/src/web3-react/connectors/metaMaskConnect/README.md.
Testing
Summary by CodeRabbit
New Features
Chores