Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions metamask-connect/evm/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ title: 'JavaScript',
description: 'Set up MetaMask Connect EVM in a JavaScript dapp.',
},
{
href: '/metamask-connect/evm/quickstart/wagmi',
title: 'Wagmi',
description: 'Set up MetaMask Connect EVM in a React and Wagmi dapp.',
},
{
href: '/metamask-connect/evm/quickstart/react-native',
title: 'React Native',
description: 'Set up MetaMask Connect EVM in a React Native or Expo dapp.',
Expand Down
281 changes: 224 additions & 57 deletions metamask-connect/evm/quickstart/wagmi.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,58 @@
---
title: "Wagmi Integration - MetaMask Connect EVM"
description: Integrate MetaMask into a React dapp using Wagmi hooks like useConnect and useAccount, with the MetaMask connector and wallet connection UI.
title: 'Wagmi Integration - MetaMask Connect EVM'
description: Integrate MetaMask Connect EVM into a React dapp using Wagmi hooks like useConnect and useConnection, with the MetaMask connector and wallet connection UI.
toc_max_heading_level: 3
sidebar_label: Wagmi
keywords: [connect, MetaMask, JavaScript, Wagmi, SDK, dapp, Wallet SDK, wagmi connector, react hooks, useConnect, useAccount, wallet connector, web3 react]
keywords:
[
connect,
MetaMask,
JavaScript,
Wagmi,
MetaMask Connect,
dapp,
connect-evm,
wagmi connector,
react hooks,
useConnect,
useConnection,
wallet connector,
web3 react,
]
---

:::info Heads up
Looks like you've landed on a guide that still uses the MetaMask legacy SDK (`@metamask/sdk`).
The MetaMask Connect integration for this library is on its way — once ready, it will be linked
from the sidebar navigation. In the meantime, this guide is still perfectly valid if you're using
MetaMask SDK.
:::
# Connect to EVM - Wagmi quickstart

# Connect to MetaMask using JavaScript + Wagmi
Get started with MetaMask Connect EVM in a React and Wagmi dapp.
[Download the quickstart template](#set-up-using-a-template) or [manually set up MetaMask Connect EVM](#set-up-manually) in an existing dapp.

Get started with MetaMask SDK in a JavaScript and Wagmi dapp.
[Download the quickstart template](#set-up-using-a-template) or [manually set up MetaMask SDK](#set-up-manually) in an existing dapp.
:::tip Migrating from @metamask/sdk?
If you are upgrading an existing wagmi project that used `@metamask/sdk`, see the
[Wagmi connector migration reference](#migrate-from-metamasksdk) at the bottom of this page
for a parameter mapping table.
:::

<!--
TOD0: Update with new screenshot and link
<p align="center">
<!-- a href="https://metamask-wagmi-demo.vercel.app/" target="_blank" -->
a href="https://metamask-wagmi-demo.vercel.app/" target="_blank"
<img src={require("../_assets/quickstart.jpg").default} alt="MetaMask Connect EVM with Wagmi dapp interface" width="600px" class="appScreen" />
<!-- /a -->
</p>
/a
</p> -->

## Prerequisites

- [Node.js](https://nodejs.org/) version 19 or later installed.
- A package manager installed, such as [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm), [Yarn](https://yarnpkg.com/), [pnpm](https://pnpm.io/installation), or [bun](https://bun.sh/).
- [MetaMask](https://metamask.io/) installed in your browser or on mobile.
- [MetaMask](https://metamask.io/download) installed in your browser or on mobile.
- An [Infura API key](/developer-tools/dashboard/get-started/create-api) from the MetaMask Developer dashboard.

## Set up using a template

1. Download the [MetaMask SDK Wagmi template](https://github.com/MetaMask/metamask-sdk-examples/tree/main/quickstarts/wagmi):
1. Download the [MetaMask Connect Wagmi template](https://github.com/MetaMask/metamask-connect-examples/tree/main/integrations/wagmi):

```bash
npx degit MetaMask/metamask-sdk-examples/quickstarts/wagmi metamask-wagmi
npx degit MetaMask/metamask-connect-examples/integrations/wagmi metamask-wagmi
```

2. Navigate into the repository:
Expand All @@ -51,11 +68,11 @@ Get started with MetaMask SDK in a JavaScript and Wagmi dapp.
`degit` is a tool that enables cloning only the directory structure from a GitHub repository, without retrieving the entire repository.

Alternatively, use `git clone` to download the entire repository.
Clone the MetaMask SDK examples repository and navigate into the `quickstarts/wagmi` directory:
Clone the MetaMask Connect examples repository and navigate into the `quickstarts/wagmi` directory:

```bash
git clone https://github.com/MetaMask/metamask-sdk-examples
cd metamask-sdk-examples/quickstarts/wagmi
git clone https://github.com/MetaMask/metamask-connect-examples
cd metamask-connect-examples/integrations/wagmi
```

</div>
Expand All @@ -75,12 +92,16 @@ Get started with MetaMask SDK in a JavaScript and Wagmi dapp.

## Set up manually

### 1. Install the SDK
### 1. Install dependencies

Install MetaMask SDK along with its peer dependencies to an existing React project:
Install MetaMask Connect EVM along with its peer dependencies to an existing React project:

:::note Version requirements
This quickstart requires `wagmi@^3.6.0` and `wagmi/connectors@^8.0.0`
:::

```bash npm2yarn
npm install @metamask/sdk wagmi viem@2.x @tanstack/react-query
npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0 viem@2.x @tanstack/react-query
```

### 2. Import required dependencies
Expand All @@ -90,30 +111,34 @@ In the root of your project, import the required dependencies:
```jsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { http, WagmiProvider, createConfig } from 'wagmi'
import { mainnet, linea, lineaSepolia } from 'wagmi/chains'
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, set the `infuraAPIKey` option to your [Infura API key](/developer-tools/dashboard/get-started/create-api) to use for RPC requests:
In the following example, replace `<VITE_INFURA_API_KEY>` with your [Infura API key](/developer-tools/dashboard/get-started/create-api):

```jsx
const INFURA_KEY = import.meta.env.VITE_INFURA_API_KEY

const config = createConfig({
ssr: true, // Enable this if your dapp uses server-side rendering.
chains: [mainnet, linea, lineaSepolia],
chains: [mainnet, sepolia, lineaSepolia],
connectors: [
metaMask({
infuraAPIKey: process.env.NEXT_PUBLIC_INFURA_API_KEY!,
dapp: {
name: 'My Dapp',
url: window.location.origin,
},
}),
],
transports: {
[mainnet.id]: http(),
[linea.id]: http(),
[lineaSepolia.id]: http(),
[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
Expand All @@ -139,59 +164,201 @@ const App = () => {
Add the wallet connect and disconnect buttons to your application:

```jsx
import { useAccount, useConnect, useDisconnect } from 'wagmi'
import { useConnection, useConnect, useConnectors, useDisconnect } from 'wagmi'

export const ConnectButton = () => {
const { address } = useAccount()
const { connectors, connect } = useConnect()
const { disconnect } = useDisconnect()
const { address, isConnected } = useConnection()
const connectors = useConnectors()
const connect = useConnect()
const disconnect = useDisconnect()

const handleConnect = async () => {
// highlight-start
const connector = connectors.find(c => c.id === 'metaMaskSDK') ?? connectors[0]
await connect.mutateAsync({ connector })
// highlight-end
}

return (
<div>
{address ? (
<button onClick={() => disconnect()}>Disconnect</button>
{isConnected ? (
<button onClick={() => disconnect.mutate()}>Disconnect</button>
) : (
connectors.map(connector => (
<button key={connector.uid} onClick={() => connect({ connector })}>
{connector.name}
</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`.

## Production readiness
## Common operations

:::tip
For production deployments, it's important to use reliable RPC providers instead of public nodes.
We recommend using services like [MetaMask Developer](https://developer.metamask.io/) to ensure better reliability and performance.
:::
### Switch chains

Use `useConnection`, `useChains`, and `useSwitchChain` to let users switch between your configured chains:

```tsx
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:

```tsx
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:

```tsx
import { useSendTransaction } from 'wagmi'
import { parseEther } from 'viem'

Configure your RPC endpoints in the Wagmi configuration as follows, replacing `<YOUR-API-KEY>` with your [Infura API key](/developer-tools/dashboard/get-started/create-api):
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:

```jsx
const config = createConfig({
// ... other config options
transports: {
[mainnet.id]: http('https://mainnet.infura.io/v3/<YOUR-API-KEY>'),
[sepolia.id]: http('https://sepolia.infura.io/v3/<YOUR-API-KEY>'),
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:

```jsx
metaMask({
dapp: { name: 'My Dapp', url: window.location.origin },
connectWith: {
method: 'eth_signTypedData_v4',
params: [address, JSON.stringify(typedData)],
},
})
```

## Production readiness

:::tip
For production deployments, use reliable RPC providers instead of public nodes.
We recommend using services like [Infura](https://developer.metamask.io/) to ensure better reliability and performance.
See the [production readiness checklist](../guides/best-practices/production-readiness.md) for more details.
:::

## Migrate from `@metamask/sdk` {#migrate-from-metamasksdk}

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:

1. Replace `@metamask/sdk` with `@metamask/connect-evm` and update Wagmi packages:

```bash npm2yarn
npm uninstall @metamask/sdk
npm install @metamask/connect-evm wagmi@^3.6.0 wagmi/connectors@^8.0.0
```

2. Update hook usage for wagmi v3:

| Old (wagmi v2) | New (wagmi v3) | Notes |
| ----------------------------------- | -------------------------------------- | ------------------------------------------- |
| `useAccount()` | `useConnection()` | Returns `address`, `isConnected`, `chainId` |
| `useConnect()` returns `connectors` | `useConnectors()` hook | Connectors are a separate hook |
| `connect({ connector })` | `connect.mutate({ connector })` | Hooks return mutation objects |
| `signMessage({ message })` | `signMessage.mutateAsync({ message })` | Use `.mutateAsync()` for async results |
| `sendTransaction({...})` | `sendTx.mutateAsync({...})` | Use `.mutateAsync()` for async results |
| `switchChain({ chainId })` | `switchChain.mutate({ chainId })` | Mutation pattern |

3. Update connector options:

| 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)_ | 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](../guides/migrate-from-sdk.md).

## Next steps

After completing the basic setup, follow these guides to add your own functionality:

- [Manage user accounts](../guides/manage-user-accounts.md)
- [Manage networks](../guides/manage-networks.md)
- [Send transactions](../guides/send-transactions/index.md)
- [Sign data](../guides/sign-data/index.md)
- [Interact with smart contracts](../guides/interact-with-contracts.md)

## Live example
<!-- ## Live example

<iframe className="mt-6" width="100%" height="600px" frameBorder="0" src="https://stackblitz.com/github/MetaMask/metamask-sdk-examples/tree/main/quickstarts/wagmi?ctl=1&embed=1&file=wagmi.config.ts&hideNavigation=1"></iframe>
<iframe className="mt-6" width="100%" height="600px" frameBorder="0" src="https://stackblitz.com/github/MetaMask/metamask-sdk-examples/tree/main/quickstarts/wagmi?ctl=1&embed=1&file=wagmi.config.ts&hideNavigation=1"></iframe> -->
Loading