Skip to main content

Next.js

Web3Modal SDK has support for Wagmi and Ethers, which will help you interact with wallets and smart contracts. Choose one of these Ethereum libraries to get started.

Note

These steps are specific to Next.js app router. For other React frameworks read the React documentation.

Installation

npm install @web3modal/wagmi wagmi viem @tanstack/react-query

Don't have a project ID?

Head over to WalletConnect Cloud and create a new project now!

Get startedcloud illustration

Implementation

Web3Modal can be configured in two different ways:

  • Default: For a quick integration you can use defaultWagmiConfig function which wraps Wagmi's creatConfig function with predefined configuration. This includes WalletConnect, Coinbase and Injected connectors, and our Blockchain API as a transport (if the chain is not support by the Blockchain API it will fallback to the chain's default RPC).
    As shown in the code example, this configuration (with the exception of the connectors) can be overridden.
  • Custom: This configuration setup is great for projects that already have Wagmi integrated or that would like to have more control over the Wagmi configuration. Once Wagmi is integrated in your project you will need to add showQrModal: false to the WalletConnect connector and call createWeb3Modal with its required parameters.

Select your preferred configuration mode below:

Wagmi config

Create a new file for your Wagmi configuration, since we are going to be calling this function on the client and the server it cannot live inside a file with the 'use client' directive.

For this example we will create a file called config/index.tsx outside our app directory and set up the following configuration

import { defaultWagmiConfig } from '@web3modal/wagmi/react/config'

import { cookieStorage, createStorage } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'

// Get projectId at https://cloud.walletconnect.com
export const projectId = process.env.NEXT_PUBLIC_PROJECT_ID

if (!projectId) throw new Error('Project ID is not defined')

const metadata = {
name: 'Web3Modal',
description: 'Web3Modal Example',
url: 'https://web3modal.com', // origin must match your domain & subdomain
icons: ['https://avatars.githubusercontent.com/u/37784886']
}

// Create wagmiConfig
const chains = [mainnet, sepolia] as const
export const config = defaultWagmiConfig({
chains,
projectId,
metadata,
ssr: true,
storage: createStorage({
storage: cookieStorage
}),
...wagmiOptions // Optional - Override createConfig parameters
})
info
  • Notice that we are using here the recommended configuration from Wagmi for SSR.
  • Using cookies is completely optional and by default Wagmi will use localStorage instead if the storage param is not defined.
  • The ssr flag will delay the hydration of the Wagmi's store to avoid hydration mismatch errors.

Context Provider

Let's create now a context provider that will wrap our application and initialized Web3Modal (createWeb3Modal needs to be called inside a React Client Component file).

In this example we will create a file called context/index.tsx outside our app directory and set up the following configuration

'use client'

import React, { ReactNode } from 'react'
import { config, projectId } from '@/config'

import { createWeb3Modal } from '@web3modal/wagmi/react'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

import { State, WagmiProvider } from 'wagmi'

// Setup queryClient
const queryClient = new QueryClient()

if (!projectId) throw new Error('Project ID is not defined')

// Create modal
createWeb3Modal({
wagmiConfig: config,
projectId,
enableAnalytics: true, // Optional - defaults to your Cloud configuration
enableOnramp: true // Optional - false as default
})

export default function Web3ModalProvider({
children,
initialState
}: {
children: ReactNode
initialState?: State
}) {
return (
<WagmiProvider config={config} initialState={initialState}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</WagmiProvider>
)
}

Layout

Next, in our app/layout.tsx file, we will import our Web3ModalProvider component and call the Wagmi's function cookieToInitialState.

The initialState returned by cookieToInitialState, contains the optimistic values that will populate the Wagmi's store both on the server and client.

import './globals.css'
import type { Metadata } from 'next'
import { headers } from 'next/headers'

import { cookieToInitialState } from 'wagmi'

import { config } from '@/config'
import Web3ModalProvider from '@/context'

export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app'
}

export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode
}>) {
const initialState = cookieToInitialState(config, headers().get('cookie'))
return (
<html lang="en">
<body>
<Web3ModalProvider initialState={initialState}>{children}</Web3ModalProvider>
</body>
</html>
)
}
note

The cookieToInitialState function is only needed when using cookies for the Wagmi's storage.

IMPORTANT

Make sure that the url from the metadata matches your domain and subdomain. This will later be used by the Verify API to tell wallets if your application has been verified or not.

Trigger the modal

To open Web3Modal you can use our web component or build your own button with Web3Modal hooks.

export default function ConnectButton() {
return <w3m-button />
}

Learn more about the Web3Modal web components here

note

Web components are global html elements that don't require importing.

Smart Contract Interaction

Wagmi hooks can help us interact with wallets and smart contracts:

import { useReadContract } from 'wagmi'
import { USDTAbi } from '../abi/USDTAbi'

const USDTAddress = '0x...'

function App() {
const result = useReadContract({
abi: USDTAbi,
address: USDTAddress,
functionName: 'totalSupply'
})
}

Read more about Wagmi hooks for smart contract interaction here.

Extra configuration

Next.js relies on SSR. This means some specific steps are required to make Web3Modal work properly.

  • Add the following code in the next.config.js file
// Path: next.config.js
const nextConfig = {
webpack: config => {
config.externals.push('pino-pretty', 'lokijs', 'encoding')
return config
}
}