install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/TerminalSkills/skills/viem" ~/.claude/skills/comeonoliver-skillshub-viem && rm -rf "$T"
manifest:
skills/TerminalSkills/skills/viem/SKILL.mdsource content
Viem — Type-Safe Ethereum Interactions for TypeScript
You are an expert in Viem, the TypeScript interface for Ethereum that provides low-level, type-safe primitives for interacting with the blockchain. You help developers build dApps, scripts, and backends that read blockchain data, send transactions, interact with smart contracts, and handle wallet connections — with full type inference from ABIs, tree-shakeable modules, and zero dependencies beyond noble cryptography.
Core Capabilities
Client Setup
import { createPublicClient, createWalletClient, http, parseEther } from "viem"; import { mainnet, sepolia } from "viem/chains"; import { privateKeyToAccount } from "viem/accounts"; // Public client: read blockchain data (no wallet needed) const publicClient = createPublicClient({ chain: mainnet, transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"), }); // Wallet client: sign and send transactions const account = privateKeyToAccount("0x..."); const walletClient = createWalletClient({ account, chain: mainnet, transport: http("https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"), });
Read Blockchain Data
// Get ETH balance const balance = await publicClient.getBalance({ address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", // vitalik.eth }); console.log(`Balance: ${formatEther(balance)} ETH`); // Get block const block = await publicClient.getBlock({ blockTag: "latest" }); console.log(`Block #${block.number}: ${block.transactions.length} txs`); // Read contract (type-safe from ABI) const erc20Abi = [ { name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ name: "balance", type: "uint256" }], }, ] as const; const usdcBalance = await publicClient.readContract({ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi: erc20Abi, functionName: "balanceOf", // Autocompleted from ABI args: ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"], }); // Return type automatically inferred as bigint
Write Transactions
// Send ETH const hash = await walletClient.sendTransaction({ to: "0x...", value: parseEther("0.1"), }); const receipt = await publicClient.waitForTransactionReceipt({ hash }); // Write to contract const hash = await walletClient.writeContract({ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi: erc20Abi, functionName: "transfer", args: ["0xrecipient...", 1000000n], // 1 USDC (6 decimals) });
Event Watching
// Watch for ERC-20 Transfer events in real-time const unwatch = publicClient.watchContractEvent({ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi: erc20Abi, eventName: "Transfer", onLogs: (logs) => { for (const log of logs) { console.log(`Transfer: ${log.args.from} → ${log.args.to}: ${log.args.value}`); } }, }); // Get historical events const transferLogs = await publicClient.getContractEvents({ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", abi: erc20Abi, eventName: "Transfer", fromBlock: 18000000n, toBlock: 18001000n, });
ENS Resolution
// ENS name → address const address = await publicClient.getEnsAddress({ name: "vitalik.eth" }); // Address → ENS name const name = await publicClient.getEnsName({ address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", });
Installation
npm install viem
Best Practices
- ABI as const — Declare ABIs with
for full type inference on function names, args, and return typesas const - Separate clients — Use
for reads (free),publicClient
for writes (costs gas)walletClient - waitForTransactionReceipt — Always wait for receipt after sending; don't assume success from hash alone
- parseEther/formatEther — Use viem's utilities for ETH conversions; never do manual decimal math with bigint
- Chain configuration — Import chains from
; includes RPC URLs, block explorer, native currencyviem/chains - Error handling — Viem throws typed errors; catch
for contract revertsContractFunctionRevertedError - Batch requests — Use
to batch multiple contract reads into one RPC call; reduces latencymulticall - Works with wagmi — Viem is the core of wagmi (React hooks for Ethereum); same patterns, same types