Subscriptions & Filters

Simple Format

{"subscribe": ["BlockStart", "BlockEnd", "TPS"]}

A list of event names and/or metrics. Maximum 3 items by default (see limits.max_subscribes in Hello).

Extended Format

{
  "subscribe": {
    "events": ["TxnLog"],
    "filters": [
      {
        "event_name": "TxnLog",
        "field_filters": [
          {"field": "address", "filter": {"values": ["0x0000000000000000000000000000000000001000"]}}
        ]
      }
    ],
    "min_stage": "Finalized",
    "correlate": true
  }
}
FieldTypeDescription
eventsstring[]List of event types
filtersobject[]Filter specifications (see below)
min_stagestringMinimum consensus stage (see Finality)
correlatebooleanAuto-deliver all events for a transaction (see Finality - Correlation)

Subscribable Items

Metrics:

ItemDescriptionMessage format
TPSTransactions per second{"seq": N, "TPS": 2450}
ContentionDataStorage slot contention analysis{"seq": N, "ContentionData": {...}}
TopAccessesMost accessed accounts/slots{"seq": N, "TopAccesses": {...}}
LifecycleBlock stage transitions{"seq": N, "Lifecycle": {...}}

Events (25+ types):

CategoryEventsBlocked
Block lifecycleBlockStart, BlockEnd, BlockQC, BlockFinalized, BlockVerified, BlockRejectNo
Block perfBlockPerfEvmEnter, BlockPerfEvmExitYes
TransactionTxnHeaderStart, TxnEvmOutput, TxnEnd, TxnRejectNo
Transaction detailTxnHeaderEnd, TxnAccessListEntry, TxnAuthListEntryYes
Transaction perfTxnPerfEvmEnter, TxnPerfEvmExitYes
EVM detailsTxnLog, TxnCallFrame, NativeTransferNo
State accessAccountAccessListHeader, AccountAccess, StorageAccessYes
ErrorsRecordError, EvmErrorYes

Blocked = blocked by default.

Subscription Replacement

Each new Subscribe message fully replaces the previous subscription; it is not additive. If you subscribe to ["BlockStart"] and then send ["TPS"], you will only receive TPS. BlockStart is gone.

Identical subscriptions (same content as current) are silently ignored; no snapshot or state change occurs.

Subscription Limit

There is subscription limit. An "item" is any entry in the simple array or the events array in extended format. Metrics (TPS, ContentionData, TopAccesses, lifecycle) and event names (BlockStart, TxnLog, etc.) each count as one item.

When exceeded, the server sends an error:

{"seq": 0, "Error": {"type": "subscribe_limit", "message": "Subscription exceeds limit of 3 items", "limit": 3}}

The current subscription remains unchanged, so this is safe to retry with fewer items. The limit is announced in Hello as limits.max_subscribes.


Server-Side Filters

Filters allow the server to send only the events you need, saving bandwidth.

Filter Types

TypeJSONDescription
Range{"min": N, "max": M}Inclusive range. Both fields are optional.
Exact match{"values": ["0x...", "0x..."]}Match any value in the list.
Array prefix{"values": ["0x...", "0x..."]}The array in the event must start with the specified values.

Available Fields

FieldFilter typeApplies toDescription
txn_indexRangeTxnLogTransaction index within the block
log_indexRangeTxnLogLog index within the transaction
addressExact matchTxnLogAddress of the contract emitting the event
topicsArray prefixTxnLogLog topics (topic[0] = event signature)
senderExact matchTxnHeaderStartTransaction sender
toExact matchTxnHeaderStartTransaction recipient
function_selectorExact matchTxnHeaderStartFirst 4 bytes of calldata

Combination Logic

  • Within a single specification (field_filters): AND, all filters must match
  • Between specifications (filters array): OR, matching any specification is sufficient
(Spec1: event_name AND filter1 AND filter2)
  OR
(Spec2: event_name AND filter3)

Application Order

For each incoming event, the server applies filters in this exact sequence:

Input: Event from ring buffer
  │
  ▼
1. Blacklist (blocked_filters.json)
   Is this event type in the server's blocked list?
   → YES: drop (never delivered regardless of subscription)
   → NO: continue
  │
  ▼
2. Stage gating (min_stage)
   Is the block's commit_stage >= min_stage?
   → NO: drop (event is too early in consensus)
   → YES or null stage: continue
  │
  ▼
3. Event name match
   Is this event type in the subscribe list?
   → NO: continue to step 5 (correlation may still deliver it)
   → YES: continue
  │
  ▼
4. Field filters
   Does any filter specification match? (OR between specs, AND within)
   → NO spec matches: drop
   → YES: deliver
  │
  ▼
5. Correlation check
   Is correlate=true AND this event's txn_idx in the correlation set?
   → YES: deliver (bypasses steps 3-4)
   → NO: drop
  │
  ▼
Output: Deliver or drop

Key insight: Correlation (step 5) can deliver events that would normally be rejected by steps 3-4. But it cannot override the blacklist (step 1) or stage gating (step 2). This means correlated events from blocked types or pre-finality blocks are still dropped.