Viem: TypeScript Interface for Ethereum
Viem is a comprehensive, TypeScript-first interface for interacting with the Ethereum blockchain, designed to simplify dApp development. Currently stable at version 2.48.1, it exhibits a rapid release cadence with frequent patch updates and minor feature additions, reflecting active development. It provides robust abstractions over the JSON-RPC API, first-class APIs for smart contract interaction, and native BigInt support for handling large numbers without external libraries like BigNumber.js. Key differentiators include its deep integration with TypeScript for type inference from ABIs and EIP-712 typed data, strong alignment with official Ethereum terminology, and out-of-the-box support for local development environments such as Anvil, Hardhat, and Ganache. Viem aims to be a lightweight and highly type-safe alternative to other Ethereum libraries, focusing on developer experience and correctness through its strong type system.
Common errors
-
ERR_REQUIRE_ESM: require() of ES Module ... not supported.
cause Attempting to `require()` an ESM-only Viem module in a CommonJS environment.fixMigrate your project to use ES Modules (set `"type": "module"` in `package.json` and use `import` statements) or use a bundler that correctly handles ESM-to-CJS transpilation. -
Cannot read properties of undefined (reading 'chainId')
cause The client was initialized without a `chain` property or an invalid chain object was provided.fixEnsure `createPublicClient` or similar client creation functions are called with a valid `chain` object, e.g., `chain: mainnet` imported from `viem/chains`. -
A BigInt can not be serialized as JSON.
cause Attempting to `JSON.stringify` an object containing a native JavaScript BigInt without a custom replacer. Viem uses native BigInts for large number handling.fixWhen serializing data that may contain BigInts (e.g., for logging or API responses), provide a custom replacer function to `JSON.stringify` that converts BigInts to strings: `JSON.stringify(obj, (key, value) => typeof value === 'bigint' ? value.toString() : value)`. -
Error: Version mismatch, found 'typescript@X.Y.Z', expected 'typescript@>=5.0.4'
cause Your project's installed TypeScript version does not meet Viem's peer dependency requirement.fixInstall a compatible TypeScript version: `npm install typescript@^5.0.4 -D` or `yarn add typescript@^5.0.4 -D`.
Warnings
- breaking Viem is an ESM-first library. Projects using CommonJS (require()) may encounter compatibility issues, especially with older Node.js versions or specific bundler configurations.
- gotcha The `typescript` peer dependency requires version `>=5.0.4`. Using an older version may lead to `npm ERESOLVE` warnings or compilation errors due to incompatible type definitions or language features.
- deprecated In `viem/tempo`, `withFeePayer` has been deprecated in favor of `withRelay`. This change impacts how transaction relaying is configured and used.
- gotcha While Viem includes internal retry logic for RPC calls, aggressive rate limiting from some providers (e.g., Alchemy returning `HTTP 200` with `{ code: 429 }` in JSON-RPC body) can still cause failures, especially in batch mode.
Install
-
npm install viem -
yarn add viem -
pnpm add viem
Imports
- createPublicClient, http
const { createPublicClient, http } = require('viem');import { createPublicClient, http } from 'viem'; - mainnet
const { mainnet } = require('viem/chains');import { mainnet } from 'viem/chains'; - parseAbi
import { parseAbi } from 'viem'; - Address, Hash, Hex
import type { Address, Hash, Hex } from 'viem';
Quickstart
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const client = createPublicClient({
chain: mainnet,
transport: http(process.env.ETHEREUM_RPC_URL ?? 'https://rpc.ankr.com/eth')
});
async function getBlockNumber() {
try {
const blockNumber = await client.getBlockNumber();
console.log(`Current block number: ${blockNumber}`);
return blockNumber;
} catch (error) {
console.error('Failed to get block number:', error);
throw error;
}
}
getBlockNumber();