返回章节列表
第 05 章进阶
合约事件监听
实时监听链上事件,获取历史事件日志
4 课时2小时
概述
事件是链上状态变化的通知机制。本章讲解如何监听和处理合约事件。
事件监听模式
两种主要的事件获取方式: 1. **实时监听**: useWatchContractEvent - 订阅新事件 2. **历史查询**: 使用 viem 的 getLogs 获取历史事件
代码示例
监听 Transfer 事件
实时监听 ERC20 Transfer 事件并展示
typescript
1'use client'2 3import { useWatchContractEvent } from 'wagmi'4import { useState } from 'react'5import { formatUnits } from 'viem'6 7const erc20Abi = [8 {9 name: 'Transfer',10 type: 'event',11 inputs: [12 { name: 'from', type: 'address', indexed: true },13 { name: 'to', type: 'address', indexed: true },14 { name: 'value', type: 'uint256', indexed: false },15 ],16 },17] as const18 19interface TransferEvent {20 from: string21 to: string22 value: string23 txHash: string24}25 26export function TransferWatcher({ tokenAddress }: { tokenAddress: `0x${string}` }) {27 const [transfers, setTransfers] = useState<TransferEvent[]>([])28 29 useWatchContractEvent({30 address: tokenAddress,31 abi: erc20Abi,32 eventName: 'Transfer',33 onLogs(logs) {34 const newTransfers = logs.map((log) => ({35 from: log.args.from as string,36 to: log.args.to as string,37 value: formatUnits(log.args.value as bigint, 6),38 txHash: log.transactionHash,39 }))40 setTransfers((prev) => [...newTransfers, ...prev].slice(0, 50))41 },42 })43 44 return (45 <div className="space-y-2">46 <h3 className="font-bold">实时转账</h3>47 {transfers.map((t, i) => (48 <div key={i} className="p-2 bg-gray-800 rounded text-sm">49 <p>{t.from.slice(0, 8)}... → {t.to.slice(0, 8)}...</p>50 <p className="text-green-400">{t.value} USDC</p>51 </div>52 ))}53 </div>54 )55}