StreamMempoolTxs - Stream Pre-Consensus Transactions
Stream pre-consensus Hyperliquid client blocks over V3 gRPC. Each record carries signed transaction requests seen before block inclusion, positioned by receive time.
Stream pre-consensus client blocks. A client block is a batch of signed transaction requests that a Hyperliquid node received from its peers before block inclusion. This method is V3-only.
Full Code Examples
Clone our gRPC Code Examples Repository for complete, runnable V3 client setup in Go, Python, and Node.js.
Pre-consensus data
A request in a mempool record is not guaranteed to land in a block. It can still fail, be replaced, be reordered, or never be included. Records carry requests only, with no responses. Use StreamBlocks for committed actions and their responses.
Tokyo region
We guarantee mempool data availability only in our Tokyo region.
When to Use This Method
StreamMempoolTxs is useful for:
- Order-flow monitoring - Observe signed actions before they are committed
- Inclusion analysis - Compare pre-consensus requests with committed blocks
- Latency research - Measure when requests reach the node relative to block time
Method signature
rpc StreamMempoolTxs(StreamRequest) returns (stream Record) {}The mempool feed is positioned by time only. Set position.timestamp (Unix milliseconds) or position.timestamp_ns (Unix nanoseconds); both are inclusive. A positioned call replays from that time and then tails live; an empty request tails newly received client blocks. position.block_number returns INVALID_ARGUMENT, and so does an explicit zero cursor.
The feed is not filterable. ListFeeds advertises no filter_fields for mempool-txs, so any filter constraint returns INVALID_ARGUMENT. The feed does not accept StreamRequest.progress either; setting it returns INVALID_ARGUMENT.
Client receive limits
A record carries one whole client block and can exceed the default 4 MiB gRPC receive limit. Raise the client inbound message limit well above the default, for example grpc.MaxCallRecvMsgSize(64 << 20) in Go.
Response Stream
Each Record carries one client block:
block_numberis always unset. Mempool records are pre-consensus and have no block.timestampis the time the node received the client block, in Unix milliseconds.timestamp_nsis the same receive time at nanosecond precision. Only the mempool feed sets it.datais the source line as bytes. The line is a JSON array, not an object.
Record Format
Decoded Record.data is a two-element array: the receive time, then the client block. Hashes and signatures are truncated below:
["2026-09-28T16:00:01.005217781", {"tx_hash": "0xeb4f...", "signed_actions": [
{"signature": {"r": "0x1dc1...", "s": "0x161d...", "v": 27},
"vaultAddress": "0x31ca...",
"action": {"type": "order", "orders": [{"a": 190, "b": true, "p": "0.040938", "s": "15819", "r": false, "t": {"limit": {"tif": "Alo"}}}], "grouping": "na"},
"nonce": 1790614526470}
]}]| Field | Description |
|---|---|
[0] | Receive time in UTC as an ISO-8601 string with nanosecond precision and no Z suffix |
[1].tx_hash | Hash of the client block |
[1].signed_actions | Signed transaction requests in the client block |
signed_actions[].action | The signed action in the exchange API's action encoding; order actions use the compact a/b/p/s/r/t/c keys. See the action types reference |
signed_actions[].signature | r, s, v signature components |
signed_actions[].nonce | Action nonce |
signed_actions[].vaultAddress | Present when the action acts for a vault or subaccount |
signed_actions[].expiresAfter | Expiry time in Unix milliseconds, when the signer set one |
Records do not include the signer's address, only the signature (and vaultAddress where present), so the feed has no users filter.
Ordering and Delivery
- One
Recordper client block, in the order the node received them. Receive times strictly increased across a 50,000-record sample, but treat that as observed behavior, not a guarantee. - Several client blocks often share one millisecond. Resuming with
position.timestampredelivers every record of that millisecond; deduplicate ontx_hashif that matters. timestamp_nsis the exact cursor. Resuming withposition.timestamp_nsset to the last received value redelivers exactly that one record, then continues.- A cursor before the earliest retained record returns
NOT_FOUND.timestampis compared at millisecond precision,timestamp_nsexactly. - A stream timestamp up to 2 seconds ahead of the server's clock starts a live tail; more than 2 seconds ahead returns
INVALID_ARGUMENT.
Error Handling and Reconnection
Persist the last Record.timestamp_ns that was set and reconnect with StreamRequest.position.timestamp_ns set to it. Replay is inclusive, so skip the one record that matches the saved cursor. A replay can skip a stored record whose timestamp does not parse, without an error.
The feed is high volume: every subscriber receives every client block, several megabytes per second uncompressed. Drain the stream continuously and enable gzip if bandwidth matters.
DATA_LOSS- The stream fell behind the live feed and ended before sending any record after the loss. Reconnect from the lasttimestamp_ns; the replay re-reads the gap. A positioned stream that catches up with live data ends the same way if it then falls behind.UNAVAILABLE- No client blocks arrived before the stream timeout, for example while upstream peers are quiet, or the stream failed mid-stream. Reconnect from the lasttimestamp_ns.DEADLINE_EXCEEDED- The stream could not deliver records in time because the client read too slowly or stopped reading. Reconnect from the lasttimestamp_ns.RESOURCE_EXHAUSTED- From the client library, a record exceeded the client receive limit; raise it before reconnecting, since retrying alone fails again. From the server, replay capacity is temporarily unavailable; retry with backoff.NOT_FOUND- The cursor is outside retained history, or the selected endpoint does not serve the mempool feed. CheckListFeedsformempool-txs.
Once replay has caught up with live data, a growing gap between Record.timestamp and your clock means the client is not keeping up. Process records faster, or the stream ends with DATA_LOSS.
Current Limitations
- Pre-consensus only: Records carry requests without responses, and inclusion is not guaranteed
- No filtering: Every subscriber receives every client block
- Time positioning only:
position.block_numberis rejected; resume ontimestamp_ns - Replay History: Available replay history varies by endpoint. A cursor outside retained history returns
NOT_FOUND
Resources
- GetMempoolTxs - Point-in-time mempool record retrieval
- StreamBlocks - Committed blocks with signed actions and responses
- ListFeeds - Feed inventory and accepted cursor kinds
Need help? Contact our support team or check the Hyperliquid gRPC documentation.
StreamFills - Real-time Fill Streaming
Stream continuous fill data from Hyperliquid L1 Gateway via gRPC. Monitor order executions in real-time.
StreamMiscEvents - Real-time Miscellaneous Event Streaming
Stream non-fill balance-affecting events from Hyperliquid L1 Gateway via gRPC. Filter by user address. Monitor deposits, withdrawals, transfers, staking, and validator rewards in real-time.