Skip to main content

Documentation Index

Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt

Use this file to discover all available pages before exploring further.

Overview

EventLog represents Ethereum event logs emitted by smart contracts. Events are indexed by topic0 (event signature hash) and up to 3 additional indexed parameters. The EventLog primitive provides type-safe construction, filtering, sorting, and RPC conversion.
import * as EventLog from '@voltaire/primitives/EventLog';
import * as Address from '@voltaire/primitives/Address';
import * as Hash from '@voltaire/primitives/Hash';

// Create an event log
const log = EventLog.create({
  address: Address.from("0x1234567890123456789012345678901234567890"),
  topics: [
    Hash.from("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") // Transfer event
  ],
  data: new Uint8Array([]),
  blockNumber: 18000000n,
  logIndex: 0
});

Type Definition

type EventLogType<
  TAddress extends AddressType = AddressType,
  TTopics extends readonly HashType[] = readonly HashType[]
> = {
  address: TAddress;           // Contract address that emitted the log
  topics: TTopics;             // Event topics (topic0 = signature, topic1-3 = indexed params)
  data: Uint8Array;            // Non-indexed parameters (ABI-encoded)
  blockNumber?: bigint;        // Block number where log was emitted
  transactionHash?: HashType;  // Transaction hash that generated the log
  transactionIndex?: number;   // Transaction index in block
  blockHash?: HashType;        // Block hash
  logIndex?: number;           // Log index in block
  removed?: boolean;           // True if log was removed due to chain reorg
} & { readonly __tag: "EventLog" };

Constructor Methods

create

Create an EventLog from parameters with branded types.
const log = EventLog.create({
  address: Address.from("0x1234567890123456789012345678901234567890"),
  topics: [transferTopic0, senderTopic, recipientTopic],
  data: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 100]), // amount = 100
  blockNumber: 18000000n,
  transactionHash: txHash,
  transactionIndex: 5,
  blockHash: blockHash,
  logIndex: 12,
  removed: false
});

from

Alias for create. Creates an EventLog from parameters.
const log = EventLog.from({
  address: contractAddress,
  topics: [eventSignature],
  data: eventData
});

fromRpc

Convert RPC log format (hex strings) to EventLog.
const rpcLog = {
  address: "0x1234567890123456789012345678901234567890",
  topics: ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
  data: "0x0000000000000000000000000000000000000000000000000000000000000064",
  blockNumber: "0x112a880",
  transactionHash: "0x...",
  transactionIndex: "0x5",
  blockHash: "0x...",
  logIndex: "0xc",
  removed: false
};

const log = EventLog.fromRpc(rpcLog);

Conversion Methods

toRpc

Convert EventLog to RPC format (hex strings).
const log = EventLog.create({ address, topics, data });
const rpcLog = EventLog.toRpc(log);
// {
//   address: "0x...",
//   topics: ["0x...", "0x..."],
//   data: "0x...",
//   blockNumber: "0x112a880",
//   ...
// }

clone / copy

Create a deep copy of an EventLog.
const log = EventLog.create({ address, topics, data });
const cloned = EventLog.clone(log);
const copied = EventLog.copy(log);  // alias for clone

Accessor Methods

getTopic0 / getSignature

Get the event signature hash (topic0).
const log = EventLog.create({ address, topics, data });
const signature = EventLog.getTopic0(log);      // HashType | undefined
const sig = EventLog.getSignature(log);         // alias

getIndexedTopics / getIndexed

Get indexed parameters (topic1-topic3).
const log = EventLog.create({
  address,
  topics: [transferSig, senderHash, recipientHash],
  data
});

const indexed = EventLog.getIndexedTopics(log);  // [senderHash, recipientHash]
const params = EventLog.getIndexed(log);         // alias

isRemoved / wasRemoved

Check if log was removed due to chain reorganization.
const log = EventLog.create({ address, topics, data, removed: true });
const removed = EventLog.isRemoved(log);   // true
const was = EventLog.wasRemoved(log);      // alias

Filtering Methods

matchesAddress

Check if log matches an address filter.
const log = EventLog.create({ address: contractA, topics, data });

// Single address
EventLog.matchesAddress(log, contractA);  // true
EventLog.matchesAddress(log, contractB);  // false

// Multiple addresses
EventLog.matchesAddress(log, [contractA, contractB]);  // true

matchesTopics

Check if log matches a topic filter. Use null as wildcard.
const log = EventLog.create({
  address,
  topics: [transferSig, senderHash, recipientHash],
  data
});

// Match exact topic0
EventLog.matchesTopics(log, [transferSig]);  // true

// Wildcard topic0, match topic1
EventLog.matchesTopics(log, [null, senderHash]);  // true

// Match any of multiple topics at position
EventLog.matchesTopics(log, [null, [senderHash, otherHash]]);  // true

matchesFilter

Check if log matches a complete filter object.
const filter = {
  address: contractAddress,
  topics: [transferSig, null, recipientHash],
  fromBlock: 18000000n,
  toBlock: 18100000n
};

EventLog.matchesFilter(log, filter);  // true if log matches all criteria

filterLogs

Filter an array of logs by criteria.
const logs = [log1, log2, log3, log4];

const filtered = EventLog.filterLogs(logs, {
  address: contractAddress,
  topics: [transferSig]
});
// Returns logs from contractAddress with Transfer event signature

Sorting

sortLogs

Sort logs by block number and log index.
const unsorted = [log3, log1, log2];
const sorted = EventLog.sortLogs(unsorted);
// Sorted by blockNumber ascending, then logIndex ascending

Filter Type

type Filter<
  TAddress extends AddressType | AddressType[] | undefined,
  TTopics extends readonly (HashType | HashType[] | null)[] | undefined
> = {
  address?: TAddress;          // Contract address(es) to filter
  topics?: TTopics;            // Topic filters (null = any, array = any of)
  fromBlock?: bigint;          // Starting block (inclusive)
  toBlock?: bigint;            // Ending block (inclusive)
  blockHash?: HashType;        // Specific block hash (alternative to range)
};

Usage Patterns

Decoding Transfer Events

import * as EventLog from '@voltaire/primitives/EventLog';
import * as Keccak256 from '@voltaire/crypto/Keccak256';

// Transfer(address indexed from, address indexed to, uint256 value)
const transferSig = Keccak256.hashString("Transfer(address,address,uint256)");

const logs = await provider.getLogs({
  address: tokenContract,
  topics: [transferSig]
});

for (const rpcLog of logs) {
  const log = EventLog.fromRpc(rpcLog);
  const [from, to] = EventLog.getIndexedTopics(log);
  // Decode log.data for the value parameter
}

Filtering by Multiple Addresses

const filter = {
  address: [usdcAddress, usdtAddress, daiAddress],
  topics: [transferSig],
  fromBlock: 18000000n
};

const filtered = EventLog.filterLogs(allLogs, filter);

Handling Reorgs

for await (const event of blockStream.watch()) {
  if (event.type === 'reorg') {
    // Remove logs from reverted blocks
    for (const block of event.removed) {
      const logsToRemove = logs.filter(
        log => log.blockHash && EventLog.matchesFilter(log, { blockHash: block.hash })
      );
      for (const log of logsToRemove) {
        rollbackLog(log);
      }
    }
  }
}