mcpField
V
viem-integration

viem-integration

github.com/uniswap开发2361.7k 次安装2 天前更新
代码仓库

关于 viem-integration

用于在 TypeScript 和 JavaScript 应用中通过 viem 集成 EVM 区块链的技能,介绍客户端与传输方式选择、链上读写,以及相关 wagmi 用法。

主要功能

  1. 01配置 PublicClient 和 WalletClient
  2. 02HTTP、WebSocket 与自定义传输
  3. 03链和账户管理
  4. 04读取与写入合约
  5. 05地址、单位和错误处理工具

适用场景

  1. 01读取余额和合约数据
  2. 02发送交易或签署消息
  3. 03监控实时区块链事件
  4. 04为 React 应用接入 EVM

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/uniswap/uniswap-ai --skill viem-integration

安装后在 Claude Code 中输入/viem-integration确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
accounts-and-keys.md
clients-and-transports.md
contract-patterns.md
reading-data.md
wagmi-react.md
writing-transactions.md

详细介绍

viem 集成

使用 viem 为 TypeScript/JavaScript 应用集成 EVM 区块链。

快速选择指南

正在构建……使用此方案
Node.js 脚本/后端使用 http 传输的 viem
React/Next.js 前端wagmi 钩子(基于 viem 构建)
实时事件监控使用 webSocket 传输的 viem
浏览器钱包集成wagmi 或 viem 自定义传输

安装

# Core library
npm install viem

# For React apps, also install wagmi
npm install wagmi viem @tanstack/react-query

核心概念

客户端

viem 使用两种客户端类型:

客户端用途示例用途
PublicClient只读操作获取余额、读取合约、获取日志
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() 进行验证
  • 链 ID:必须来自 viem 支持的链定义
  • 私钥:绝不能硬编码 — 始终使用 process.env.PRIVATE_KEY 并在运行时进行验证
  • RPC URL:只能使用 https:// 或 wss:// 协议
  • ABI 输入:编码前,验证类型是否与预期的 Solidity 类型匹配

快速入门示例

读取余额
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)']);

// 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}`);

参考文档

如需深入了解特定主题:

主题参考文件
客户端设置、传输方式、链客户端与传输方式
读取区块链数据读取数据
发送交易写入交易
私钥、HD 钱包账户与密钥
ABI 处理、multicall合约模式
React/wagmi 钩子Wagmi React

相关插件

熟悉 viem 基础知识后,uniswap-trading 插件可提供全面的 Uniswap 兑换集成:

  • Uniswap Trading API 集成
  • Universal Router SDK 的使用
  • 代币兑换实现

使用以下命令安装: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 会抛出带类型的错误,可捕获并处理:

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')
  }
}

资源

评论

支持 Markdown