Passer au contenu principal

Stream Filtering Guide

Mis à jour le
Jul 12, 2026

Aperçu

Hyperliquid streaming APIs support powerful filtering capabilities to help you receive only the data you need. Filters work across gRPC, JSON-RPC, and WebSocket protocols, allowing you to subscribe to specific events, users, trading pairs, and more.

Supported Protocols:


  • gRPC Streaming API - High-performance streaming with filters
  • JSON-RPC over WebSocket - Standard WebSocket filtering
  • WebSocket API - Real-time filtered subscriptions

Why Use Filtering?

Without filtering, streaming from Hyperliquid can generate massive amounts of data. The exchange processes thousands of trades, orders, and events per minute across hundreds of trading pairs. Filtering is essential because it allows you to:

  • Reduce bandwidth and improve performance - Receive only relevant data instead of processing everything, significantly reducing network traffic and processing overhead
  • Focus on specific data - Track particular trading pairs, users, or event types instead of consuming all market data
  • Build efficient applications - Create focused applications without overwhelming data streams that could impact performance
  • Enable real-time decision making - Process targeted data faster for alerts, notifications, and trading decisions

Basic Filtering Concepts

Before diving into syntax, here are the key concepts:


  1. Streams - Different data types (trades, orders, events, etc.)
  2. Fields - Properties within each stream that can be filtered
  3. Values - Specific criteria you want to match
  4. Logic - How multiple filters combine (AND/OR)

Simple Example:

"I want to see only BTC trades that are buys (not sells)"

WebSocket Filter: {"coin": ["BTC"], "side": ["B"]}
gRPC Filter: {"coin": {"values": ["BTC"]}, "side": {"values": ["B"]}}

Available Streams

Stream NameDescriptionData Format
tradesFilled trades/executionsTuple: [user_address, fill_data]
ordersOrder status updatesObject with order fields
book_updatesOrder book changesObject with price/size
twap_ordersTWAP order statusesFlexible object
événementsLedger updates, deposits, withdrawals, fundingNested object
writer_actionsSystem actions, spot sendsObject with action type
mempool_txsPending mempool transactions (gRPC only)Tuple: [timestamp, transaction_data]
order_priorityNormalized priority-fee order events (gRPC only)Object with priority order fields
gossip_priorityNormalized gossip-priority bid events (gRPC only)Object with gossip priority fields
blocsRaw replica commands (gRPC only - filter by action type or user)Full block data
StreamL2BookAggregated price levels (gRPC only - coin specified in request)L2BookUpdate protobuf
StreamL4BookIndividual orders (gRPC only - coin specified in request)L4BookUpdate protobuf
StreamBboBookTop-of-book best bid/ask (gRPC only - coins specified in request)BboBookUpdate protobuf
StreamL2BookDiffIncremental L2 price-level changes (gRPC only - coins specified in request)L2BookDiffUpdate protobuf
StreamL4BookUpdatesTyped per-order diffs (gRPC only - coins specified in request)L4BookUpdatesUpdate protobuf
StreamTpslUpdatesTrigger (TP/SL) order updates (gRPC only - coins specified in request)TpslUpdatesUpdate protobuf

Filter Syntax

WebSocket and gRPC APIs use similar filter logic, but with different syntax:


{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"<field_name>": ["<value1>", "<value2>"]
},
"filterName": "optional_name"
},
"id": 1
}

Key points:

  • streamType: Stream name (trades, events, etc.)
  • filters: Each field maps directly to an array of values
  • filterName: Optional name for this filter (enables OR logic, unsubscribe by name)
  • Multiple streams require separate subscription requests

Filter Logic

AND Across Fields

When multiple fields are specified, ALL must match:

// WebSocket
{"filters": {"coin": ["BTC"], "side": ["B"]}}

Returns events where coin=BTC AND side=B

OR Within Field

When multiple values are specified for one field, ANY can match:

// WebSocket
{"filters": {"coin": ["BTC", "ETH", "HYPE"]}}

Returns events where coin=BTC OR coin=ETH OR coin=HYPE

Combined Example

// WebSocket
{"filters": {"coin": ["BTC", "ETH"], "side": ["B"]}}

