Get Started
Get a Web3 project running end-to-end: wallet, viem, a testnet, a tiny contract, deploy + read + write.
Web3 — getting started
EXAMPLE
# ===== 1. Tools =====
# Wallet: MetaMask / Rabby (browser extensions)
# Library: viem (TypeScript-first) or ethers.js
# Test chain: Anvil (Foundry) or Hardhat node
# Contracts: Solidity via Foundry (forge) or Hardhat
# ===== 2. Install Foundry =====
curl -L https://foundry.paradigm.xyz | bash
foundryup
forge --version
anvil --version
# ===== 3. New project =====
forge init my-app
cd my-app
# src/Counter.sol
# pragma solidity ^0.8.20;
# contract Counter {
# uint256 public n;
# function bump() public { n += 1; }
# }
forge build
forge test # runs the demo tests
# ===== 4. Local chain =====
anvil & # starts a local chain on http://127.0.0.1:8545
# anvil prints accounts + private keys; use one for testing.
# ===== 5. Deploy locally =====
forge script script/Counter.s.sol --rpc-url http://127.0.0.1:8545 --broadcast \
--private-key 0xYOUR_TEST_KEY
# Or the simple way:
forge create src/Counter.sol:Counter --rpc-url http://127.0.0.1:8545 --private-key 0xYOUR_TEST_KEY
# Note the deployed address printed.
# ===== 6. Frontend with Vite + viem =====
npm create vite@latest dapp -- --template react-ts
cd dapp
npm install viem
# src/main.tsx
import { createPublicClient, createWalletClient, custom, http, getContract } from 'viem';
import { foundry } from 'viem/chains';
const ABI = [{ name: 'bump', type: 'function', stateMutability: 'nonpayable', inputs: [], outputs: [] },
{ name: 'n', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] }];
const pub = createPublicClient({ chain: foundry, transport: http() });
const counter = getContract({ address: '0xDEPLOYED', abi: ABI, client: { public: pub } });
const n = await counter.read.n();
console.log('count', n);
# Write via wallet:
async function bumpFromWallet() {
if (!window.ethereum) throw new Error('No wallet');
const wallet = createWalletClient({ chain: foundry, transport: custom(window.ethereum) });
const [address] = await wallet.requestAddresses();
const hash = await wallet.writeContract({ address: '0xDEPLOYED', abi: ABI, functionName: 'bump', account: address });
console.log('tx', hash);
}
# ===== 7. Connect MetaMask to Anvil =====
# In MetaMask: Networks -> Add a network
# Name: Anvil
# RPC: http://127.0.0.1:8545
# Chain ID: 31337
# Import a private key from the anvil output.
# ===== 8. Move to a testnet =====
# Sepolia (ETH), Optimism Sepolia, Arbitrum Sepolia.
# Get test ETH from a faucet.
# Use --rpc-url <sepolia_rpc> to deploy; verify on Etherscan with --verify.
# forge create ... --rpc-url $SEPOLIA --private-key $KEY --verify --etherscan-api-key $ETHERSCAN_KEY
# ===== 9. Don't ship to mainnet on day one =====
# - Test thoroughly on a public testnet
# - Get an audit for any contract holding real funds
# - Add a pause function + admin timelock
# - Document the contract address + ABI
# ===== Patterns to internalise =====
# - Anvil + Foundry for local dev (fast, modern, well-documented)
# - viem + TypeScript at the frontend
# - Read via public client; write via wallet client
# - Pin chain + addresses in config; do not hardcode anywhere else
# ===== Pitfalls =====
# - Mainnet keys in local .env files
# - Sending real ETH to a Sepolia contract address (different chain)
# - Hardcoding addresses across environments
# - Trusting your own contract before audits + testnet time
Why it matters
Foundry for contracts + viem for the frontend + Anvil for the local chain is the fastest path from idea to working dApp. Read via the public client, write via the wallet, test on Sepolia before mainnet, and ship with timelocks + pause + audits when real money is involved.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Foundry — fast, Rust-built toolchain curl -L https://foundry.paradigm.xyz | bash foundryup forge init myproject && cd myproject forge testTry it Yourself »
Exercise
Foundry CLI to create a new project.
forge
myproject
Four letters.
Discussion
Loading…