viem-integration

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

viem Integration

viem 集成

Integrate EVM blockchains using viem for TypeScript/JavaScript applications.
为TypeScript/JavaScript应用使用viem集成EVM区块链。

Quick Decision Guide

快速决策指南

Building...Use This
Node.js script/backendviem with http transport
React/Next.js frontendwagmi hooks (built on viem)
Real-time event monitoringviem with webSocket transport
Browser wallet integrationwagmi or viem custom transport
开发场景推荐方案
Node.js脚本/后端搭配http传输的viem
React/Next.js前端wagmi钩子(基于viem构建)
实时事件监控搭配webSocket传输的viem
浏览器钱包集成wagmi或viem自定义传输

Installation

安装

bash
undefined
bash
undefined

Core library

Core library

npm install viem
npm install viem

For React apps, also install wagmi

For React apps, also install wagmi

npm install wagmi viem @tanstack/react-query
undefined
npm install wagmi viem @tanstack/react-query
undefined

Core Concepts

核心概念

Clients

客户端

viem uses two client types:
ClientPurposeExample Use
PublicClientRead-only operationsGet balances, read contracts, fetch logs
WalletClientWrite operationsSend transactions, sign messages
viem使用两种客户端类型:
客户端类型用途使用示例
PublicClient只读操作查询余额、读取合约、获取日志
WalletClient写入操作发送交易、签名消息

Transports

传输方式

TransportUse Case
http()
Standard RPC calls (most common)
webSocket()
Real-time event subscriptions
custom()
Browser wallets (window.ethereum)
传输方式适用场景
http()
标准RPC调用(最常用)
webSocket()
实时事件订阅
custom()
浏览器钱包(window.ethereum)

Chains

viem includes 50+ chain definitions. Import from
viem/chains
:
typescript
import { mainnet, arbitrum, optimism, base, polygon } from 'viem/chains';

viem包含50+条链的定义,可从
viem/chains
导入:
typescript
import { mainnet, arbitrum, optimism, base, polygon } from 'viem/chains';

Quick Start Examples

快速入门示例

Read Balance

查询余额

typescript
import { createPublicClient, http, formatEther } from 'viem';
import { mainnet } from 'viem/chains';

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const balance = await client.getBalance({
  address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
});

console.log(`Balance: ${formatEther(balance)} ETH`);
typescript
import { createPublicClient, http, formatEther } from 'viem';
import { mainnet } from 'viem/chains';

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const balance = await client.getBalance({
  address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
});

console.log(`Balance: ${formatEther(balance)} ETH`);

Read Contract

读取合约

typescript
import { createPublicClient, http, parseAbi } from 'viem';
import { mainnet } from 'viem/chains';

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const abi = parseAbi([
  'function balanceOf(address) view returns (uint256)',
  'function decimals() view returns (uint8)',
]);

const balance = await client.readContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  abi,
  functionName: 'balanceOf',
  args: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'],
});
typescript
import { createPublicClient, http, parseAbi } from 'viem';
import { mainnet } from 'viem/chains';

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const abi = parseAbi([
  'function balanceOf(address) view returns (uint256)',
  'function decimals() view returns (uint8)',
]);

const balance = await client.readContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  abi,
  functionName: 'balanceOf',
  args: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'],
});

Send Transaction

发送交易

typescript
import { createWalletClient, http, parseEther } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

const client = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

const hash = await client.sendTransaction({
  to: '0x...',
  value: parseEther('0.1'),
});

console.log(`Transaction hash: ${hash}`);
typescript
import { createWalletClient, http, parseEther } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

const client = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

const hash = await client.sendTransaction({
  to: '0x...',
  value: parseEther('0.1'),
});

console.log(`Transaction hash: ${hash}`);

Write to Contract

写入合约

typescript
import { createWalletClient, createPublicClient, http, parseAbi, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const abi = parseAbi(['function transfer(address to, uint256 amount) returns (bool)']);

// Simulate first to catch errors
const { request } = await publicClient.simulateContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  abi,
  functionName: 'transfer',
  args: ['0x...', parseUnits('100', 6)],
  account,
});

