| name | migrate-wagmi-metamask-connector |
| description | Migrate a wagmi app from @metamask/sdk to the new @metamask/connect-evm connector (wagmi PR |
Migrate Wagmi MetaMask Connector to @metamask/connect-evm
When to use
- Upgrading a wagmi project from
@wagmi/connectors v6.x/v7.x (which bundled @metamask/sdk) to v8.x+ / wagmi >= 3.6 (which uses @metamask/connect-evm)
- You see errors like
Cannot find module '@metamask/sdk' after updating wagmi
- You want to adopt the new MetaMask Connect SDK in an existing wagmi app
- Consumer is migrating to the latest wagmi version that includes the MetaMask connector refactor (PR #4960)
Breaking Change Summary
The MetaMask connector in wagmi has been completely rewritten. The underlying SDK changed from @metamask/sdk to @metamask/connect-evm. The connector now dynamically imports @metamask/connect-evm instead of bundling @metamask/sdk.
Key impacts:
- New optional peer dependency:
@metamask/connect-evm must be installed explicitly, at a version inside wagmi's declared peer range (check npm info @wagmi/connectors peerDependencies — currently ^1.3.0)
- Old dependency
@metamask/sdk should be removed
- Configuration parameter names changed (
dappMetadata → dapp, useDeeplink → mobile.useDeeplink)
- Several deprecated SDK-specific options are removed entirely
- Internal provider type changed from
SDKProvider to EIP1193Provider
Workflow
Step 1: Update Dependencies
Remove the old SDK and install the new one:
npm uninstall @metamask/sdk
npm install @metamask/connect-evm
pnpm remove @metamask/sdk
pnpm add @metamask/connect-evm
yarn remove @metamask/sdk
yarn add @metamask/connect-evm
Then update wagmi packages to the latest:
npm install wagmi@latest @wagmi/core@latest @wagmi/connectors@latest
Step 2: Update MetaMask Connector Configuration
Before (old @metamask/sdk options):
import { metaMask } from 'wagmi/connectors'
metaMask({
dappMetadata: {
name: 'My Dapp',
url: 'https://mydapp.com',
},
useDeeplink: true,
logging: { sdk: false },
forceDeleteProvider: false,
forceInjectProvider: false,
injectProvider: false,
})
After (new @metamask/connect-evm options):
import { metaMask } from 'wagmi/connectors'
metaMask({
dapp: {
name: 'My Dapp',
url: 'https://mydapp.com',
iconUrl: 'https://mydapp.com/icon.png',
},
debug: false,
mobile: {
useDeeplink: true,
preferredOpenLink: undefined,
},
})
Step 3: Configuration Parameter Migration Reference
Old Parameter (@metamask/sdk) | New Parameter (@metamask/connect-evm) | Notes |
|---|
dappMetadata: { name, url } | dapp: { name, url, iconUrl } | dappMetadata still works but is deprecated |
logging: { sdk: true } | debug: true | logging still works but is deprecated |
useDeeplink: boolean | mobile: { useDeeplink: boolean } | Moved into mobile namespace |
preferredOpenLink | mobile: { preferredOpenLink } | Moved into mobile namespace |
forceDeleteProvider | (removed) | No replacement — not needed with new SDK |
forceInjectProvider | (removed) | No replacement — not needed with new SDK |
injectProvider | (removed) | No replacement — not needed with new SDK |
readonlyRPCMap | (auto-configured) | Built automatically from wagmi's chain config |
_source | (auto-set to 'wagmi') | Set internally by the connector |
Step 4: Update connectAndSign / connectWith Usage (if applicable)
The connectAndSign parameter name changed from msg to message internally. However, at the wagmi connector level the API is the same — you still pass connectAndSign: 'message string' in the metaMask() parameters.
metaMask({
dapp: { name: 'My Dapp' },
connectAndSign: 'Please sign this message to verify your identity',
})
The connectWith API is also unchanged at the wagmi level:
metaMask({
dapp: { name: 'My Dapp' },
connectWith: {
method: 'eth_signTypedData_v4',
params: [address, typedData],
},
})
Step 5: Handle Provider Type Changes
If your code directly accesses the provider from the connector, the type has changed:
const connector = config.connectors.find(c => c.id === 'metaMaskSDK')
if (connector) {
const instance = await connector.getInstance()
}
Step 6: Remove Deprecated Patterns
The new connector handles event listeners internally. If you had code that manually managed MetaMask SDK event listeners, you can remove it:
Step 7: Additional Wagmi API Renames (same major version)
This wagmi release also includes several API renames. Deprecated aliases are provided but you should migrate:
| Old API | New API | Package |
|---|
useAccount() | useConnection() | wagmi |
useAccountEffect() | useConnectionEffect() | wagmi |
useSwitchAccount() | useSwitchConnection() | wagmi |
getAccount() | getConnection() | @wagmi/core |
switchAccount() | switchConnection() | @wagmi/core |
watchAccount() | watchConnection() | @wagmi/core |
WagmiConfig | WagmiProvider | wagmi (alias removed) |
useToken() | useReadContracts() | wagmi (hook removed) |
useFeeData() | useEstimateFeesPerGas() | wagmi (alias removed) |
normalizeChainId() | (removed) | wagmi (export removed) |
Step 8: Verify the Migration
After making changes, verify:
- Build succeeds —
npm run build or tsc --noEmit should pass
- No
@metamask/sdk imports remain — search your codebase:
grep -r "@metamask/sdk" --include="*.ts" --include="*.tsx" --include="*.js"
- Wallet connection works — test connecting via MetaMask browser extension
- Mobile deep-link works (if applicable) — test QR code / deep-link flow
- Chain switching works — test switching between configured chains
- Signing works — test message signing and transaction signing
Complete Before/After Example
Before (@wagmi/connectors <= 7.x + @metamask/sdk):
import { createConfig, http } from 'wagmi'
import { mainnet, sepolia, optimism } from 'wagmi/chains'
import { metaMask } from 'wagmi/connectors'
export const config = createConfig({
chains: [mainnet, sepolia, optimism],
connectors: [
metaMask({
dappMetadata: {
name: 'My Dapp',
url: window.location.origin,
},
useDeeplink: true,
}),
],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
[optimism.id]: http(),
},
})
After (wagmi >= 3.6 / @wagmi/connectors >= 8 + @metamask/connect-evm):
import { createConfig, http } from 'wagmi'
import { mainnet, sepolia, optimism } from 'wagmi/chains'
import { metaMask } from 'wagmi/connectors'
export const config = createConfig({
chains: [mainnet, sepolia, optimism],
connectors: [
metaMask({
dapp: {
name: 'My Dapp',
url: window.location.origin,
},
mobile: {
useDeeplink: true,
},
}),
],
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
[optimism.id]: http(),
},
})
React Native Specific Migration
If you are using wagmi with React Native, the preferredOpenLink callback has moved:
metaMask({
dappMetadata: { name: 'My RN App' },
preferredOpenLink: (link, target) => Linking.openURL(link),
useDeeplink: true,
})
metaMask({
dapp: { name: 'My RN App' },
mobile: {
preferredOpenLink: (link, target) => Linking.openURL(link),
useDeeplink: true,
},
})
Important Notes
@metamask/connect-evm is an optional peer dependency of @wagmi/connectors — you only need it if you use the metaMask() connector
- The connector ID remains
'metaMaskSDK' and the name remains 'MetaMask' — no changes to connector identity
- The connector's
rdns is ['io.metamask', 'io.metamask.mobile'] — unchanged
- The
supportedNetworks map is now auto-built from wagmi's configured chains and their default RPC URLs — you no longer need to pass readonlyRPCMap
- The
dappMetadata parameter still works (it's mapped to dapp internally) but is deprecated — migrate to dapp for forward compatibility
- The
logging parameter still works (mapped to debug: true) but is deprecated
- If no
dapp config is provided, the connector defaults to { name: window.location.hostname, url: window.location.href } in browsers, or { name: 'wagmi' } in Node.js/SSR