Returns events where (coin=BTC OR coin=ETH) AND side=B

OR Across Named Filters (Advanced)

Multiple subscriptions with different filterName values on the same stream = OR logic between them.

Request 1:

{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["BTC"],
"side": ["B"]
},
"filterName": "btc_buys"
},
"id": 1
}

Request 2:

{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["ETH"],
"side": ["A"]
},
"filterName": "eth_sells"
},
"id": 2
}

Returns (BTC AND side=B) OR (ETH AND side=A)

This is impossible with a single filter since AND applies across all fields.

Recursive Field Matching

Filters automatically search through nested JSON objects:

// This data:
{"inner": {"LedgerUpdate": {"users": ["0xABC"], "delta": {"type": "deposit"}}}}

// Matches this WebSocket filter:
{"filters": {"type": ["deposit"]}}

Special Filter Values

ValeurSignificationUse Case
"*"Field exists (any value)Find all liquidations: {"liquidation": {"values": ["*"]}}
"exists"Same as "*"Alternative syntax: {"liquidation": {"values": ["exists"]}}
"null"Field is nullFind unfilled TWAPs: {"twapId": {"values": ["null"]}}
Existence Filter Examples
// Find all trades that are liquidations (WebSocket)
{"filters": {"liquidation": ["*"]}}

// Find all trades with a builder (WebSocket)
{"filters": {"builder": ["*"]}}

// Find trades without TWAP ID (WebSocket)
{"filters": {"twapId": ["null"]}}

Stream-Specific Fields

Trades Stream

Filter completed trades and fills by user, trading pair, side, price, and execution details.

Format: Each event is a tuple [user_address, fill_data]

ChampTypeDescriptionExample Filter
utilisateurchaîne de caractèresWallet address (matches tuple first element){"user": {"values": ["0x123..."]}}
pièce de monnaiechaîne de caractèresTrading pair{"coin": {"values": ["BTC", "ETH"]}}
côtéchaîne de caractères"A" (ask/sell) or "B" (bid/buy){"side": {"values": ["B"]}}
pxchaîne de caractèresExecution price{"px": {"values": ["50000"]}}
szchaîne de caractèresSize executed-
dirchaîne de caractèresDirection{"dir": {"values": ["Open Long", "Close Short"]}}
crossedbooléenCrossed the spread{"crossed": {"values": ["true"]}}
fraischaîne de caractèresFee amount-
feeTokenchaîne de caractèresFee token{"feeToken": {"values": ["USDC"]}}
hachagechaîne de caractèresTransaction hash{"hash": {"values": ["0xabc..."]}}
oidnuméroOrder ID{"oid": {"values": ["12345"]}}
tidnuméroTrade ID-
cloidchaîne de caractèresClient order ID (optional){"cloid": {"values": ["0x..."]}}
twapIdnumber/nullTWAP ID if from TWAP{"twapId": {"values": ["*"]}}
builderchaîne de caractèresBuilder address (optional){"builder": {"values": ["0x999..."]}}
builderFeechaîne de caractèresBuilder fee (optional)-
liquidationobjetLiquidation data (optional){"liquidation": {"values": ["*"]}}
liquidation.liquidatedUserchaîne de caractèresLiquidated user address{"liquidatedUser": {"values": ["0x..."]}}
liquidation.methodchaîne de caractèresLiquidation method{"method": {"values": ["market"]}}
liquidation.markPxchaîne de caractèresMark price at liquidation-
Trades Filter Examples
// Get all BTC buys (WebSocket)
{"streamType": "trades", "filters": {"coin": ["BTC"], "side": ["B"]}}

// Get liquidations only (WebSocket)
{"streamType": "trades", "filters": {"liquidation": ["*"]}}

// Get trades for specific user (WebSocket)
{"streamType": "trades", "filters": {"user": ["0x727956612a8700627451204a3ae26268bd1a1525"]}}

// Get TWAP executions only (WebSocket)
{"streamType": "trades", "filters": {"twapId": ["*"]}}

Orders Stream

Monitor order status updates including placements, cancellations, and partial fills.

