Hyperliquid gRPC API
Versioned reference for Dwellir's Hyperliquid V3 raw feeds and market streams, with V2 compatibility guidance and Protocol Buffer contracts.
Dwellir's Hyperliquid gRPC endpoint exposes the V3 raw-feed and typed market-streaming services alongside the V2 compatibility service. Use V3 for new integrations. Existing V2 clients can continue using their generated V2 stubs and the established method URLs in this reference.
How the data surfaces fit together
The gRPC API is the live transport for raw node feeds and derived V3 market views. Start with How Hyperliquid works for the relationship between node files, order books, indexed products, and archives.
Versions and services
| Version | Service | Surface |
|---|---|---|
| V3 | hyperliquid_l1_gateway.v3.HyperliquidL1Gateway | Feed discovery plus seven raw streams and seven raw unary lookups |
| V3 | hyperliquid_l1_gateway.v3.MarketStreaming | Fourteen typed, live market streams |
| V2 | hyperliquid_l1_gateway.v2.HyperliquidL1Gateway | Compatibility surface for the fourteen established raw stream and unary methods |
Download the published contracts as v3.proto and v2.proto. Regenerate client stubs when you change versions; the V2 and V3 packages, request messages, and response messages are different.
curl -fsSLo v3.proto https://www.dwellir.com/docs/hyperliquid/grpc/v3.protoAuthentication
Connect over TLS and pass the API key in the x-api-key metadata header. Keep the endpoint and credential outside source control:
grpcurl -proto v3.proto \
-H "x-api-key: ${DWELLIR_API_KEY}" \
"${HYPERLIQUID_GRPC_ENDPOINT}" \
hyperliquid_l1_gateway.v3.HyperliquidL1Gateway/ListFeedsV3 raw-feed service
The V3 raw service declares fifteen RPCs: ListFeeds, seven server streams, and seven unary lookups.
| Feed concept | Stream | Unary | Source |
|---|---|---|---|
| Configured-feed discovery | ListFeeds | - | Gateway registry |
| Blocks | StreamBlocks | GetBlock | replica_cmds |
| Fills | StreamFills | GetFills | node_fills_by_block |
| Raw book diffs | StreamRawBookDiffs | GetRawBookDiffs | node_raw_book_diffs_by_block |
| Order statuses | StreamOrderStatuses | GetOrderStatuses | node_order_statuses_by_block |
| Miscellaneous events | StreamMiscEvents | GetMiscEvents | misc_events_by_block |
| TWAP statuses | StreamTwapStatuses | GetTwapStatuses | node_twap_statuses_by_block |
| Generated order-book snapshots | StreamOrderbookSnapshots | GetOrderbookSnapshot | Generated snapshot output |
StreamOrderbookSnapshots and GetOrderbookSnapshot are the public methods for generated order-book snapshots. Snapshots intentionally sit outside the raw-feed registry, so absence from ListFeeds does not describe their status. Snapshot availability and maximum response size vary by endpoint. Oversized responses return RESOURCE_EXHAUSTED.
Shared request contract
All raw streams accept StreamRequest; all raw unary methods accept GetRequest.
message Position {
oneof position {
int64 timestamp = 1;
int64 block_number = 2;
}
}
message Filter {
repeated FieldFilter fields = 1;
}
message FieldFilter {
string field = 1;
FilterOp op = 2;
repeated string values = 3;
}
message StreamRequest {
Position position = 1;
Filter filter = 2;
}
message GetRequest {
Position position = 1;
Filter filter = 2;
}Position is inclusive. A positioned stream replays the selected record and all subsequent retained records, then tails live data. A positioned unary call returns the record at the requested block number or the nearest record at or after a timestamp.
Leave position unset to tail new records in a raw stream. For the six registry feeds, an unpositioned unary call waits for the next record written after the call begins; it does not return the most recently stored record. The snapshot contract is different: an unpositioned snapshot stream sends the latest snapshot and then newer snapshots, while an unpositioned GetOrderbookSnapshot returns the latest existing snapshot.
V3 uses block_number and timestamp in Unix milliseconds. V2 uses block_height and timestamp_ms. In V3, explicitly setting either cursor to 0 returns INVALID_ARGUMENT; omit position for the unpositioned behavior. A Record.block_number is the sequential Hyperliquid block number and is never the potentially skipping HyperBFT consensus value in abci_block.round.
Filtering
The fills, raw-book-diffs, order-statuses, and TWAP-statuses feeds accept users and coins field filters. Blocks, miscellaneous events, and order-book snapshots do not accept filters. Use ListFeeds.filter_fields as the deployed capability source for registry feeds.
- Constraints for separate fields use AND semantics.
- Values within one field use OR semantics.
- User addresses match case-insensitively.
- Coin identifiers match case-sensitively.
FILTER_OP_UNSPECIFIEDis treated asFILTER_OP_IN.- Unknown or duplicate fields, empty names, and empty value lists return
INVALID_ARGUMENT. - An unsupported operator returns
UNIMPLEMENTED.
Filtering preserves the raw block envelope and removes non-matching entries from its events array. A streaming filter skips records with zero matching events. A unary filter still returns the selected Record, with data containing an empty events array when no events match.
Raw response and recovery
message Record {
optional int64 block_number = 1;
optional int64 timestamp = 2;
bytes data = 3;
}data is the source record as bytes when no filter is applied. Cursor fields are optional because metadata extraction is best-effort; resume only from a cursor that is present. Streams carry no heartbeat frames. UNAVAILABLE means no new records arrived before the stream timeout. DEADLINE_EXCEEDED means the consumer was too slow; reconnect from the last processed cursor.
Available replay history varies by feed and endpoint. A cursor outside retained history returns NOT_FOUND; use the historical-data products for archival data. RESOURCE_EXHAUSTED means replay capacity is temporarily unavailable; retry with backoff. This also applies to filtered replay.
V3 market-streaming service
MarketStreaming exposes fourteen typed subscriptions:
| Method | Opening behavior |
|---|---|
StreamL2Book | Current full L2 book, then coalesced full snapshots |
StreamBbo | Current top of book per requested coin, then changes |
StreamL2BookDiff | Full-book snapshot per coin, then ordered level diffs |
StreamL4Book | Full L4 snapshot for one coin, then native JSON diffs |
StreamL4OrderUpdates | Typed snapshot frame, then typed order diffs |
StreamTpslUpdates | TP/SL snapshot frame, then lifecycle diffs |
StreamTrades | Live-only normalized trades |
StreamAllFills | Live-only fills across the requested scope |
StreamUserFills | Live-only fills for one user |
StreamBuilderFills | Live-only builder-attributed fills |
StreamLiquidationFills | Live-only liquidation fills |
StreamCandle | Current tracked bucket when available, otherwise the next execution |
StreamAllMids | Current full perp-mid map, then changed maps |
StreamActiveAssetCtx | Current context for one perp, then changes |
These are live subscriptions without historical backfill. One RPC represents one subscription; cancel its context to unsubscribe. Most stateful views open with current state, while trades and all fills-family streams are live-only.
Snapshot-derived views (StreamL2Book, StreamBbo, StreamCandle, StreamAllMids, and StreamActiveAssetCtx) recover from subscriber lag in-band because a later frame supersedes dropped state. Incremental streams terminate with ABORTED on frame loss; reconnect and rebuild from their opening snapshot where provided. StreamL2BookDiff chains seq and prev_seq per coin. Typed L4, TP/SL, and fills-family streams expose a per-subscription sequence; a gap means loss.
Market streams carry no heartbeat frames, and an idle subscription can be healthy. INVALID_ARGUMENT identifies malformed requests, FAILED_PRECONDITION an unavailable feature, UNAVAILABLE a view that is not yet ready or whose latest upstream data is stale, ABORTED lost frames or reset state, and DEADLINE_EXCEEDED a consumer that did not drain promptly.
Prices and sizes are decimal strings. Times are Unix milliseconds. Coin identifiers use native, case-sensitive names such as BTC, @1, and #2. User addresses match case-insensitively. Frame-level time is block time, while per-order timestamp is placement time. StreamAllMids and StreamActiveAssetCtx have no block_number; their time identifies when the endpoint made the update available, not a block or upstream timestamp.
V2 compatibility
V2 retains the fourteen established raw methods and their feed-specific response messages. Its request cursor fields are timestamp_ms and block_height, and its pages remain at the same flat canonical URLs. V2 has no ListFeeds, shared Record, or V3 server-side raw filtering. Each overlapping method page keeps the V2 shape and adds its V3 equivalent.
Client guidance
- Generate stubs from the exact proto version you call.
- Attach
x-api-keymetadata on every RPC and use TLS. - Set deadlines on unary calls, especially unpositioned V3 raw calls that wait for the next record.
- Persist only present V3 cursors and replay inclusively after reconnecting; deduplicate the last committed cursor.
- Drain streams continuously and reconnect with bounded exponential backoff for retryable statuses.
- Seed order-book reconstruction from a snapshot or another known state, then apply ordered diffs. Raw diffs alone are insufficient.
Complete client examples are available in the Dwellir gRPC examples repository. For help with deployment capabilities, contact support@dwellir.com.
hl_getLatestBlockNumber - Get Latest Block Number
Get the highest block number currently available for a HyperCore data stream via the JSON-RPC API.
ListFeeds - Discover V3 Raw Feeds
Discover the raw feeds available from a Hyperliquid V3 gRPC endpoint, including supported cursors and server-side filter fields.