Getting Started ​
This page sets up a viem environment that all the function-reference examples build on.
Install ​
bash
pnpm add viemClients ​
ts
import { createPublicClient, createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { privateKeyToAccount } from 'viem/accounts'
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`)
export const publicClient = createPublicClient({
chain: mainnet,
transport: http(process.env.RPC_URL),
})
export const walletClient = createWalletClient({
account,
chain: mainnet,
transport: http(process.env.RPC_URL),
})Constants ​
ts
export const VAULT = '0x273DA948ACa9261043fbdb2a857BC255ECC29012' as const
export const USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' as const
// USDC has 6 decimals; vault shares have 18 decimals (standard ERC-4626 default).
export const USDC_DECIMALS = 6
export const SHARE_DECIMALS = 18ABI ​
Use the snippet files in this project:
snippets/abi.tsfor vault functions (read + write) sourced from the contract interface
For standard share-token reads such as balanceOf and allowance, use viem's bundled erc20Abi.
Approving USDC ​
deposit and mint pull USDC from the caller, so they require an ERC-20 approval on USDC, not on the vault:
ts
import { parseUnits } from 'viem'
import { walletClient, publicClient } from './client'
import { USDC, VAULT, USDC_DECIMALS } from './constants'
const usdcAbi = [{
type: 'function',
name: 'approve',
stateMutability: 'nonpayable',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
],
outputs: [{ name: 'success', type: 'bool' }],
}] as const
const amount = parseUnits('1000', USDC_DECIMALS) // 1000 USDC
const hash = await walletClient.writeContract({
address: USDC,
abi: usdcAbi,
functionName: 'approve',
args: [VAULT, amount],
})
await publicClient.waitForTransactionReceipt({ hash })You only need to do this once per allowance window (or use a large value if you prefer infinite approvals).
Simulate before writing ​
Every example uses the simulate-then-write pattern. simulateContract runs the call against state and returns the human-readable revert reason if it would fail — much better than a raw execution reverted:
ts
const { request, result } = await publicClient.simulateContract({
account,
address: VAULT,
abi: liteUsdVaultAbi,
functionName: 'deposit',
args: [amount, account.address],
})
const hash = await walletClient.writeContract(request)
const receipt = await publicClient.waitForTransactionReceipt({ hash })
