watchEvent
Watches and returns emitted Event Logs.
This Action will batch up all the Event Logs found within the pollingInterval
, and invoke them via onLogs
.
watchEvent
will attempt to create an Event Filter and listen to changes to the Filter per polling interval, however, if the RPC Provider does not support Filters (ie. eth_newFilter
), then watchEvent
will fall back to using getLogs
instead.
Usage
By default, you can watch all broadcasted events to the blockchain by just passing onLogs
.
These events will be batched up into Event Logs and sent to onLogs
:
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
Scoping
You can also scope watchEvent
to a set of given attributes (listed below).
Address
watchEvent
can be scoped to an address:
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
Event
watchEvent
can be scoped to an event.
The event
argument takes in an event in ABI format – we have a parseAbiItem
utility that you can use to convert from a human-readable event signature → ABI.
import { parseAbiItem } from 'viem'
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { parseAbiItem } from 'viem'
import { publicClient } from './client'
import { wagmiAbi } from './abi'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
By default, event
accepts the AbiEvent
type:
import { publicClient } from './client'
const unwatch = publicClient.watchEvent(publicClient, {
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: {
name: 'Transfer',
inputs: [
{ type: 'address', indexed: true, name: 'from' },
{ type: 'address', indexed: true, name: 'to' },
{ type: 'uint256', indexed: false, name: 'value' }
]
},
onLogs: logs => console.log(logs)
})
import { publicClient } from './client'
const unwatch = publicClient.watchEvent(publicClient, {
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: {
name: 'Transfer',
inputs: [
{ type: 'address', indexed: true, name: 'from' },
{ type: 'address', indexed: true, name: 'to' },
{ type: 'uint256', indexed: false, name: 'value' }
]
},
onLogs: logs => console.log(logs)
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
Arguments
watchEvent
can be scoped to given indexed arguments on the event:
import { parseAbiItem } from 'viem'
import { publicClient } from './client'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'
},
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { parseAbiItem } from 'viem'
import { publicClient } from './client'
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'
},
onLogs: logs => console.log(logs)
})
// > [{ ... }, { ... }, { ... }]
// > [{ ... }, { ... }]
// > [{ ... }, { ... }, { ... }, { ... }]
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const publicClient = createPublicClient({
chain: mainnet,
transport: http()
})
Only indexed arguments in event
are candidates for args
.
These arguments can also be an array to indicate that other values can exist in the position:
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
// '0xd8da...' OR '0xa5cc...' OR '0xa152...'
from: [
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
'0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0xa152f8bb749c55e9943a3a0a3111d18ee2b3f94e',
],
}
onLogs: logs => console.log(logs)
})
const unwatch = publicClient.watchEvent({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
// '0xd8da...' OR '0xa5cc...' OR '0xa152...'
from: [
'0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
'0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac',
'0xa152f8bb749c55e9943a3a0a3111d18ee2b3f94e',
],
}
onLogs: logs => console.log(logs)
})
Multiple Events
watchEvent
can be scoped to multiple events:
const unwatch = publicClient.watchEvent({
events: parseAbi([
'event Approval(address indexed owner, address indexed sender, uint256 value)',
'event Transfer(address indexed from, address indexed to, uint256 value)',
]),
onLogs: logs => console.log(logs)
})
const unwatch = publicClient.watchEvent({
events: parseAbi([
'event Approval(address indexed owner, address indexed sender, uint256 value)',
'event Transfer(address indexed from, address indexed to, uint256 value)',
]),
onLogs: logs => console.log(logs)
})
Note: watchEvent
scoped to multiple events cannot be also scoped with indexed arguments (args
).
Returns
UnwatchFn
A function that can be invoked to stop watching for new Event Logs.
Parameters
onLogs
- Type:
(logs: Log[]) => void
The new Event Logs.
const unwatch = publicClient.watchEvent(
{ onLogs: logs => console.log(logs) }
)
const unwatch = publicClient.watchEvent(
{ onLogs: logs => console.log(logs) }
)
address (optional)
- Type:
Address | Address[]
The contract address or a list of addresses from which Logs should originate.
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
onLogs: logs => console.log(logs)
}
)
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
onLogs: logs => console.log(logs)
}
)
event (optional)
- Type:
AbiEvent
The event in ABI format.
A parseAbiItem
utility is exported from viem that converts from a human-readable event signature → ABI.
import { parseAbiItem } from 'viem'
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: logs => console.log(logs)
}
)
import { parseAbiItem } from 'viem'
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
onLogs: logs => console.log(logs)
}
)
args (optional)
- Type: Inferred.
A list of indexed event arguments.
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'
}
onLogs: logs => console.log(logs)
}
)
const unwatch = publicClient.watchEvent(
{
address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2',
event: parseAbiItem('event Transfer(address indexed from, address indexed to, uint256 value)'),
args: {
from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045',
to: '0xa5cc3c03994db5b0d9a5eedd10cabab0813678ac'
}
onLogs: logs => console.log(logs)
}
)
batch (optional)
- Type:
boolean
- Default:
true
Whether or not to batch the Event Logs between polling intervals.
const unwatch = publicClient.watchEvent(
{
batch: false,
onLogs: logs => console.log(logs),
}
)
const unwatch = publicClient.watchEvent(
{
batch: false,
onLogs: logs => console.log(logs),
}
)
onError (optional)
- Type:
(error: Error) => void
Error thrown from listening for new Event Logs.
const unwatch = publicClient.watchEvent(
{
onError: error => console.log(error)
onLogs: logs => console.log(logs),
}
)
const unwatch = publicClient.watchEvent(
{
onError: error => console.log(error)
onLogs: logs => console.log(logs),
}
)
poll (optional)
- Type:
boolean
- Default:
false
for WebSocket Clients,true
for non-WebSocket Clients
Whether or not to use a polling mechanism to check for new logs instead of a WebSocket subscription.
This option is only configurable for Clients with a WebSocket Transport.
import { createPublicClient, webSocket } from 'viem'
import { mainnet } from 'viem/chains'
const publicClient = createPublicClient({
chain: mainnet,
transport: webSocket()
})
const unwatch = publicClient.watchEvent(
{
onLogs: logs => console.log(logs),
poll: true,
}
)
import { createPublicClient, webSocket } from 'viem'
import { mainnet } from 'viem/chains'
const publicClient = createPublicClient({
chain: mainnet,
transport: webSocket()
})
const unwatch = publicClient.watchEvent(
{
onLogs: logs => console.log(logs),
poll: true,
}
)
pollingInterval (optional)
- Type:
number
Polling frequency (in ms). Defaults to the Client's pollingInterval
config.
const unwatch = publicClient.watchEvent(
{
pollingInterval: 1_000,
onLogs: logs => console.log(logs),
}
)
const unwatch = publicClient.watchEvent(
{
pollingInterval: 1_000,
onLogs: logs => console.log(logs),
}
)
Live Example
Check out the usage of watchEvent
in the live Event Logs Example below.
JSON-RPC Methods
When poll true
and RPC Provider supports eth_newFilter
:
- Calls
eth_newFilter
to create a filter (called on initialize). - On a polling interval, it will call
eth_getFilterChanges
.
When poll true
RPC Provider does not support eth_newFilter
:
- Calls
eth_getLogs
for each block between the polling interval.
When poll false
and WebSocket Transport:
- Uses a WebSocket subscription via
eth_subscribe
and the "logs" event.