🤔 Got questions? Schedule an office hours session.
Virtual TestNets
UI Libraries
Reown AppKit

Reown AppKit and Virtual TestNets

With Reown AppKit, you can provide seamless wallet connections, including email and social logins, on-ramp functionality, smart accounts, one-click authentication, and wallet notifications, all designed to deliver an exceptional user experience.

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 Reown AppKit TestNet
  • Choose a unique chain ID 73571
  • Turn on the Public Explorer
  • Copy the Testnet RPC

Create a Chain Config

Create a file app/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
app/tenderly.config.ts
import { defineChain } from '@reown/appkit/networks'
 
export const vTestnet = defineChain({
  id: 73571,  // Add this to match the chain Id you set for your Virtual TestNet
  caipNetworkId: 'eip155:73571',
  chainNamespace: 'eip155',
  name: 'Virtual Sepolia',
  nativeCurrency: { name: 'vSepolia', symbol: 'vETH', decimals: 18 },
  rpcUrls: {
    default:{
      http: [process.env.TENDERLY_VIRTUAL_TESTNET_RPC!],
    }
  },
  blockExplorers: {
    default:{
      name:'Tenderly Explorer',
      url: 'https://dashboard.tenderly.co/explorer/vnet/6a6910ba-5831-4758-9d89-1f8e3169433f', // replace this with your Virtual TestNet's explorer URL
    }
  },
  contracts: {
    ensRegistry: {
      address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e'
    },
    ensUniversalResolver: {
      address: '0xE4Acdd618deED4e6d2f03b9bf62dc6118FC9A4da',
      blockCreated: 16773775
    },
    multicall3: {
      address: '0xca11bde05977b3631167028862be2a173976ca11',
      blockCreated: 14353601
    }
  }
})
 

Create a Wagmi Config

Create a Wagmi config at config/index.tsx that will:

  • include the vMainnet chain we defined in the previous step
  • Specify the Public RPC in transport under vMainnet.id
config/wagmi.config.ts
import { cookieStorage, createStorage, http } from '@wagmi/core'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { mainnet, arbitrum } from '@reown/appkit/networks'
import { vTestnet } from '@/app/tenderly.config'
 
// Get projectId from https://cloud.reown.com
export const projectId = process.env.NEXT_PUBLIC_PROJECT_ID
 
if (!projectId) {
  throw new Error('Project ID is not defined')
}
 
export const networks = [mainnet, arbitrum, vTestnet]
 
//Set up the Wagmi Adapter (Config)
export const wagmiAdapter = new WagmiAdapter({
  storage: createStorage({
    storage: cookieStorage
  }),
  ssr: true,
  transports: {
    [vTestnet.id]: http(process.env.TENDERLY_VIRTUAL_TESTNET_RPC!)
  },
  networks,
  projectId
})
 
export const config = wagmiAdapter.wagmiConfig

Create a ContextProvider

Now, inside your context/index.tsx file, you also need to import vTestnet and pass it as one of the supported networks within the createAppKit function, as shown below.

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.

'use client'
 
import { wagmiAdapter, projectId } from '@/config'
import { createAppKit } from '@reown/appkit/react'
import { mainnet, arbitrum } from '@reown/appkit/networks'
import { vTestnet } from '@/app/tenderly.config'
 
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import React, { type ReactNode } from 'react'
import { cookieToInitialState, WagmiProvider, type Config } from 'wagmi'
 
// Set up queryClient
const queryClient = new QueryClient()
 
if (!projectId) {
  throw new Error('Project ID is not defined')
}
 
// Set up metadata
const metadata = { //this is optional
  name: "appkit-example",
  description: "AppKit Example - EVM",
  url: "https://exampleapp.com", // origin must match your domain & subdomain
  icons: ["https://avatars.githubusercontent.com/u/37784886"]
}
 
// Create the modal
const modal = createAppKit({
  adapters: [wagmiAdapter],
  projectId,
  networks: [mainnet, arbitrum, vTestnet],
  metadata: metadata,
  features: {
    analytics: true, // Optional - defaults to your Cloud configuration
  }
})
 
function ContextProvider({ children, cookies }: { children: ReactNode; cookies: string | null }) {
  const initialState = cookieToInitialState(wagmiAdapter.wagmiConfig as Config, cookies)
 
  return (
    <WagmiProvider config={wagmiAdapter.wagmiConfig as Config} initialState={initialState}>
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    </WagmiProvider>
  )
}
 
export default ContextProvider

Use the ContextProvider

Wrap your dapp body (app/layout.tsx) in a ContextProvider 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 ContextProvider from '@/context';
 
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}>
      <ContextProvider>
        {children}
      </ContextProvider>
    </body>
    </html>
  );
}

Run the dapp

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