ListEventsRequest
ListEventsRequest lists events with CEL filtering and pagination.
Returns events ordered from most recent to older (slot DESC, block_offset DESC, call_idx DESC). Supports filtering on event metadata and payload using CEL expressions with specialized byte functions.
Available fields for filtering:
- event.event_id (string): Unique event identifier (format: “ts{slot}{block_offset}{call_idx}”)
- event.transaction_signature.value (bytes): Transaction signature that emitted the event
- event.slot (uint64): Block slot number where event was emitted
- event.call_idx (uint32): Instruction call index within transaction
- event.block_offset (uint32): Transaction’s position within the block
- event.timestamp (google.protobuf.Timestamp): Event emission timestamp
- event.program.value (bytes): Program public key that emitted the event
- event.program_idx (uint32): Program index within transaction
- event.payload (bytes): Event payload data
- event.payload_size (uint32): Size of event payload in bytes
- event.fee_payer.value (bytes): Fee payer’s public key for the transaction
Available CEL functions:
- has(field): Check if optional field exists
- startsWith(string, prefix): Check if string starts with prefix (string fields only)
- first1Byte(bytes): Extract first byte as uint8
- first4Bytes(bytes): Extract first 4 bytes as uint32 (little-endian)
- first8Bytes(bytes): Extract first 8 bytes as uint64 (little-endian)
- bytesPrefix(bytes, prefix): Check if bytes start with prefix
- uint(value): Convert to uint type
- int(value): Convert to int type
- string(value): Convert to string type
- bytes(value): Convert to bytes type
- double(value): Convert to double type
- timestamp(value): Convert to timestamp type
- duration(value): Convert to duration type
Available filter parameters (accessible via params.* in expressions):
- params.slot (uint64): Slot number for filtering
- params.u64 (uint64): Generic uint64 parameter for payload matching
- params.signature (Signature): Transaction signature for filtering
- params.signature.value (bytes): Transaction signature bytes for filtering
- params.address (Pubkey): Program address for filtering
- params.address.value (bytes): Program address bytes for filtering
- params.prefix (bytes): Byte prefix for payload filtering
- params.timestamp (Timestamp): Timestamp parameter for filtering
Filter examples:
-
Filter by slot: filter.expression = “event.slot > uint(1000)” filter.expression = “event.slot >= uint(100) && event.slot <= uint(200)”
-
Filter by slot using parameter: filter.expression = “event.slot >= params.slot” filter.params[“slot”].int_value = 1234
-
Filter by call index: filter.expression = “event.call_idx == uint(0)” // First instruction filter.expression = “event.call_idx > uint(0)” // Nested instructions
-
Filter by block offset: filter.expression = “event.block_offset >= uint(0)” filter.expression = “event.block_offset == uint(5)”
-
Filter by transaction signature (using parameter): filter.expression = “event.transaction_signature.value == params.signature” filter.params[“signature”].signature_value.value = <64-byte signature>
-
Filter by program address (using parameter): filter.expression = “has(event.program) && event.program.value == params.address” filter.params[“address”].pubkey_value.value = <32-byte program pubkey>
-
Filter by event ID prefix using startsWith: filter.expression = “event.event_id.startsWith(“ts”)” filter.expression = “event.event_id.startsWith(“ts1000_”)”
-
Check for payload existence: filter.expression = “has(event.payload)”
-
Check for program existence: filter.expression = “has(event.program)”
-
Filter by payload first byte (event type): filter.expression = “has(event.payload) && first1Byte(event.payload) == uint(1)” // MESSAGE events filter.expression = “has(event.payload) && first1Byte(event.payload) == uint(2)” // Other type
-
Filter by payload first 4 bytes (uint32 event type): filter.expression = “has(event.payload) && first4Bytes(event.payload) == uint(2)” // COUNTER events filter.expression = “has(event.payload) && first4Bytes(event.payload) == params.u64” filter.params[“u64”].int_value = 2
-
Filter by payload first 8 bytes (uint64 event type): filter.expression = “has(event.payload) && first8Bytes(event.payload) == uint(6)” // PATTERN events filter.expression = “has(event.payload) && first8Bytes(event.payload) == params.u64” filter.params[“u64”].int_value = 6
-
Filter by payload byte prefix: filter.expression = “bytesPrefix(event.payload, params.prefix)” filter.params[“prefix”].bytes_value = <byte prefix to match>
-
Combine slot and call_idx filters: filter.expression = “event.slot > uint(1000) && event.call_idx == uint(0)”
-
Combine slot, call_idx, and payload existence: filter.expression = “event.slot > uint(1000) && event.call_idx == uint(0) && has(event.payload)”
-
Filter by program and payload type: filter.expression = “has(event.program) && event.program.value == params.address && first1Byte(event.payload) == uint(1)” filter.params[“address”].pubkey_value.value = <32-byte program pubkey>
-
Filter MESSAGE events (type 1) with specific program: filter.expression = “has(event.payload) && first1Byte(event.payload) == uint(1) && event.program.value == params.address” filter.params[“address”].pubkey_value.value = <32-byte program pubkey>
-
Filter COUNTER events (type 2) in slot range: filter.expression = “has(event.payload) && first4Bytes(event.payload) == uint(2) && event.slot >= uint(100) && event.slot <= uint(200)”
-
Filter PATTERN events (type 6) with payload prefix: filter.expression = “has(event.payload) && first8Bytes(event.payload) == uint(6) && bytesPrefix(event.payload, params.prefix)” filter.params[“prefix”].bytes_value = <pattern prefix bytes>
-
Complex combined filter: filter.expression = “(event.slot > uint(1000) && event.call_idx == uint(0)) || first1Byte(event.payload) == uint(1)”
-
Filter events from specific transaction: filter.expression = “event.transaction_signature.value == params.signature && has(event.payload)” filter.params[“signature”].signature_value.value = <64-byte signature>
-
Filter by multiple payload type options: filter.expression = “has(event.payload) && (first1Byte(event.payload) == uint(1) || first1Byte(event.payload) == uint(2))”
-
Filter nested instruction events: filter.expression = “event.call_idx > uint(0) && has(event.program)”
-
Filter first instruction events only: filter.expression = “event.call_idx == uint(0)”
-
Filter events with payload longer than specific size (using bytesPrefix with empty prefix): filter.expression = “has(event.payload)”
-
Combine has() checks: filter.expression = “has(event.program) && has(event.payload) && has(event.timestamp)”
-
Use inequality operators: filter.expression = “event.slot < uint(10000)” filter.expression = “event.slot <= uint(10000)” filter.expression = “event.call_idx >= uint(0)” filter.expression = “event.block_offset != uint(0)”
-
Filter by timestamp (if available): filter.expression = “has(event.timestamp)”
-
Match specific event ID pattern: filter.expression = “event.event_id.startsWith(“ts1234_0_”)”
-
Complex payload and metadata filter: filter.expression = “event.slot >= params.slot && has(event.payload) && first8Bytes(event.payload) == params.u64 && event.program.value == params.address” filter.params[“slot”].int_value = 1000 filter.params[“u64”].int_value = 6 filter.params[“address”].pubkey_value.value = <32-byte program pubkey>
Note: Filters on slot, call_idx, block_offset, transaction_signature, and program are pushed down to SQL for optimal performance. Payload filters (first1Byte, first4Bytes, first8Bytes, bytesPrefix) are evaluated in-memory on fetched results.
Package: thru.services.v1
Fields
Section titled “Fields”| Field | Type | # | Description |
|---|---|---|---|
filter | thru.common.v1.Filter | 1 · optional | CEL filter expression (OPTIONAL). See message documentation for examples. |
page | thru.common.v1.PageRequest | 2 · optional | |
version_context | thru.common.v1.VersionContext | 3 · optional | |
min_consensus | thru.common.v1.ConsensusStatus | 4 · optional |