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
}
}
| Field | Type | Description |
|---|---|---|
events | string[] | List of event types |
filters | object[] | Filter specifications (see below) |
min_stage | string | Minimum consensus stage (see Finality) |
correlate | boolean | Auto-deliver all events for a transaction (see Finality - Correlation) |
Subscribable Items
Metrics:
| Item | Description | Message format |
|---|---|---|
TPS | Transactions per second | {"seq": N, "TPS": 2450} |
ContentionData | Storage slot contention analysis | {"seq": N, "ContentionData": {...}} |
TopAccesses | Most accessed accounts/slots | {"seq": N, "TopAccesses": {...}} |
Lifecycle | Block stage transitions | {"seq": N, "Lifecycle": {...}} |
Events (25+ types):
| Category | Events | Blocked |
|---|---|---|
| Block lifecycle | BlockStart, BlockEnd, BlockQC, BlockFinalized, BlockVerified, BlockReject | No |
| Block perf | BlockPerfEvmEnter, BlockPerfEvmExit | Yes |
| Transaction | TxnHeaderStart, TxnEvmOutput, TxnEnd, TxnReject | No |
| Transaction detail | TxnHeaderEnd, TxnAccessListEntry, TxnAuthListEntry | Yes |
| Transaction perf | TxnPerfEvmEnter, TxnPerfEvmExit | Yes |
| EVM details | TxnLog, TxnCallFrame, NativeTransfer | No |
| State access | AccountAccessListHeader, AccountAccess, StorageAccess | Yes |
| Errors | RecordError, EvmError | Yes |
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
| Type | JSON | Description |
|---|---|---|
| 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
| Field | Filter type | Applies to | Description |
|---|---|---|---|
txn_index | Range | TxnLog | Transaction index within the block |
log_index | Range | TxnLog | Log index within the transaction |
address | Exact match | TxnLog | Address of the contract emitting the event |
topics | Array prefix | TxnLog | Log topics (topic[0] = event signature) |
sender | Exact match | TxnHeaderStart | Transaction sender |
to | Exact match | TxnHeaderStart | Transaction recipient |
function_selector | Exact match | TxnHeaderStart | First 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.