// Execute the transaction
const hash = await walletClient.writeContract(request);

// Wait for confirmation
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log(`Confirmed in block ${receipt.blockNumber}`);

typescript
import { createWalletClient, createPublicClient, http, parseAbi, parseUnits } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const abi = parseAbi(['function transfer(address to, uint256 amount) returns (bool)']);

// 先模拟以捕获错误
const { request } = await publicClient.simulateContract({
  address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
  abi,
  functionName: 'transfer',
  args: ['0x...', parseUnits('100', 6)],
  account,
});

// 执行交易
const hash = await walletClient.writeContract(request);

// 等待确认
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log(`已在区块 ${receipt.blockNumber} 中确认`);

Reference Documentation

参考文档

For deeper coverage of specific topics:
TopicReference File
Client setup, transports, chainsClients & Transports
Reading blockchain dataReading Data
Sending transactionsWriting Transactions
Private keys, HD walletsAccounts & Keys
ABI handling, multicallContract Patterns
React/wagmi hooksWagmi React

如需深入了解特定主题:
主题参考文档
客户端配置、传输方式、链客户端与传输方式
读取区块链数据数据读取
发送交易交易写入
私钥、HD钱包账户与密钥
ABI处理、多调用合约模式
React/wagmi钩子Wagmi React

Related Plugins

相关插件

Once you're comfortable with viem basics, the uniswap-trading plugin provides comprehensive Uniswap swap integration:
  • Uniswap Trading API integration
  • Universal Router SDK usage
  • Token swap implementations
Install it with:
claude plugin add @uniswap/uniswap-trading

当你熟悉viem基础后,uniswap-trading插件可提供全面的Uniswap兑换集成:
  • Uniswap Trading API集成
  • Universal Router SDK使用
  • 代币兑换实现
安装命令:
claude plugin add @uniswap/uniswap-trading

Common Utilities

常用工具函数

Unit Conversion

单位转换

typescript
import { parseEther, formatEther, parseUnits, formatUnits } from 'viem';

// ETH
parseEther('1.5'); // 1500000000000000000n (wei)
formatEther(1500000000000000000n); // "1.5"

// Tokens (e.g., USDC with 6 decimals)
parseUnits('100', 6); // 100000000n
formatUnits(100000000n, 6); // "100"
typescript
import { parseEther, formatEther, parseUnits, formatUnits } from 'viem';

// ETH
parseEther('1.5'); // 1500000000000000000n (wei)
formatEther(1500000000000000000n); // "1.5"

// 代币(如USDC,6位小数)
parseUnits('100', 6); // 100000000n
formatUnits(100000000n, 6); // "100"

Address Utilities

地址工具函数

typescript
import { getAddress, isAddress } from 'viem';

isAddress('0x...'); // true/false
getAddress('0x...'); // checksummed address
typescript
import { getAddress, isAddress } from 'viem';

isAddress('0x...'); // true/false
getAddress('0x...'); // 校验后的地址

Hashing

哈希计算

typescript
import { keccak256, toHex } from 'viem';

keccak256(toHex('hello')); // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8

typescript
import { keccak256, toHex } from 'viem';

keccak256(toHex('hello')); // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8

Error Handling

错误处理

viem throws typed errors that can be caught and handled:
typescript
import { ContractFunctionExecutionError, InsufficientFundsError } from 'viem'

try {
  await client.writeContract(...)
} catch (error) {
  if (error instanceof ContractFunctionExecutionError) {
    console.error('Contract call failed:', error.shortMessage)
  }
  if (error instanceof InsufficientFundsError) {
    console.error('Not enough ETH for gas')
  }
}

viem会抛出类型化错误,可捕获并处理:
typescript
import { ContractFunctionExecutionError, InsufficientFundsError } from 'viem'

try {
  await client.writeContract(...)
} catch (error) {
  if (error instanceof ContractFunctionExecutionError) {
    console.error('合约调用失败:', error.shortMessage)
  }
  if (error instanceof InsufficientFundsError) {
    console.error('Gas费用不足')
  }
}

Resources

资源