viem-integration by uniswap/uniswap-ai
npx skills add https://github.com/uniswap/uniswap-ai --skill viem-integration使用 viem 为 TypeScript/JavaScript 应用程序集成 EVM 区块链。
| 正在构建... | 使用此方案 |
|---|---|
| Node.js 脚本/后端 | viem 配合 http 传输 |
| React/Next.js 前端 | wagmi hooks(基于 viem 构建) |
| 实时事件监控 | viem 配合 webSocket 传输 |
| 浏览器钱包集成 | wagmi 或 viem 自定义传输 |
# 核心库
npm install viem
# 对于 React 应用,还需安装 wagmi
npm install wagmi viem @tanstack/react-query
viem 使用两种客户端类型:
| 客户端 | 用途 | 示例 |
|---|---|---|
| PublicClient | 只读操作 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 获取余额、读取合约、获取日志 |
| WalletClient | 写入操作 | 发送交易、签名消息 |
| 传输方式 | 使用场景 |
|---|---|
http() | 标准 RPC 调用(最常见) |
webSocket() | 实时事件订阅 |
custom() | 浏览器钱包(window.ethereum) |
viem 包含 50+ 条链的定义。从 viem/chains 导入:
import { mainnet, arbitrum, optimism, base, polygon } from 'viem/chains';
在将 任何 用户提供的值插入到生成的 TypeScript 代码之前:
^0x[a-fA-F0-9]{40}$ — 使用 viem 的 isAddress() 进行验证process.env.PRIVATE_KEY 并进行运行时验证https:// 或 wss:// 协议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`);
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'],
});
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}`);
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(`Confirmed in block ${receipt.blockNumber}`);
如需深入了解特定主题:
熟悉 viem 基础后,uniswap-trading 插件提供了全面的 Uniswap 交易集成:
使用以下命令安装:claude plugin add @uniswap/uniswap-trading
import { parseEther, formatEther, parseUnits, formatUnits } from 'viem';
// ETH
parseEther('1.5'); // 1500000000000000000n (wei)
formatEther(1500000000000000000n); // "1.5"
// 代币(例如,6位小数的 USDC)
parseUnits('100', 6); // 100000000n
formatUnits(100000000n, 6); // "100"
import { getAddress, isAddress } from 'viem';
isAddress('0x...'); // true/false
getAddress('0x...'); // 校验和地址
import { keccak256, toHex } from 'viem';
keccak256(toHex('hello')); // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
viem 会抛出类型化的错误,可以捕获并处理:
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')
}
}
每周安装量
308
仓库
GitHub 星标数
185
首次出现
2026年2月12日
安全审计
安装于
codex293
opencode292
gemini-cli287
github-copilot285
cursor283
kimi-cli282
Integrate EVM blockchains using viem for TypeScript/JavaScript applications.
| Building... | Use This |
|---|---|
| Node.js script/backend | viem with http transport |
| React/Next.js frontend | wagmi hooks (built on viem) |
| Real-time event monitoring | viem with webSocket transport |
| Browser wallet integration | wagmi or viem custom transport |
# Core library
npm install viem
# For React apps, also install wagmi
npm install wagmi viem @tanstack/react-query
viem uses two client types:
| Client | Purpose | Example Use |
|---|---|---|
| PublicClient | Read-only operations | Get balances, read contracts, fetch logs |
| WalletClient | Write operations | Send transactions, sign messages |
| Transport | Use Case |
|---|---|
http() | Standard RPC calls (most common) |
webSocket() | Real-time event subscriptions |
custom() | Browser wallets (window.ethereum) |
viem includes 50+ chain definitions. Import from viem/chains:
import { mainnet, arbitrum, optimism, base, polygon } from 'viem/chains';
Before interpolating ANY user-provided value into generated TypeScript code:
^0x[a-fA-F0-9]{40}$ — use viem's isAddress() for validationprocess.env.PRIVATE_KEY with runtime validationhttps:// or wss:// protocols onlyimport { 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`);
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'],
});
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}`);
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}`);
For deeper coverage of specific topics:
| Topic | Reference File |
|---|---|
| Client setup, transports, chains | Clients & Transports |
| Reading blockchain data | Reading Data |
| Sending transactions | Writing Transactions |
| Private keys, HD wallets | Accounts & Keys |
| ABI handling, multicall | Contract Patterns |
| React/wagmi hooks | Wagmi React |
Once you're comfortable with viem basics, the uniswap-trading plugin provides comprehensive Uniswap swap integration:
Install it with: claude plugin add @uniswap/uniswap-trading
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"
import { getAddress, isAddress } from 'viem';
isAddress('0x...'); // true/false
getAddress('0x...'); // checksummed address
import { keccak256, toHex } from 'viem';
keccak256(toHex('hello')); // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
viem throws typed errors that can be caught and handled:
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')
}
}
Weekly Installs
308
Repository
GitHub Stars
185
First Seen
Feb 12, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
codex293
opencode292
gemini-cli287
github-copilot285
cursor283
kimi-cli282
Solidity 智能合约安全指南:防范重入攻击、溢出漏洞与访问控制
5,700 周安装