ChampTypeDescriptionExample Filter
pièce de monnaiechaîne de caractèresTrading pair{"coin": {"values": ["ETH"]}}
côtéchaîne de caractères"A" or "B"{"side": {"values": ["A"]}}
limit_pxchaîne de caractèresLimit price-
szchaîne de caractèresCurrent size-
orig_szchaîne de caractèresOriginal size-
oidnuméroOrder ID{"oid": {"values": ["12345"]}}
horodatagenuméroOrder timestamp-
Orders Filter Examples
// Get all ETH orders (WebSocket)
{"streamType": "orders", "filters": {"coin": ["ETH"]}}

// Get sell orders only (WebSocket)
{"streamType": "orders", "filters": {"side": ["A"]}}

Book Updates Stream

Track order book changes including price level updates and size modifications for bid and ask sides.

ChampTypeDescriptionExample Filter
pièce de monnaiechaîne de caractèresTrading pair{"coin": {"values": ["BTC"]}}
côtéchaîne de caractères"A" (ask) or "B" (bid){"side": {"values": ["B"]}}
pxchaîne de caractèresPrice level-
szchaîne de caractèresSize at level-
Book Updates Filter Examples
// Get BTC bid updates only (WebSocket)
{"streamType": "book_updates", "filters": {"coin": ["BTC"], "side": ["B"]}}

// Get updates for multiple coins (WebSocket)
{"streamType": "book_updates", "filters": {"coin": ["BTC", "ETH", "SOL"]}}

Events Stream

Filter ledger updates including deposits, withdrawals, transfers, vault operations, and funding events.

Note: Events have nested structure with various types.

ChampTypeDescriptionExample Filter
utilisateurstableauAffected users{"users": {"values": ["0x..."]}}
typechaîne de caractèresEvent type{"type": {"values": ["deposit", "withdraw"]}}
usdcchaîne de caractèresUSDC amount-
jetonnuméroToken ID{"token": {"values": ["124"]}}

Common Event Types:

  • deposit - USDC deposit
  • withdraw - USDC withdrawal
  • internalTransfer - Internal transfer
  • spotTransfer - Spot transfer
  • liquidation - Liquidation event
  • funding - Funding payment
  • vaultDeposit / vaultWithdraw - Vault operations
Events Filter Examples
// Get deposits only (WebSocket)
{"streamType": "events", "filters": {"type": ["deposit"]}}

// Get all events for a user (WebSocket)
{"streamType": "events", "filters": {"users": ["0xabc..."]}}

// Get vault operations (WebSocket)
{"streamType": "events", "filters": {"type": ["vaultDeposit", "vaultWithdraw"]}}

Writer Actions Stream

Monitor system actions including spot token transfers, perps operations, and core system activities.

ChampTypeDescriptionExample Filter
utilisateurchaîne de caractèresUser address{"user": {"values": ["0x200..."]}}
NoncenuméroAction nonce-
evm_tx_hashchaîne de caractèresEVM transaction hash{"evm_tx_hash": {"values": ["0x..."]}}
action.typechaîne de caractèresAction type{"type": {"values": ["SystemSpotSendAction"]}}
action.destinationchaîne de caractèresDestination address{"destination": {"values": ["0x..."]}}
action.tokennuméroToken ID{"token": {"values": ["124"]}}
action.weinuméroAmount in wei-

Common Action Types:

  • SystemSpotSendAction - Spot token transfer
  • SystemPerpsAction - Perps system action
  • CoreWriterAction - Core writer action
Writer Actions Filter Examples
// Get spot sends only (WebSocket)
{"streamType": "writer_actions", "filters": {"type": ["SystemSpotSendAction"]}}

// Get actions for specific token (WebSocket)
{"streamType": "writer_actions", "filters": {"token": ["124"]}}

// Get actions for specific user (WebSocket)
{"streamType": "writer_actions", "filters": {"user": ["0x200..."]}}

TWAP Orders Stream

Track Time-Weighted Average Price order status updates including running, completed, and cancelled TWAP orders.

