Connect to EVM - Wagmi quickstart
Get started with MetaMask Connect EVM in a React and Wagmi dapp. Download the quickstart template or manually set up MetaMask Connect EVM in an existing dapp.
If you are upgrading an existing wagmi project that used @metamask/sdk, see the
Wagmi connector migration reference at the bottom of this page
for a parameter mapping table.
Prerequisites
- Node.js version 19 or later installed.
- A package manager installed, such as npm, Yarn, pnpm, or bun.
- MetaMask installed in your browser or on mobile.
- An Infura API key from the MetaMask Developer dashboard.
Set up using a template
-
Download the MetaMask Connect Wagmi template:
npx degit MetaMask/metamask-connect-examples/integrations/wagmi metamask-wagmi -
Navigate into the repository:
cd metamask-wagmiDegit vs. Git clone
degitis a tool that enables cloning only the directory structure from a GitHub repository, without retrieving the entire repository.Alternatively, use
git cloneto download the entire repository. Clone the MetaMask Connect examples repository and navigate into thequickstarts/wagmidirectory:git clone https://github.com/MetaMask/metamask-connect-examples
cd metamask-connect-examples/integrations/wagmi -
Install dependencies:
pnpm install -
Run the project:
pnpm dev
Set up manually
1. Install dependencies
Install MetaMask Connect EVM along with its peer dependencies to an existing React project:
This quickstart requires wagmi@^3.6.0 and wagmi/connectors@^8.0.0
- npm
- Yarn
- pnpm
- Bun
npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query
yarn add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query
pnpm add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query
bun add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query
2. Import required dependencies
In the root of your project, import the required dependencies:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { http, WagmiProvider, createConfig } from 'wagmi'
import { mainnet, sepolia, lineaSepolia } from 'wagmi/chains'
import { metaMask } from 'wagmi/connectors'
3. Configure your project
Set up your configuration with the desired chains and connectors.
In the following example, replace <VITE_INFURA_API_KEY> with your Infura API key:
const INFURA_KEY = import.meta.env.VITE_INFURA_API_KEY
const config = createConfig({
chains: [mainnet, sepolia, lineaSepolia],
connectors: [
metaMask({
dapp: {
name: 'My Dapp',
url: window.location.origin,
},
}),
],
transports: {
[mainnet.id]: http(`https://mainnet.infura.io/v3/${INFURA_KEY}`),
[sepolia.id]: http(`https://sepolia.infura.io/v3/${INFURA_KEY}`),
[lineaSepolia.id]: http(`https://linea-sepolia.infura.io/v3/${INFURA_KEY}`),
},
})
4. Set up providers
Wrap your application with the necessary providers:
const client = new QueryClient()
const App = () => {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={client}>
<Component {...pageProps} />
</QueryClientProvider>
</WagmiProvider>
)
}
5. Add the connect button
Add the wallet connect and disconnect buttons to your application:
import { useConnection, useConnect, useConnectors, useDisconnect } from 'wagmi'
export const ConnectButton = () => {
const { address, isConnected } = useConnection()
const connectors = useConnectors()
const connect = useConnect()
const disconnect = useDisconnect()
const handleConnect = async () => {
const connector = connectors.find(c => c.id === 'metaMaskSDK') ?? connectors[0]
await connect.mutateAsync({ connector })
}
return (
<div>
{isConnected ? (
<button onClick={() => disconnect.mutate()}>Disconnect</button>
) : (
<button onClick={handleConnect}>Connect MetaMask</button>
)}
{address && <p>Connected: {address}</p>}
</div>
)
}
After adding the connect button, test your dapp by running pnpm run dev.
Common operations
Switch chains
Use useConnection, useChains, and useSwitchChain to let users switch between your configured chains:
import { useConnection, useChains, useSwitchChain } from 'wagmi'
function ChainSwitcher() {
const { chainId } = useConnection()
const chains = useChains()
const switchChain = useSwitchChain()
return (
<div>
{chains.map(chain => (
<button
key={chain.id}
disabled={chainId === chain.id}
onClick={() => switchChain.mutate({ chainId: chain.id })}>
{chain.name}
</button>
))}
</div>
)
}
Sign a message
Use useSignMessage to request a personal_sign signature from the connected wallet:
import { useSignMessage } from 'wagmi'
function SignMessage() {
const signMessage = useSignMessage()
const handleSign = async () => {
const signature = await signMessage.mutateAsync({ message: 'Hello from my dapp!' })
console.log('Signature:', signature)
}
return (
<div>
<button disabled={signMessage.isPending} onClick={handleSign}>
{signMessage.isPending ? 'Signing...' : 'Sign Message'}
</button>
{signMessage.data && <p>Signature: {signMessage.data}</p>}
</div>
)
}
Send a transaction
Use useSendTransaction to send ETH:
import { useSendTransaction } from 'wagmi'
import { parseEther } from 'viem'
function SendTransaction() {
const sendTx = useSendTransaction()
const handleSend = async () => {
const hash = await sendTx.mutateAsync({
to: '0xRecipientAddress',
value: parseEther('0.01'),
})
console.log('Transaction hash:', hash)
}
return (
<div>
<button disabled={sendTx.isPending} onClick={handleSend}>
{sendTx.isPending ? 'Sending...' : 'Send 0.01 ETH'}
</button>
{sendTx.data && <p>Transaction hash: {sendTx.data}</p>}
</div>
)
}
Connect and sign
Use the connectAndSign connector option to connect and prompt the user to sign a message in a single approval:
metaMask({
dapp: { name: 'My Dapp', url: window.location.origin },
connectAndSign: 'By signing, you agree to our Terms of Service.',
})
Connect and execute
Use the connectWith connector option to connect and execute any RPC method in a single approval:
metaMask({
dapp: { name: 'My Dapp', url: window.location.origin },
connectWith: {
method: 'eth_signTypedData_v4',
params: [address, JSON.stringify(typedData)],
},
})
Production readiness
For production deployments, use reliable RPC providers instead of public nodes. We recommend using services like Infura to ensure better reliability and performance. See the production readiness checklist for more details.
Migrate from @metamask/sdk
If you previously used @metamask/sdk with Wagmi, the MetaMask connector now uses @metamask/connect-evm under the hood. Update your dependencies and connector configuration:
-
Replace
@metamask/sdkwith@metamask/connect-evmand update Wagmi packages:- npm
- Yarn
- pnpm
- Bun
npm uninstall @metamask/sdk
npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0yarn remove @metamask/sdk
yarn add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0pnpm remove @metamask/sdk
pnpm add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0bun remove @metamask/sdk
bun add @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 -
Update hook usage for wagmi v3:
Old (wagmi v2) New (wagmi v3) Notes useAccount()useConnection()Returns address,isConnected,chainIduseConnect()returnsconnectorsuseConnectors()hookConnectors are a separate hook connect({ connector })connect.mutate({ connector })Hooks return mutation objects signMessage({ message })signMessage.mutateAsync({ message })Use .mutateAsync()for async resultssendTransaction({...})sendTx.mutateAsync({...})Use .mutateAsync()for async resultsswitchChain({ chainId })switchChain.mutate({ chainId })Mutation pattern -
Update connector options:
Old parameter ( @metamask/sdk)New parameter ( @metamask/connect-evm)Notes dappMetadata: { name, url }dapp: { name, url, iconUrl }dappMetadatastill works but is deprecatedlogging: { sdk: true }debug: trueloggingstill works but is deprecateduseDeeplink: booleanmobile: { useDeeplink: boolean }Moved into mobilenamespacepreferredOpenLinkmobile: { preferredOpenLink }Moved into mobilenamespaceforceDeleteProvider(removed) Not needed with new SDK forceInjectProvider(removed) Not needed with new SDK injectProvider(removed) Not needed with new SDK readonlyRPCMap(auto-configured) Built automatically from Wagmi's chain config
For non-Wagmi migration details, see the full migration guide.
Next steps
After completing the basic setup, follow these guides to add your own functionality: