0xsardius/onchain-typescript-skills
Overview
This skill provides TypeScript patterns and best practices for low-level EVM interactions using Viem. It focuses on correct client setup, ABI type safety, read/write contract flows, event watching, multicall batching, and robust error handling. Use it when building Node scripts, CLIs, or backend services that interact directly with Ethereum or other EVM chains.
How this skill works
The skill documents concrete Viem calls and code patterns: createPublicClient/createWalletClient for read and write flows, use as const on ABIs for full type inference, simulate writes before executing, and watch contract events with cleanup. It also shows multicall batching for efficient reads and demonstrates error handling using Viem's error classes. Examples use BigInt for amounts and recommend letting Viem estimate gas.
When to use it
- Backend services or cron jobs that read on-chain state or submit transactions
- CLI tools and Node scripts for deployments, tooling, or on-chain maintenance
- Signing and sending transactions server-side with private key accounts
- Monitoring contracts and reacting to events via watchContractEvent
- Batching many read calls efficiently with multicall
Best practices
- Always add
as constto ABIs to enable full TypeScript inference - Simulate contract writes with publicClient.simulateContract before sending
- Use BigInt (e.g., 1000000n) for uint256 values, not Number
- Let Viem estimate gas or call publicClient.estimateGas instead of hardcoding
- Await transaction confirmation with publicClient.waitForTransactionReceipt
- Clean up event watchers by calling the returned unwatch function
Example use cases
- Read token balances and totalSupply across multiple contracts using multicall
- Simulate and write ERC-20 transfer transactions from a server wallet account
- Watch Transfer events to update an off-chain indexer or alerting system
- Create a CLI for contract maintenance that signs transactions with a private key
- Implement robust error parsing to surface revert reasons to operators
FAQ
as const preserves literal types in TypeScript so Viem can infer function names, argument types, and return types for fully typed read/write calls.
Should I simulate every write?
Yes. simulateContract catches common errors and returns a request object you can pass to walletClient.writeContract, reducing failed transactions.