ChampTypeDescriptionExample Filter
utilisateurchaîne de caractèresUser address{"user": {"values": ["0x..."]}}
pièce de monnaiechaîne de caractèresTrading pair{"coin": {"values": ["BTC"]}}
côtéchaîne de caractères"A" or "B"{"side": {"values": ["B"]}}
statutchaîne de caractèresTWAP status{"status": {"values": ["running", "completed"]}}

Blocks Stream

Filter the raw replica_cmds block stream so you receive only blocks that contain activity you care about. Blocks filtering is available on the gRPC StreamData method using stream_type: BLOCKS. Filters are matched recursively against the actions and responses inside each block: a block is delivered when at least one action or response in it matches your filter, and the full block payload is returned unchanged.

ChampTypeDescriptionExample Filter
typechaîne de caractèresHyperCore action type within signed_action_bundles (order, cancel, twapOrder, withdraw3, perpDeploy, and more){"type": {"values": ["order", "twapOrder"]}}
utilisateurchaîne de caractèresAddress that appears in the block (signer or in resps results){"user": {"values": ["0x925a3877cd884b8edf3160192f76c7c251f83856"]}}
Blocks Filter Examples
// Get blocks containing withdrawals (gRPC)
{"streamType": "blocks", "filters": {"type": {"values": ["withdraw3"]}}}

// Get blocks containing a specific user's activity (gRPC)
{"streamType": "blocks", "filters": {"user": {"values": ["0x925a3877cd884b8edf3160192f76c7c251f83856"]}}}

// Get blocks with new market deployments (gRPC)
{"streamType": "blocks", "filters": {"type": {"values": ["perpDeploy"]}}}

Each delivered block still contains all of its actions, not just the matching ones. Use the filter to decide which blocks to receive, then parse abci_block et resps as described in the Blocks dataset page.

MEMPOOL_TXS Stream

Monitor pending mempool transactions before block confirmation. Available via gRPC.

Format: Each event is an array [timestamp, transaction_data]

ChampTypeDescriptionExample Filter
tx_hashchaîne de caractèresTransaction hash{"tx_hash": {"values": ["0x450e9f..."]}}
typechaîne de caractèresAction type (order, noop, etc.){"type": {"values": ["order", "noop"]}}
anuméroAsset ID (for orders){"a": {"values": ["122", "6"]}}
bbooléenBuy side (true=buy, false=sell){"b": {"values": ["true"]}}
pchaîne de caractèresPrice (for orders)-
schaîne de caractèresSize (for orders)-
rbooléenReduce only flag{"r": {"values": ["true"]}}
cchaîne de caractèresClient order ID (optional){"c": {"values": ["0xf7d966..."]}}
NoncenuméroTransaction nonce-
MEMPOOL_TXS Filter Examples
// Get pending orders for specific asset (gRPC)
{"filters": {"type": {"values": ["order"]}, "a": {"values": ["122"]}}}

// Get buy orders only (gRPC)
{"filters": {"b": {"values": ["true"]}, "type": {"values": ["order"]}}}

// Get all order actions (gRPC)
{"filters": {"type": {"values": ["order"]}}}

ORDER_PRIORITY Stream

Monitor normalized priority-fee order events from mempool and confirmed block sources. Available via gRPC StreamData method using stream_type: ORDER_PRIORITY.

Format: Each event is a JSON object with priority-fee order metadata

ChampTypeDescriptionExample Filter
sourcechaîne de caractèresEvent source (mempool_txs or replica_cmds){"source": {"values": ["mempool_txs"]}}
typechaîne de caractèresEvent type (order){"type": {"values": ["order"]}}
pièce de monnaiechaîne de caractèresTrading pair symbol{"coin": {"values": ["BTC", "ETH"]}}
market_typechaîne de caractèresMarket type (e.g., perp){"market_type": {"values": ["perp"]}}
asset_idnuméroAsset ID{"asset_id": {"values": ["0"]}}
pnuméroPriority fee value (10000 = 1 bp){"p": {"values": ["10000", "80000"]}}
côtéchaîne de caractèresOrder side (buy or sell){"side": {"values": ["buy"]}}
tifchaîne de caractèresTime in force (Ioc or Alo){"tif": {"values": ["Ioc"]}}
outcomechaîne de caractèresExecution outcome (e.g., filled) - replica_cmds only{"outcome": {"values": ["filled"]}}
utilisateurchaîne de caractèresUser address{"user": {"values": ["0x..."]}}
broadcasterchaîne de caractèresBroadcaster address{"broadcaster": {"values": ["0x..."]}}
tx_hashchaîne de caractèresTransaction hash{"tx_hash": {"values": ["0x..."]}}
block_numbernuméroBlock number (replica_cmds only){"block_number": {"values": ["581285917"]}}
ORDER_PRIORITY Filter Examples
// Get priority orders for BTC perps (gRPC)
{"filters": {"coin": {"values": ["BTC"]}, "market_type": {"values": ["perp"]}}}

