Skip to content

StreamBlocksRequest

View as Markdown

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:

  1. Filter by specific slot: Expression: “block.block.header.slot == params.slot” Params: {“slot”: 12345}

  2. Filter by slot range: Expression: “block.block.header.slot >= params.min_slot” Params: {“min_slot”: 1000}

  3. Filter by block version: Expression: “block.block.header.version >= uint(0)”

  4. Filter by specific producer: Expression: “has(block.block.header.producer) && block.block.header.producer.value == params.producer” Params: {“producer”: <32-byte pubkey>}

  5. Filter by max compute units: Expression: “block.block.header.max_compute_units > uint(0)”

  6. Filter by max state units: Expression: “block.block.header.max_state_units > uint(0)”

  7. Filter by bond amount lock-up: Expression: “block.block.header.bond_amount_lock_up >= uint(0)”

  8. 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

  9. Filter by consensus status: Expression: “block.block.consensus_status == int(2)” Note: CONSENSUS_STATUS_UNSPECIFIED = 0, CONSENSUS_STATUS_OBSERVED = 1, CONSENSUS_STATUS_INCLUDED = 2

  10. Check for optional fields presence: Expression: “has(block.block.header) && has(block.block.footer)”

  11. 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}

  12. Numeric comparison with params: Expression: “block.block.header.max_compute_units > params.u64” Params: {“u64”: 1000000}

Package: thru.services.v1

FieldType#Description
start_slotuint641 · optional
filterthru.common.v1.Filter2 · optional
viewthru.core.v1.BlockView3 · optional
min_consensusthru.common.v1.ConsensusStatus4 · optional