parseEventLogs
Extracts & decodes logs matching the provided abi
(and optional eventName
) from a set of opaque logs.
Useful for decoding logs on Transaction Receipts.
Install
import { parseEventLogs } from 'viem'
import { parseEventLogs } from 'viem'
Usage
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3 ... },
// { args: { ... }, eventName: 'Approval', logIndex: 5 ... },
// ...
// ]
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3 ... },
// { args: { ... }, eventName: 'Approval', logIndex: 5 ... },
// ...
// ]
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
Scoping to Event Name(s)
You can scope the logs to a specific event name by providing the eventName
argument:
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
eventName: 'Transfer',
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3, ... },
// { args: { ... }, eventName: 'Transfer', logIndex: 7, ... },
// ...
// ]
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
eventName: 'Transfer',
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3, ... },
// { args: { ... }, eventName: 'Transfer', logIndex: 7, ... },
// ...
// ]
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
You can also pass an array to scope multiple event names:
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
eventName: ['Transfer', 'Approval'],
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3, ... },
// { args: { ... }, eventName: 'Approval', logIndex: 5, ... },
// { args: { ... }, eventName: 'Transfer', logIndex: 7, ... },
// ...
// ]
import { parseEventLogs } from 'viem'
import { erc20Abi } from './abi'
import { client } from './client'
const receipt = await getTransactionReceipt(client, {
hash: '0xec23b2ba4bc59ba61554507c1b1bc91649e6586eb2dd00c728e8ed0db8bb37ea',
})
const logs = parseEventLogs({
abi: erc20Abi,
eventName: ['Transfer', 'Approval'],
logs: receipt.logs,
})
// [
// { args: { ... }, eventName: 'Transfer', logIndex: 3, ... },
// { args: { ... }, eventName: 'Approval', logIndex: 5, ... },
// { args: { ... }, eventName: 'Transfer', logIndex: 7, ... },
// ...
// ]
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
export const erc20Abi = [
...
{
inputs: [
{
indexed: true,
name: 'from',
type: 'address',
},
{ indexed: true, name: 'to', type: 'address' },
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Transfer',
type: 'event',
},
{
inputs: [
{
indexed: true,
name: 'owner',
type: 'address',
},
{
indexed: true,
name: 'spender',
type: 'address',
},
{
indexed: false,
name: 'value',
type: 'uint256',
},
],
name: 'Approval',
type: 'event',
}
...
] as const;
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'
export const client = createPublicClient({
chain: mainnet,
transport: http()
})
Partial Decode
By default, if the topics
and data
does not conform to the ABI (a mismatch between the number of indexed/non-indexed arguments), parseEventLogs
will not return return the decoded log.
For example, the following will not return the nonconforming log as there is a mismatch in non-indexed
arguments & data
length.
parseEventLogs({
abi: parseAbi(['event Transfer(address indexed, address, uint256)']),
logs: [{
// `data` should be 64 bytes, but is only 32 bytes.
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
]
// ...
}]
})
// []
parseEventLogs({
abi: parseAbi(['event Transfer(address indexed, address, uint256)']),
logs: [{
// `data` should be 64 bytes, but is only 32 bytes.
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
]
// ...
}]
})
// []
It is possible for parseEventLogs
to try and partially decode the Log, this can be done by setting the strict
argument to false
:
parseEventLogs({
abi: parseAbi(['event Transfer(address indexed, address, uint256)']),
logs: [{
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
]
// ...
}]
strict: false
})
/**
* [
* {
* eventName: 'Transfer',
* args: ['0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'],
* blockNumber: 42069420n,
* logIndex: 69,
* ...
* }
* ]
*/
parseEventLogs({
abi: parseAbi(['event Transfer(address indexed, address, uint256)']),
logs: [{
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
]
// ...
}]
strict: false
})
/**
* [
* {
* eventName: 'Transfer',
* args: ['0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'],
* blockNumber: 42069420n,
* logIndex: 69,
* ...
* }
* ]
*/
Return Value
Log[]
Decoded logs.
Parameters
abi
- Type:
Abi
The contract's ABI.
const topics = parseEventLogs({
abi: wagmiAbi,
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
const topics = parseEventLogs({
abi: wagmiAbi,
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
logs
- Type:
Log[]
An array of logs to parse.
const topics = parseEventLogs({
abi: wagmiAbi,
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
const topics = parseEventLogs({
abi: wagmiAbi,
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
eventName (optional)
- Type:
string
An event name from the ABI.
const topics = parseEventLogs({
abi: wagmiAbi,
eventName: 'Transfer',
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
const topics = parseEventLogs({
abi: wagmiAbi,
eventName: 'Transfer',
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}]
})
strict (optional)
- Type:
boolean
- Default:
true
If true
, parseEventLogs
will not return nonconforming logs. If false
, parseEventLogs
will try and partially decode nonconforming logs.
const topics = parseEventLogs({
abi: wagmiAbi,
eventName: 'Transfer',
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}],
strict: false
})
const topics = parseEventLogs({
abi: wagmiAbi,
eventName: 'Transfer',
logs: [{
blockNumber: 69420n,
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
logIndex: 1,
topics: [
'0x406dade31f7ae4b5dbc276258c28dde5ae6d5c2773c5745802c493a2360e55e0',
'0x00000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266',
'0x0000000000000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8'
]
// ...
}],
strict: false
})