// Get IOC priority orders only (gRPC)
{"filters": {"tif": {"values": ["Ioc"]}, "type": {"values": ["order"]}}}

// Get filled priority orders from confirmed blocks (gRPC)
{"filters": {"source": {"values": ["replica_cmds"]}, "outcome": {"values": ["filled"]}}}

// Get mempool priority activity (gRPC)
{"filters": {"source": {"values": ["mempool_txs"]}}}

GOSSIP_PRIORITY Stream

Monitor normalized gossip/read-priority bid events from mempool and confirmed block sources. Available via gRPC StreamData method using stream_type: GOSSIP_PRIORITY.

Format: Each event is a JSON object with gossip-priority bid metadata

ChampTypeDescriptionExample Filter
sourcechaîne de caractèresEvent source (mempool_txs or replica_cmds){"source": {"values": ["mempool_txs"]}}
typechaîne de caractèresEvent type (gossip){"type": {"values": ["gossip"]}}
GOSSIP_PRIORITY Filter Examples
// Get gossip priority events from mempool (gRPC)
{"filters": {"source": {"values": ["mempool_txs"]}, "type": {"values": ["gossip"]}}}

// Get confirmed gossip priority events (gRPC)
{"filters": {"source": {"values": ["replica_cmds"]}}}

OrderBookStreaming Methods

Le StreamL2Book, StreamL4Book, StreamBboBook, StreamL2BookDiff, StreamL4BookUpdates, et StreamTpslUpdates streams are part of a separate gRPC service (OrderBookStreaming) and use a different filtering model. Instead of the filter object syntax used by StreamData, these streams accept the coin(s) directly as a request parameter:

// L2 - coin specified as a request field
L2BookRequest { coin: "BTC", n_levels: 20 }

// L4 - coin specified as a request field
L4BookRequest { coin: "ETH" }

// BBO - repeated coins; empty means all coins
BboBookRequest { coins: ["BTC", "ETH"] }

// L2 diff - repeated coins; empty means all coins
L2BookDiffRequest { coins: ["BTC"], n_levels: 20 }

// L4 updates - repeated coins; empty means all coins
L4BookUpdatesRequest { coins: ["BTC"] }

// TP/SL updates - repeated coins; empty means all perp coins
TpslUpdatesRequest { coins: ["ETH", "BTC"] }

Key differences from StreamData filtering:


  • gRPC only - OrderBookStreaming methods are not available via WebSocket or JSON-RPC
  • Same coin filtering capabilities - The node accepts the same coin parameters as StreamData
  • Repeated coins on the newer methods - StreamBboBook, StreamL2BookDiff, StreamL4BookUpdates, et StreamTpslUpdates take a repeated coins field where an empty list means all coins (all perp coins for StreamTpslUpdates)

See the StreamL2Book, StreamL4Book, StreamBboBook, StreamL2BookDiff, StreamL4BookUpdates, and StreamTpslUpdates dataset pages for full details.

Filter Limits

Three independent dimensions control what you can subscribe to. The same limits apply to both WebSocket and gRPC:

  • Concurrent streams - how many active streams you can run simultaneously. Plan-tiered.
  • Named filters per stream - how many filterName slots a single stream supports. Plan-tiered.
  • Filter values per field - how many values you can specify per field within one named filter. Server-side constants, the same for all plans.

