Virtual TestNets are live! ⚡️ Test and stage dapps on real-time production data.
Get started →

All Products

Virtual TestNets
UI Libraries
Wallet Connect

ConnectKit and Virtual TestNets

Web3Modal SDK asimplifies connecting Web3 dapps to wallets, offering a user-friendly interface for executing actions like signing transactions and interacting with smart contracts on the blockchain.

You can use a Virtual Testnet as a chain for UI development, testing, and dapp demo mode.

Create a Virtual TestNet

In Tenderly Dashboard, create a new Virtual TestNet:

  • Select Mainnet as the base network
  • Name it Web3 Modal TestNet
  • Choose a unique chain ID 73571
  • Turn on the Public Explorer
  • Copy the Testnet RPC

Create a Chain Config

Create a file src/tenderly.config.ts and replace the following:

  1. Paste the chain ID to the id property
  2. Change the name and currency
  3. Paste the Public RPC to rpcUrls.default.http
  4. Paste the Block Explorer URL to blockExplorers.default.url
src/tenderly.config.ts
import { defineChain } from 'viem'
 
export const vMainnet = defineChain({
  id: 73571,
  name: 'Virtual Ethereum Mainnet',
  nativeCurrency: { name: 'vEther', symbol: 'vETH', decimals: 18 },
  rpcUrls: {
    default: { http: [process.env.TENDERLY_VIRTUAL_MAINNET_RPC!] }
  },
  blockExplorers: {
    default: {
      name: 'Tenderly Explorer',
      url: 'https://dashboard.tenderly.co/explorer/vnet/47cdac98-cda3-431a-8fce-9f31037a3d0c'
    }
  },
  contracts: {
    ensRegistry: {
      address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'
    },
    ensUniversalResolver: {
      address: '0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da',
      blockCreated: 16773775
    },
    multicall3: {
      address: '0xca11bde05977b3631167028862be2a173976ca11',
      blockCreated: 14353601
    }
  }
})

Create a Wagmi Config

Create a Wagmi config that will:

  • include the vMainnet chain we defined in the previous step
  • Specify the Public RPC in transport under vMainnet.id
src/wagmi.config.ts
import { cookieStorage, createConfig, createStorage, http } from 'wagmi'
import { mainnet } from 'wagmi/chains'
import { vMainnet } from '@/tenderly.config'
import { injected } from '@wagmi/core'
 
// 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')
 
// Create wagmiConfig
export const config = createConfig({
  chains: [mainnet, vMainnet],
  connectors: [
    injected()
  ],
  ssr: true,
  transports: {
    [mainnet.id]: http('https://mainnet.gateway.tenderly.co/'),
    [vMainnet.id]: http(process.env.TENDERLY_VIRTUAL_MAINNET_RPC!)
  },
  storage: createStorage({
    storage: cookieStorage
  }),
})

Create a Web3ModalProvider

Create a Web3ModalProvider that will wrap your application.

To use the Virtual Testnet only while building UI, testing, and demoing the dapp, we added a NEXT_PUBLIC_TENDERLY_VNETS_ENABLED environment variable. The call to createWeb3Modal uses vMainnet as the default chain, when app runs with NEXT_PUBLIC_TENDERLY_VNETS_ENABLED.

In this example, we used the w3m-button web-component to trigger the Web3 Modal.

'use client'
 
import React, { ReactNode } from 'react'
import { wagmiConfig, projectId } from './wagmi.config'
import { createWeb3Modal } from '@web3modal/wagmi/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { State, WagmiProvider } from 'wagmi'
import { vMainnet } from '@/tenderly.config'
 
// Setup queryClient
const queryClient = new QueryClient()
 
if (!projectId) throw new Error('Project ID is not defined')
 
// Create modal
createWeb3Modal({
  wagmiConfig: wagmiConfig,
  projectId,
  enableAnalytics: true, // Optional - defaults to your Cloud configuration
  enableOnramp: true, // Optional - false as default
  defaultChain: process.env.NEXT_PUBLIC_TENDERLY_VNETS_ENABLED === 'true' ? vMainnet : wagmiConfig.chains[0]
})
 
export default function Web3ModalProvider({ children, initialState }: {
  children: ReactNode
  initialState?: State
}) {
  return (
    <WagmiProvider config={wagmiConfig} initialState={initialState}>
      <QueryClientProvider client={queryClient}>
        <w3m-button />
        {children}
      </QueryClientProvider>
    </WagmiProvider>
  )
}

Use the Web3ModalProvider

Wrap your dapp body (app/layout.tsx) in a Web3ModalProvider we created in the last step.

src/app/layout.ts
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import Web3ModalProvider from '@/Web3ModalProvider';
 
const inter = Inter({ subsets: ['latin'] });
 
export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};
 
export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) {
  return (
    <html lang="en">
 
    <body className={inter.className}>
      <Web3ModalProvider>
        {children}
      </Web3ModalProvider>
    </body>
    </html>
  );
}

Run the dapp

## Get projectId at https://cloud.walletconnect.com
NEXT_PUBLIC_PROJECT_ID=???? \
NEXT_PUBLIC_TENDERLY_VNETS_ENABLED=true \
pnpm run dev

You should see