Viem
Overview
Viem is a TypeScript interface for Ethereum that provides low-level stateless primitives for interacting with the blockchain. It focuses on developer experience, stability, bundle size, and performance.
Key features:
-
Automatic type safety and inference
-
Tree-shakable lightweight modules
-
Optimized encoding/parsing
-
Composable APIs
Core Concepts
Concept Description
Clients PublicClient , WalletClient , TestClient
- entry points
Transports Connection layer (http , webSocket , custom )
Actions Operations like getBlockNumber , sendTransaction
Chains Chain configurations (mainnet , sepolia , arbitrum , etc.)
Constants
Viem exports useful constants for common values:
import { maxUint256, maxUint128, maxInt256, zeroAddress, zeroHash } from "viem";
// Max values for uint types maxUint256; // 2n ** 256n - 1n maxUint128; // 2n ** 128n - 1n
// Zero values zeroAddress; // 0x0000000000000000000000000000000000000000 zeroHash; // 0x0000000000000000000000000000000000000000000000000000000000000000
Utilities
Unit Conversion
Convert between wei and human-readable values:
import { parseEther, formatEther, parseUnits, formatUnits } from "viem";
// ETH <-> Wei (18 decimals) parseEther("1"); // 1000000000000000000n formatEther(1000000000000000000n); // "1"
// Custom decimals (e.g., USDC with 6 decimals) parseUnits("100", 6); // 100000000n formatUnits(100000000n, 6); // "100"
ABI Utilities
Parse human-readable ABIs:
import { parseAbi, parseAbiItem } from "viem";
const abi = parseAbi([ "function balanceOf(address owner) view returns (uint256)", "function transfer(address to, uint256 amount) returns (bool)", "event Transfer(address indexed from, address indexed to, uint256 amount)", ]);
const item = parseAbiItem("function name() view returns (string)");
Address Utilities
import { getAddress, isAddress, isAddressEqual } from "viem";
// Checksum address getAddress("0xabc..."); // "0xAbc..." (checksummed)
// Validation isAddress("0x..."); // true/false isAddressEqual("0xAbc...", "0xabc..."); // true (case-insensitive)
Clients
Public Client (Read Operations)
For querying blockchain state:
import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains";
const publicClient = createPublicClient({ chain: mainnet, transport: http(), // or http("https://eth-mainnet.g.alchemy.com/v2/...") });
// Read operations const blockNumber = await publicClient.getBlockNumber(); const balance = await publicClient.getBalance({ address: "0x..." }); const block = await publicClient.getBlock();
Wallet Client (Write Operations)
For signing and sending transactions:
import { createWalletClient, http } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains";
const account = privateKeyToAccount("0x...");
const walletClient = createWalletClient({ account, chain: mainnet, transport: http(), });
// Send transaction const hash = await walletClient.sendTransaction({ to: "0x...", value: parseEther("0.1"), });
Browser Wallet Client
For browser environments with injected wallets:
import "viem/window"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains";
const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), });
// Request accounts const [address] = await walletClient.requestAddresses();
Extending Clients
Combine capabilities using .extend() :
import { createWalletClient, http, publicActions } from "viem"; import { mainnet } from "viem/chains";
const client = createWalletClient({ chain: mainnet, transport: http(), }).extend(publicActions);
// Now supports both wallet and public actions const balance = await client.getBalance({ address: "0x..." }); const hash = await client.sendTransaction({ to: "0x...", value: 1n });
Contract Interactions
Reading from Contracts
import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains";
const publicClient = createPublicClient({ chain: mainnet, transport: http(), });
const abi = [ { inputs: [{ name: "owner", type: "address" }], name: "balanceOf", outputs: [{ name: "", type: "uint256" }], stateMutability: "view", type: "function", }, ] as const;
const balance = await publicClient.readContract({ address: "0x...", // Contract address abi, functionName: "balanceOf", args: ["0x..."], // Owner address });
Writing to Contracts
const hash = await walletClient.writeContract({ address: "0x...", abi, functionName: "transfer", args: ["0x...", parseUnits("100", 18)], });
Simulating Before Writing
Simulate a transaction before sending:
const { request } = await publicClient.simulateContract({ address: "0x...", abi, functionName: "transfer", args: ["0x...", parseUnits("100", 18)], account: "0x...", });
const hash = await walletClient.writeContract(request);
Account Types
Local Accounts
For server-side or controlled environments:
import { privateKeyToAccount, mnemonicToAccount } from "viem/accounts";
// From private key const account = privateKeyToAccount("0x...");
// From mnemonic const account = mnemonicToAccount("legal winner thank year wave sausage ...");
JSON-RPC Accounts
For browser wallets:
import "viem/window";
const [account] = await window.ethereum!.request({ method: "eth_requestAccounts", });
Chain Configuration
Built-in Chains
import { mainnet, sepolia, arbitrum, optimism, polygon, base } from "viem/chains";
const client = createPublicClient({ chain: arbitrum, transport: http(), });
Custom Chains
import { defineChain } from "viem";
const customChain = defineChain({ id: 123456, name: "My Chain", nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 }, rpcUrls: { default: { http: ["https://rpc.mychain.com"] }, }, blockExplorers: { default: { name: "Explorer", url: "https://explorer.mychain.com" }, }, });
Documentation
This skill provides a reference for common operations. For comprehensive documentation, fetch the full viem docs using context7 MCP:
Library ID: /wevm/viem
Use context7 to query specific topics:
-
clients
-
Client types and configuration
-
actions
-
Available actions (read, write, wallet)
-
accounts
-
Local and JSON-RPC accounts
-
contract
-
Contract interactions (readContract , writeContract )
-
abi
-
ABI encoding/decoding utilities
-
chains
-
Supported chains and custom chain configuration
Fetching Documentation
To fetch viem documentation for a specific topic:
-
Resolve the library ID with mcp__context7__resolve-library-id (or use /wevm/viem directly)
-
Call mcp__context7__get-library-docs with the topic parameter
Example topics: "getting started" , "wallet client" , "send transaction" , "read contract" .