See Plan Access & FAQ for the full limits table.

Limit error responses

Exceeding the field value cap returns -32602:

{
"error": {
"code": -32602,
"message": "Filter validation failed: Too many values for field 'user': 101 (max: 100)"
}
}

Exceeding the named-filter cap returns -32000:

{
"error": {
"code": -32000,
"message": "Too many named filters per stream: 11 (max: 10)"
}
}

Complete Examples

WebSocket Examples

Basic Subscription
// Subscribe to trades stream
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades"},"id":1}

// Response
{"jsonrpc":"2.0","result":{"subscribed":["trades"]},"id":1}
Filtered Subscriptions
// Filter trades by coin and side
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"coin": ["BTC", "ETH"],
"side": ["B"]
}
},
"id": 1
}

// Get all liquidations
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "trades",
"filters": {
"liquidation": ["*"]
}
},
"id": 1
}

// Get deposits for specific user
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "events",
"filters": {
"type": ["deposit"],
"users": ["0xabc..."]
}
},
"id": 1
}

// Get SystemSpotSendAction events
{
"jsonrpc": "2.0",
"method": "hl_subscribe",
"params": {
"streamType": "writer_actions",
"filters": {
"type": ["SystemSpotSendAction"]
}
},
"id": 1
}
Unsubscribe
// Unsubscribe from specific filter
{"jsonrpc":"2.0","method":"hl_unsubscribe","params":{"filterName":"btc_trades"},"id":2}

// Unsubscribe from stream type
{"jsonrpc":"2.0","method":"hl_unsubscribe","params":{"streamType":"trades"},"id":3}

wscat One-Liners

Quick Testing Commands
# All trades (no filter)
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades"},"id":1}

# BTC trades only
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"coin":["BTC"]}},"id":1}

# Liquidations only
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"liquidation":["*"]}},"id":1}

# Specific user's trades
wscat -c wss://endpoint/ws -w 9999
{"jsonrpc":"2.0","method":"hl_subscribe","params":{"streamType":"trades","filters":{"user":["0x123..."]}},"id":1}

gRPC Examples

gRPC Filter Examples
// JavaScript gRPC example
const request = {
subscribe: {
stream_type: 'TRADES',
filters: {
"coin": { values: ["BTC", "ETH"] },
"side": { values: ["B"] }
}
}
};

// Python gRPC example
request = {
"subscribe": {
"stream_type": "TRADES",
"filters": {
"liquidation": {"values": ["*"]},
"coin": {"values": ["BTC"]}
}
}
}

// Go gRPC example
request := &pb.SubscribeRequest{
Subscribe: &pb.Subscribe{
StreamType: pb.StreamType_TRADES,
Filters: map[string]*pb.FilterValues{
"coin": {Values: []string{"BTC", "ETH"}},
"user": {Values: []string{"0x123..."}},
},
},
}

Response Format

Subscription Confirmation

{"jsonrpc":"2.0","result":{"subscribed":["trades"]},"id":1}

Stream Data

{
"stream": "trades",
"block_number": 817824278,
"data": {
"block_number": 817824278,
"block_time": "2025-12-04T17:00:15.929034389",
"local_time": "2025-12-04T17:00:16.076556955",
"events": [
["0x727956612a8700627451204a3ae26268bd1a1525", {"coin": "HYPE", "side": "B", ...}]
]
}
}

Important Notes


  • Case Sensitivity: Field names and values are case-insensitive ("Coin" = "coin" = "COIN", "btc" = "BTC")
  • Address Matching: Addresses are case-insensitive ("0xABC" = "0xabc")
  • Empty Filters: No filters = receive all events (no filtering applied)
  • Whitespace: Values are automatically trimmed of whitespace
  • Per-Stream Filters: Each stream can have independent filters
  • Recursive Matching: Filters search through nested JSON structures automatically
  • Tuple Format: TRADES stream uses [user, data] format; user filter matches the first element
  • Blocks Stream: The blocks stream supports filtering on the gRPC StreamData method (stream_type: BLOCKS). Filters match recursively, so a block is delivered when any action or response in it matches; the full block is returned.

Partager ce document