Overview
The MEMPOOL_TXS stream provides raw, high-speed access to Hyperliquid's entire mempool: every pending transaction, delivered in real time before it is confirmed and included in a block. By default it is a complete firehose so you can observe the full flow of incoming market activity; server-side filters, including virtual coin and coins fields, let you narrow it to specific markets.
Stream Type: MEMPOOL_TXS
API Availability: gRPC Streaming API only
Filtering: Supported - virtual coin/coins fields plus raw field filters
Volume: Variable - Depends on mempool activity and network congestion
This stream is valuable for:
- MEV Detection - Monitor pending trades to identify potential front-running opportunities
- Transaction Analysis - Analyze transaction patterns and user behavior pre-confirmation
- Order Flow Monitoring - Track incoming orders before they execute
- Network Activity - Monitor mempool congestion and transaction volume
- Testing and Development - Build and test applications against live transaction flow
Each message contains a signed transaction with actions (orders, cancellations, transfers, etc.) that are waiting to be included in the next block.
Data Structure
Each MEMPOOL_TXS event is an array with two elements:
[
"<timestamp>",
{
"signed_actions": [...],
"tx_hash": "0x..."
}
]
Response Fields
| Field | Type | Description |
|---|---|---|
| [0] (timestamp) | string | ISO 8601 timestamp when the transaction entered the mempool |
| [1].tx_hash | string | Transaction hash (0x-prefixed hex string) |
| [1].signed_actions | array | Array of signed action objects - each represents a signed operation in the transaction |
Signed Action Structure
Each element in signed_actions contains:
| Field | Type | Description |
|---|---|---|
| action | object | The action being performed (order, cancel, transfer, noop, etc.) |
| nonce | number | Unique nonce for this transaction to prevent replay attacks |
| signature | object | ECDSA signature with r, s, v components for transaction authentication |
Action Types
The action object has a type field that determines its structure:
Order Action (type: "order")
Used for placing new orders:
| Field | Type | Description |
|---|---|---|
| type | string | "order" - indicates this is an order placement action |
| grouping | string | Order grouping strategy (e.g., "na" for no grouping) |
| orders | array | Array of order objects to be placed |
Order Object Fields:
| Field | Type | Description |
|---|---|---|
| a | number | Asset/coin ID - numerical identifier for the trading pair |
| b | boolean | Buy side - true for buy orders, false for sell orders |
| p | string | Price - limit price for the order |
| r | boolean | Reduce only - true if order can only reduce position |
| s | string | Size - order quantity/amount |
| t | object | Order type configuration (limit, trigger, etc.) |
| c | string | (Optional) Client order ID (cloid) - custom identifier for tracking |
Order Type Object (t field):
// Limit order
{
"limit": {
"tif": "Alo" // Time in force: "Alo", "Ioc", "Gtc"
}
}
// Trigger order (stop loss/take profit)
{
"trigger": {
"isMarket": true,
"tpsl": "sl", // "sl" = stop loss, "tp" = take profit
"triggerPx": "612.18"
}
}
Noop Action (type: "noop")
No-operation transaction (often used for wallet activity or testing):
{
"action": {
"type": "noop"
},
"nonce": 1775736293821,
"signature": { ... }
}
Signature Structure
| Field | Type | Description |
|---|---|---|
| r | string | R component of ECDSA signature (0x-prefixed hex) |
| s | string | S component of ECDSA signature (0x-prefixed hex) |
| v | number | Recovery ID (typically 27 or 28) |
Example Response
[
"2026-04-09T12:07:15.440811159",
{
"signed_actions": [
{
"action": {
"grouping": "na",
"orders": [
{
"a": 122,
"b": false,
"p": "0.05726",
"r": false,
"s": "27989.1",
"t": {
"limit": {
"tif": "Ioc"
}
}
}
],
"type": "order"
},
"nonce": 1775736144931,
"signature": {
"r": "0x...",
"s": "0x...",
"v": 27
}
}
],
"tx_hash": "0x450e9f20970716b990944ee6691f6205ac138df1797138817f0689e0ae9b5bc3"
}
]
This example shows a sell order (IOC - Immediate or Cancel) for asset 122 at price 0.05726 with size 27989.1.
Multiple Actions Example
A transaction can contain multiple signed actions:
[
"2026-04-09T12:07:15.658214500",
{
"signed_actions": [
{
"action": {
"grouping": "na",
"orders": [
{
"a": 1630000,
"b": true,
"c": "0xf7d9661c3bc8db57ce1c7d491ed7e991",
"p": "536.49",
"r": false,
"s": "1",
"t": {
"limit": {
"tif": "Alo"
}
}
}
],
"type": "order"
},
"nonce": 1775736358958,
"signature": { ... }
}
],
"tx_hash": "0x..."
}
]
Use Cases
MEV Detection
Monitor pending orders to identify arbitrage opportunities or front-running risks:
for response in stream:
if response.HasField('data'):
data = json.loads(response.data.data)
timestamp, tx = data[0], data[1]
for signed_action in tx['signed_actions']:
if signed_action['action'].get('type') == 'order':
orders = signed_action['action']['orders']
for order in orders:
asset_id = order['a']
is_buy = order['b']
price = order['p']
size = order['s']
# Analyze order for MEV opportunities
analyze_order(asset_id, is_buy, price, size)
Transaction Monitoring
Track transaction volume and mempool congestion:
tx_count = 0
order_count = 0
for response in stream:
if response.HasField('data'):
data = json.loads(response.data.data)
tx_count += 1
tx_data = data[1]
for signed_action in tx_data['signed_actions']:
if signed_action['action'].get('type') == 'order':
order_count += len(signed_action['action']['orders'])
print(f"Mempool: {tx_count} txs, {order_count} orders")
Filtering
MEMPOOL_TXS supports server-side filtering on the gRPC StreamData method.
Virtual Coin Filters
Raw mempool payloads contain numeric asset IDs rather than a top-level coin field, so the stream exposes virtual coin and coins filter fields. The server resolves market names (for example BTC) to their current asset IDs dynamically, so newly listed markets work without a client-side asset table.
A transaction matches when any order-touching action in it references a requested asset: order, cancel, cancelByCloid, batchModify, modify, twapOrder, and twapCancel. Matching is at the transaction boundary: when one signed action matches, the complete original raw transaction is returned unchanged, including unrelated signed actions in the same payload.
// All pending transactions touching BTC
filters: {
"coin": FilterValues { values: ["BTC"] }
}
// Multiple markets
filters: {
"coins": FilterValues { values: ["BTC", "ETH"] }
}
Raw Field Filters
Standard recursive field filtering also applies to the raw transaction fields:
// Only transactions containing an order action
filters: {
"type": FilterValues { values: ["order"] }
}
// Only transactions referencing raw asset ID 0 (BTC perp)
filters: {
"a": FilterValues { values: ["0"] }
}
Unfiltered consumption returns the entire mempool, and streaming is billed on the data you receive, so apply filters when you do not need the full firehose. For normalized, pre-parsed priority order flow, see ORDER_PRIORITY.
For complete filtering documentation, see Stream Filtering Guide.
gRPC Streaming
Python Example
import grpc
import json
from pb import streaming_pb2, streaming_pb2_grpc
GRPC_ENDPOINT = 'your-endpoint.hype-mainnet.quiknode.pro:10000'
AUTH_TOKEN = 'your-auth-token'
def stream_mempool():
credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel(
GRPC_ENDPOINT,
credentials,
options=[
('grpc.max_receive_message_length', 100 * 1024 * 1024),
]
)
stub = streaming_pb2_grpc.StreamingStub(channel)
metadata = [('x-token', AUTH_TOKEN)]
def request_generator():
# Subscribe to MEMPOOL_TXS
subscribe_request = streaming_pb2.SubscribeRequest()
subscribe_request.subscribe.stream_type = streaming_pb2.StreamType.MEMPOOL_TXS
yield subscribe_request
# Keep connection alive with periodic pings
while True:
time.sleep(30)
ping_request = streaming_pb2.SubscribeRequest()
ping_request.ping.timestamp = int(time.time() * 1000)
yield ping_request
stream = stub.StreamData(request_generator(), metadata=metadata)
for response in stream:
if response.HasField('data'):
data = json.loads(response.data.data)
timestamp, tx = data[0], data[1]
print(f"Mempool TX: {tx['tx_hash']}")
print(f"Time: {timestamp}")
print(f"Actions: {len(tx['signed_actions'])}")
for signed_action in tx['signed_actions']:
action = signed_action['action']
print(f" Action type: {action.get('type')}")
if action.get('type') == 'order':
for order in action['orders']:
side = "BUY" if order['b'] else "SELL"
print(f" {side} asset={order['a']} "
f"price={order['p']} size={order['s']}")
if __name__ == "__main__":
stream_mempool()
JavaScript/Node.js Example
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const GRPC_ENDPOINT = 'your-endpoint.hype-mainnet.quiknode.pro:10000';
const AUTH_TOKEN = 'your-auth-token';
// Load proto file
const packageDefinition = protoLoader.loadSync('streaming.proto');
const proto = grpc.loadPackageDefinition(packageDefinition).hyperliquid;
// Create channel
const credentials = grpc.credentials.combineChannelCredentials(
grpc.credentials.createSsl(),
grpc.credentials.createFromMetadataGenerator((params, callback) => {
const metadata = new grpc.Metadata();
metadata.add('x-token', AUTH_TOKEN);
callback(null, metadata);
})
);
const client = new proto.Streaming(GRPC_ENDPOINT, credentials);
// Subscribe to MEMPOOL_TXS
const call = client.StreamData();
call.on('data', (response) => {
if (response.data) {
const [timestamp, tx] = JSON.parse(response.data.data);
console.log(`Mempool TX: ${tx.tx_hash}`);
console.log(`Time: ${timestamp}`);
tx.signed_actions.forEach(signedAction => {
const action = signedAction.action;
console.log(` Action: ${action.type}`);
if (action.type === 'order') {
action.orders.forEach(order => {
const side = order.b ? 'BUY' : 'SELL';
console.log(` ${side} asset=${order.a} price=${order.p} size=${order.s}`);
});
}
});
}
});
call.on('error', (error) => {
console.error('Stream error:', error);
});
// Send subscription
call.write({
subscribe: {
stream_type: 8 // MEMPOOL_TXS
}
});
// Send periodic pings
setInterval(() => {
call.write({
ping: { timestamp: Date.now() }
});
}, 30000);
Important Notes
- Pending Transactions - These transactions are NOT yet confirmed. They may fail, be cancelled, or never make it into a block
- No Guarantees - Mempool transactions can be reordered, replaced, or dropped
- Full Firehose by Default - Without filters you receive the entire mempool at full speed; use the virtual
coin/coinsfilters to narrow it to specific markets, or ORDER_PRIORITY for normalized priority order flow - High Volume - During active periods, the mempool stream can have high throughput, and billing is based on the data you receive
- Compression - Consider enabling zstd compression on your gRPC channel for bandwidth efficiency
Related Streams
- ORDERS - Confirmed order events after block inclusion
- TRADES - Executed trades after matching
- EVENTS - System events including balance changes
For more information about gRPC streaming setup, see gRPC API Documentation.