StreamBlocksRequest
StreamBlocksRequest subscribes to real-time block updates.
Filter expressions support the following params:
-
params.slot (int64): Slot number for comparison Example: block.block.header.slot == params.slot
-
params.min_slot (int64): Minimum slot for range filtering Example: block.block.header.slot >= params.min_slot
-
params.start_slot (int64): Starting slot for filtering Example: block.block.header.slot >= params.start_slot
-
params.u64 (int64): Generic 64-bit value for numeric comparisons Examples: block.block.header.max_compute_units > params.u64 block.block.header.bond_amount_lock_up >= params.u64
-
params.producer (bytes|Pubkey): Producer pubkey for filtering Examples: block.block.header.producer.value == params.producer has(block.block.header.producer) && block.block.header.producer.value == params.producer
Available block header fields: block.block.header.slot, block.block.header.version, block.block.header.start_slot, block.block.header.expiry_after, block.block.header.max_block_size, block.block.header.max_compute_units, block.block.header.max_state_units, block.block.header.bond_amount_lock_up, block.block.header.producer, block.block.header.producer.value
Available block footer fields (populated on the live stream): block.block.footer.signature, block.block.footer.attestor_payment
NOT populated on this stream — do not filter on these here: block.block.footer.status is ALWAYS EXECUTION_STATUS_PENDING; block.block.footer.consumed_compute_units and block.block.footer.consumed_state_units are ALWAYS 0, because StreamBlocks emits blocks at observation time, before execution completes. The CEL engine accepts these paths, but filters on them never match meaningfully. For live per-block consumed units use StreamSlotMetrics; for the fully-populated, filterable footer use QueryService.GetBlock / ListBlocks.
Available consensus status field: block.block.consensus_status
Filter expression examples:
-
Filter by specific slot: Expression: “block.block.header.slot == params.slot” Params: {“slot”: 12345}
-
Filter by slot range: Expression: “block.block.header.slot >= params.min_slot” Params: {“min_slot”: 1000}
-
Filter by block version: Expression: “block.block.header.version >= uint(0)”
-
Filter by specific producer: Expression: “has(block.block.header.producer) && block.block.header.producer.value == params.producer” Params: {“producer”: <32-byte pubkey>}
-
Filter by max compute units: Expression: “block.block.header.max_compute_units > uint(0)”
-
Filter by max state units: Expression: “block.block.header.max_state_units > uint(0)”
-
Filter by bond amount lock-up: Expression: “block.block.header.bond_amount_lock_up >= uint(0)”
-
Footer status is PENDING-only on this stream: block.block.footer.status is ALWAYS EXECUTION_STATUS_PENDING here, so a status filter can never select executed blocks. To filter on executed status use QueryService.GetBlock / ListBlocks instead. Note: EXECUTION_STATUS_PENDING = 1, EXECUTION_STATUS_EXECUTED = 2
-
Filter by consensus status: Expression: “block.block.consensus_status == int(2)” Note: CONSENSUS_STATUS_UNSPECIFIED = 0, CONSENSUS_STATUS_OBSERVED = 1, CONSENSUS_STATUS_INCLUDED = 2
-
Check for optional fields presence: Expression: “has(block.block.header) && has(block.block.footer)”
-
Combined filters (multiple conditions): Expression: “block.block.header.slot >= params.min_slot && has(block.block.footer) && block.block.footer.attestor_payment > uint(0)” Params: {“min_slot”: 1000}
-
Numeric comparison with params: Expression: “block.block.header.max_compute_units > params.u64” Params: {“u64”: 1000000}
Package: thru.services.v1
Fields
Section titled “Fields”| Field | Type | # | Description |
|---|---|---|---|
start_slot | uint64 | 1 · optional | |
filter | thru.common.v1.Filter | 2 · optional | |
view | thru.core.v1.BlockView | 3 · optional | |
min_consensus | thru.common.v1.ConsensusStatus | 4 · optional |