返回章节列表
第 03 章入门
读取合约数据
掌握 useReadContract、useReadContracts 和实时数据订阅
5 课时2.5小时
概述
读取链上数据是 DApp 的基础能力。本章讲解如何高效地从智能合约读取数据。
ABI 与类型安全
wagmi 和 viem 提供完整的类型推导: 1. **ABI 定义**: 使用 `as const` 确保类型推导 2. **函数参数**: 自动推导参数类型 3. **返回值**: 自动推导返回类型 4. **错误处理**: 类型安全的错误处理
代码示例
读取 ERC20 代币信息
使用 useReadContract 读取 ERC20 代币余额
typescript
1'use client'2 3import { useReadContract, useReadContracts } from 'wagmi'4import { formatUnits } from 'viem'5 6const erc20Abi = [7 {8 name: 'balanceOf',9 type: 'function',10 stateMutability: 'view',11 inputs: [{ name: 'account', type: 'address' }],12 outputs: [{ type: 'uint256' }],13 },14 {15 name: 'symbol',16 type: 'function',17 stateMutability: 'view',18 inputs: [],19 outputs: [{ type: 'string' }],20 },21 {22 name: 'decimals',23 type: 'function',24 stateMutability: 'view',25 inputs: [],26 outputs: [{ type: 'uint8' }],27 },28] as const29 30const USDC_ADDRESS = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'31 32export function TokenBalance({ address }: { address: `0x${string}` }) {33 const { data: balance, isLoading } = useReadContract({34 address: USDC_ADDRESS,35 abi: erc20Abi,36 functionName: 'balanceOf',37 args: [address],38 })39 40 const { data: decimals } = useReadContract({41 address: USDC_ADDRESS,42 abi: erc20Abi,43 functionName: 'decimals',44 })45 46 if (isLoading) return <span>加载中...</span>47 48 const formatted = balance && decimals 49 ? formatUnits(balance, decimals) 50 : '0'51 52 return <span>{formatted} USDC</span>53}批量读取合约数据
使用 useReadContracts 批量读取多个代币余额
typescript
1'use client'2 3import { useReadContracts } from 'wagmi'4import { erc20Abi } from 'viem'5 6const tokens = [7 { address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', symbol: 'USDC' },8 { address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', symbol: 'USDT' },9 { address: '0x6B175474E89094C44Da98b954EesdfAHD7e40C', symbol: 'DAI' },10]11 12export function MultiTokenBalance({ account }: { account: `0x${string}` }) {13 const { data, isLoading } = useReadContracts({14 contracts: tokens.map((token) => ({15 address: token.address as `0x${string}`,16 abi: erc20Abi,17 functionName: 'balanceOf',18 args: [account],19 })),20 })21 22 if (isLoading) return <div>加载中...</div>23 24 return (25 <ul>26 {tokens.map((token, i) => (27 <li key={token.address}>28 {token.symbol}: {data?.[i]?.result?.toString() ?? '0'}29 </li>30 ))}31 </ul>32 )33}