Skip to main content
In this guide you talk to the Counter contract you deployed in the quickstart, first from a Node.js script and then from a web page where anyone with a wallet can increment it.
Everything on this page uses testnet (chain 968). Get free test tokens from the faucet.

What you’ll build

  • A script that reads the counter and sends an increment transaction with viem.
  • A React page built with wagmi that connects a browser wallet, shows the counter and has an Increment button.
BOT Chain is not in viem’s built-in chain list, so you’ll define it yourself with defineChain. That way you see every value your app depends on. In your own projects you can import botChainTestnet from the Uzo SDK instead.

Prerequisites

  • A deployed Counter contract and its address, from the quickstart.
  • The uzo-dev wallet from the quickstart, with some tBOT in it.
  • Node.js 20.6 or later. This guide was tested with Node.js 24, viem 2.57 and wagmi 3.7.
  • For part 2, a browser wallet such as MetaMask with BOT Chain testnet added. See Connect a wallet.

Part 1: a viem script

1

Create the project

2

Define the chain

This tells viem everything it needs to know about BOT Chain testnet.
chain.js
The multicall3 address is the one BOT Chain deploys on both networks. Viem uses it to batch reads. The usual Multicall3 address used on other chains is not deployed on testnet, so don’t skip this field.
3

Add the contract ABI

The ABI tells viem which functions the contract has. Foundry wrote the full ABI to out/Counter.sol/Counter.json in your quickstart project. For this guide you only need these three functions:
counter.js
4

Set your environment variables

The script reads your contract address and private key from a .env file, so they never appear in your code.Export the private key of your uzo-dev testnet wallet. Cast asks for the keystore password:
Create a file named .env and paste in your values:
.env
Only ever put a testnet key in a .env file. Add .env to your .gitignore before your first commit, so the key never reaches GitHub:
5

Read the counter

A public client reads from the chain. Reading is free and doesn’t need a wallet.
read.js
Run it. The --env-file flag loads your .env file:
Output
Your block number will be higher. The n means the value is a JavaScript BigInt.
6

Send a transaction

A wallet client signs and sends transactions with your key.
write.js
The script prints a BOTScan link, waits about a second for the block, then prints the new value:
Output

Part 2: a wagmi page

Now give the contract a user interface. Visitors connect their own wallet, so this app needs no private key.
1

Create a React app

2

Configure wagmi

This file defines the chain (the same values as chain.js) and creates the wagmi config. The injected connector works with MetaMask and other browser wallets.
src/wagmi.ts
3

Add the contract

Vite exposes variables that start with VITE_ to your frontend. A contract address is public, so it’s safe here.
.env.local
src/counter.ts
as const lets TypeScript check your function names and argument types.
4

Wrap the app in providers

Replace src/main.tsx:
src/main.tsx
5

Build the page

Replace src/App.tsx:
src/App.tsx
Most browser wallets announce themselves to the page, so wagmi lists each one by name with its icon. If you have two wallets installed, you see two buttons. The generic injected connector from wagmi.ts only shows, as Connect wallet, when no wallet announces itself.
The counter page before connecting, showing the counter value 2 and two buttons, Connect Phantom and Connect MetaMask
Replace src/App.css to style the page:
src/App.css
The page reads the counter through the public RPC, so it shows the value before anyone connects. Writing needs a connected wallet on chain 968.
6

Run it

Open the local URL that Vite prints, usually http://localhost:5173.

Verify it worked

The counter page connected to a wallet on BOT Chain testnet, showing the counter value 3, the Increment button and a View transaction on BOTScan link
  1. The page shows the same counter value that read.js printed.
  2. Click Connect with your wallet’s name, then approve in your wallet.
  3. Click Increment and confirm. After about a second the value goes up by one.
  4. The View transaction on BOTScan link opens your transaction.

Troubleshooting

The script couldn’t find COUNTER_ADDRESS. Run it with node --env-file=.env, and check that .env is in the folder you’re running from. In the React app, restart npm run dev after creating .env.local, and check that the name starts with VITE_.
There is no Counter contract at that address on testnet. Check that you copied the Deployed to address from the quickstart, not your wallet address or the transaction hash.
PRIVATE_KEY must be 64 hex characters with a 0x prefix. Copy it again from cast wallet decrypt-keystore uzo-dev.
That button is the generic injected connector, which needs a browser wallet extension. Without one, the button still appears but nothing happens when you click it. Install MetaMask or another EVM wallet and reload the page.
Click Switch to BOT Chain testnet. If your wallet doesn’t know chain 968 yet, add it first using the values in Connect a wallet.

Next steps

wagmi setup

Configure wagmi for both networks in a real project.

Read events without getLogs

Show contract history on BOT Chain.

Send transactions

Gas, errors and confirmations in more depth.

Networks

Every chain value in one table.
Last modified on October 3, 2026