viem-integration
uniswap/uniswap-ai
Integrate EVM blockchains with viem for TypeScript—read data, send transactions, and interact with smart contracts.
What is viem-integration?
viem is a TypeScript library for interacting with EVM blockchains. Use it when you need to read blockchain data, send transactions, call smart contracts, or integrate wallet functionality in Node.js backends or React frontends.
- Create public clients for read-only blockchain operations (balances, contract reads, logs)
- Create wallet clients for write operations (transactions, contract writes, message signing)
- Support multiple transports: HTTP RPC, WebSocket for real-time events, and custom browser wallet integration
- Validate and encode Ethereum addresses, chain IDs, and contract ABIs with built-in utilities
- Handle unit conversions between wei and human-readable token amounts
- Provide typed error handling for contract execution and transaction failures
How to install viem-integration
npx skills add https://github.com/uniswap/uniswap-ai --skill viem-integration- Node.js and npm installed
- Basic understanding of Ethereum addresses and transactions
- An RPC endpoint URL (public or private) for the target chain
- For write operations: a private key stored securely in environment variables
How to use viem-integration
- 1.Install viem with `npm install viem` (add `wagmi` for React apps)
- 2.Choose a client type: PublicClient for reads, WalletClient for writes
- 3.Select a transport (http, webSocket, or custom) and chain from viem/chains
- 4.Create the client with the appropriate chain and transport configuration
- 5.Use client methods like getBalance, readContract, sendTransaction, or writeContract
- 6.For contract interactions, provide the contract address, ABI, and function arguments
- 7.Validate all user inputs (addresses, chain IDs, amounts) before encoding
- 8.Handle errors with typed catch blocks for ContractFunctionExecutionError and InsufficientFundsError
Use cases
- Build a Node.js script to monitor token balances across multiple wallets and chains
- Create a React app with wagmi hooks to let users connect wallets and swap tokens
- Set up real-time event monitoring using WebSocket transport to track contract events
- Implement a backend service that reads Uniswap contract data and sends transactions on behalf of users
- Develop a multi-chain portfolio tracker that queries balances on Ethereum, Arbitrum, Optimism, and Base
- Backend developers building blockchain automation or monitoring services
- React/Next.js frontend developers integrating wallet connections and on-chain interactions
- Full-stack developers implementing DeFi applications or token swaps
- DevOps engineers setting up blockchain data pipelines
- Blockchain developers familiar with Solidity who want TypeScript tooling
viem-integration FAQ
Use PublicClient for read-only operations like fetching balances or reading contract state. Use WalletClient for write operations like sending transactions or calling contract functions that modify state.
Always load private keys from environment variables using `process.env.PRIVATE_KEY` and validate them at runtime. Never commit keys to version control.
viem is the core library for EVM interactions. wagmi is a React hooks library built on top of viem, providing convenient hooks for wallet connection, contract reading/writing, and transaction management in React apps.
Use `http()` for standard RPC calls (most common). Use `webSocket()` for real-time event subscriptions. Use `custom()` for browser wallets that inject `window.ethereum`.
Use `parseAbi()` to define ABIs as human-readable strings, or import full JSON ABIs. Always validate that function names and argument types match your contract before calling.
Full instructions (SKILL.md)
Source of truth, from uniswap/uniswap-ai.
name: viem-integration description: Integrate EVM blockchains using viem. Use when user says "read blockchain data", "send transaction", "interact with smart contract", "connect to Ethereum", "use viem", "use wagmi", "wallet integration", "viem setup", or mentions blockchain/EVM development with TypeScript. allowed-tools: Read, Write, Edit, Glob, Grep, Bash(npm:), Bash(npx:), WebFetch, Task(subagent_type:viem-integration-expert) model: opus license: MIT metadata: author: uniswap version: '1.0.0'
viem Integration
Integrate EVM blockchains using viem for TypeScript/JavaScript applications.
Quick Decision Guide
| 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 |
Installation
# Core library
npm install viem
# For React apps, also install wagmi
npm install wagmi viem @tanstack/react-query
Core Concepts
Clients
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 |
Transports
| Transport | Use Case |
|---|---|
http() | Standard RPC calls (most common) |
webSocket() | Real-time event subscriptions |
custom() | Browser wallets (window.ethereum) |
Chains
viem includes 50+ chain definitions. Import from viem/chains:
import { mainnet, arbitrum, optimism, base, polygon } from 'viem/chains';
Input Validation Rules
Before interpolating ANY user-provided value into generated TypeScript code:
- Ethereum addresses: MUST match
^0x[a-fA-F0-9]{40}$— use viem'sisAddress()for validation - Chain IDs: MUST be from viem's supported chain definitions
- Private keys: MUST NEVER be hardcoded — always use
process.env.PRIVATE_KEYwith runtime validation - RPC URLs: MUST use
https://orwss://protocols only - ABI inputs: Validate types match expected Solidity types before encoding
Quick Start Examples
Read Balance
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
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
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
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}`);
Reference Documentation
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 |
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
Common Utilities
Unit Conversion
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"
Address Utilities
import { getAddress, isAddress } from 'viem';
isAddress('0x...'); // true/false
getAddress('0x...'); // checksummed address
Hashing
import { keccak256, toHex } from 'viem';
keccak256(toHex('hello')); // 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
Error Handling
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')
}
}
Resources
Related skills
More from uniswap/uniswap-ai and the wider catalog.

configurator
Configure CCA (Continuous Clearing Auction) smart contract parameters through an interactive bulk form flow. Use when user says "configure auction", "cca auction", "setup token auction", "auction configuration", "continuous auction", or mentions CCA contracts.

deployer
Deploy CCA (Continuous Clearing Auction) smart contracts using the Factory pattern. Use when user says "deploy auction", "deploy cca", "factory deployment", or wants to deploy a configured auction.

liquidity-planner
This skill should be used when the user asks to "provide liquidity", "create LP position", "add liquidity to pool", "become a liquidity provider", "create v3 position", "create v4 position", "concentrated liquidity", "set price range", or mentions providing liquidity, LP positions, or liquidity pools on Uniswap. Generates deep links to create positions in the Uniswap interface.

swap-integration
Integrate Uniswap token swaps into frontends, backends, and smart contracts.

2d-pixel-perfect
Set up, diagnose, and fix pixel-perfect 2D rendering in Unity with PixelPerfectCamera for retro and pixel-art games.

audio-setup-mixers
Route Audio Sources into mixer groups by automatically classifying sounds by type.