Developer Fundamentals

6. Events and Logs

Filter and decode smart contract events with criteria, pagination, and raw logs.

Prerequisites

Decoding Contract Chatter

Contracts shout events! 📣

Logs are immutable signals (e.g., Transfer(from, to, amount))—query them for history.

Easy filters: vtho.filters.Transfer(null, '0xTargetAddr').get({ unit: 'block', from: 1000000 }, { limit: 10 }, 'desc').
Decoded data in log.decodedData._from.
Raw power: Encode topics with ABIEvent for filterRawEventLogs.

javascriptimport { ABIEvent } from '@vechain/sdk-core';
const event = new ABIEvent('event Transfer(address indexed from, address indexed to, uint256 amount)');
const topics = event.encodeFilterTopics([null, '0xTarget']);  // Filter 'to'
const logs = await thor.logs.filterRawEventLogs({ criteriaSet: [{ address: vthoAddr, topic1: topics[1] }], range: { from: 0, to: 10000000 } });
const decoded = logs.map(log => event.decodeEventLog(log));
javascriptimport { ABIEvent } from '@vechain/sdk-core';
const event = new ABIEvent('event Transfer(address indexed from, address indexed to, uint256 amount)');
const topics = event.encodeFilterTopics([null, '0xTarget']);  // Filter 'to'
const logs = await thor.logs.filterRawEventLogs({ criteriaSet: [{ address: vthoAddr, topic1: topics[1] }], range: { from: 0, to: 10000000 } });
const decoded = logs.map(log => event.decodeEventLog(log));
javascriptimport { ABIEvent } from '@vechain/sdk-core';
const event = new ABIEvent('event Transfer(address indexed from, address indexed to, uint256 amount)');
const topics = event.encodeFilterTopics([null, '0xTarget']);  // Filter 'to'
const logs = await thor.logs.filterRawEventLogs({ criteriaSet: [{ address: vthoAddr, topic1: topics[1] }], range: { from: 0, to: 10000000 } });
const decoded = logs.map(log => event.decodeEventLog(log));

PRO TIP

filterEventLogs batches multiple filters efficiently. Paginate always—millions of logs exist!

Nailed it!