返回章节列表
第 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 const
18
19interface TransferEvent {
20 from: string
21 to: string
22 value: string
23 txHash: string
24}
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}

相关资源

useWatchContractEvent
上一章: 写入合约与交易处理下一章: 签名与身份验证