Connecting
Aleatoric supports five transport methods for accessing Hyperliquid L1 data: two SDKs (Python, TypeScript) and three direct protocols (JSON-RPC, gRPC, Unified Stream SSE, and Disk-Sync WebSocket). This page provides comprehensive, working examples for each one.
All examples assume you have an API key. See Authentication for key provisioning and security details.
Transport Architecture
Section titled “Transport Architecture”The following diagram shows how each transport maps to the Aleatoric data plane:
Each transport connects through the Aleatoric gateway, which handles authentication, rate limiting, and region routing before forwarding requests to the appropriate data service. The transport you choose determines the latency profile, message format, and streaming capabilities available to your application.
Python SDK
Section titled “Python SDK”The fastest path to streaming data. Install with:
pip install hypercore-sdkThe SDK reads your API key from the ALEATORIC_API_KEY environment variable by default, or you can pass it explicitly.
JSON-RPC via SDK
Section titled “JSON-RPC via SDK”from hypercore_sdk import HyperCoreAPI
# Uses ALEATORIC_API_KEY env var by defaultwith HyperCoreAPI() as api: # Block queries block = api.block_number() print(f"Latest block: {block}")
# Mid price lookups btc_mid = api.coin_mid("BTC") eth_mid = api.coin_mid("ETH") print(f"BTC mid: {btc_mid}, ETH mid: {eth_mid}")
# Account balance balance = api.get_balance("0x...") print(f"Balance: {balance}")gRPC Streaming via SDK
Section titled “gRPC Streaming via SDK”import asynciofrom hypercore_sdk import GrpcClient
async def stream_prices(): async with GrpcClient() as grpc: # Stream BTC mid prices (server-streaming RPC) async for price in grpc.mid_price_stream("BTC", max_events=100): print(f"BTC mid: {price.price} @ {price.timestamp}")
# Stream multiple coins concurrently async for price in grpc.mid_price_stream("ETH", max_events=50): print(f"ETH mid: {price.price}")
asyncio.run(stream_prices())For long-running streams, the SDK handles reconnection automatically. The reconnect strategy uses exponential backoff with jitter:
where , , , and is the retry count.
Unified Stream (SSE) via SDK
Section titled “Unified Stream (SSE) via SDK”from hypercore_sdk import UnifiedStreamClient
client = UnifiedStreamClient()
# Stream all eventsfor event in client.sse_events(max_events=50): print(f"{event['event_type']}: {event['payload']}")
# Filter to specific event typesfor event in client.sse_events(types=["trade", "liquidation_warning"], max_events=20): coin = event["payload"].get("coin", "unknown") print(f"[{event['event_type']}] {coin}: {event['payload']}")
# REST endpoints for point-in-time queriesstats = client.stats()print(f"Stream stats: {stats}")
events = client.events(event_type="trade", limit=10)for e in events: print(f"Recent trade: {e}")Explicit Key Configuration
Section titled “Explicit Key Configuration”from hypercore_sdk import HyperCoreAPI, GrpcClient
# Pass key explicitly (overrides env var)with HyperCoreAPI(api_key="ak_live_YOUR_KEY_HERE") as api: print(api.block_number())
# Or set the endpoint for Japan regionwith HyperCoreAPI( api_key="ak_live_YOUR_KEY_HERE", rpc_url="https://rpc-jp.aleatoric.systems",) as api: print(api.block_number())TypeScript SDK
Section titled “TypeScript SDK”Install with:
npm install hypercore-ts-sdkJSON-RPC via SDK
Section titled “JSON-RPC via SDK”import { HyperCoreAPI } from 'hypercore-ts-sdk';
const api = new HyperCoreAPI({ apiKey: process.env.ALEATORIC_API_KEY,});
// Block queriesconst block = await api.blockNumber();console.log('Latest block:', block);
// Mid price lookupsconst btcMid = await api.coinMid('BTC');const ethMid = await api.coinMid('ETH');console.log(`BTC: ${btcMid}, ETH: ${ethMid}`);gRPC Streaming via SDK
Section titled “gRPC Streaming via SDK”import { GrpcClient } from 'hypercore-ts-sdk';
const grpc = new GrpcClient({ apiKey: process.env.ALEATORIC_API_KEY,});
// Stream BTC mid prices with callbackawait grpc.streamMids('BTC', (update) => { console.log(`BTC mid: ${update.price} @ ${update.timestamp}`);}, { maxEvents: 100 });
// Async iterator patternfor await (const update of grpc.midPriceIterator('ETH')) { console.log(`ETH mid: ${update.price}`);}Unified Stream (SSE) via SDK
Section titled “Unified Stream (SSE) via SDK”import { UnifiedStreamClient } from 'hypercore-ts-sdk';
const unified = new UnifiedStreamClient({ apiKey: process.env.ALEATORIC_API_KEY,});
// REST queriesconst stats = await unified.stats();console.log('Stream stats:', stats);
const recentTrades = await unified.events({ event_type: 'trade', limit: 10,});recentTrades.forEach((e) => console.log('Trade:', e));
// SSE streamingconst stream = unified.stream({ types: ['trade', 'funding'] });stream.on('event', (event) => { console.log(`[${event.event_type}]`, event.payload);});stream.on('error', (err) => console.error('Stream error:', err));stream.connect();JSON-RPC (Direct)
Section titled “JSON-RPC (Direct)”Standard EVM-compatible JSON-RPC over HTTPS. No SDK required — any HTTP client works.
Block and State Queries
Section titled “Block and State Queries”# Get latest block numbercurl -s -X POST https://rpc.aleatoric.systems \ -H "Content-Type: application/json" \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Response:# {"jsonrpc":"2.0","id":1,"result":"0x1a4b3f"}# Get account balancecurl -s -X POST https://rpc.aleatoric.systems \ -H "Content-Type: application/json" \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ -d '{ "jsonrpc": "2.0", "method": "eth_getBalance", "params": ["0xYOUR_ADDRESS", "latest"], "id": 2 }'# Get transaction by hashcurl -s -X POST https://rpc.aleatoric.systems \ -H "Content-Type: application/json" \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ -d '{ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", "params": ["0xTXN_HASH"], "id": 3 }'ethers.js (v6)
Section titled “ethers.js (v6)”import { JsonRpcProvider, FetchRequest } from 'ethers';
const API_KEY = process.env.ALEATORIC_API_KEY;
// Custom FetchRequest to inject the API key headerconst fetchReq = new FetchRequest('https://rpc.aleatoric.systems');fetchReq.setHeader('x-api-key', API_KEY);
const provider = new JsonRpcProvider(fetchReq, undefined, { staticNetwork: true, batchMaxCount: 1,});
const blockNumber = await provider.getBlockNumber();console.log('Block:', blockNumber);
const balance = await provider.getBalance('0x...');console.log('Balance:', balance.toString());
// Subscribe to new blocks (polling)provider.on('block', (block) => { console.log('New block:', block);});web3.py
Section titled “web3.py”from web3 import Web3from web3.providers.rpc import HTTPProvider
API_KEY = "ak_live_YOUR_KEY_HERE"
provider = HTTPProvider( "https://rpc.aleatoric.systems", request_kwargs={ "headers": {"x-api-key": API_KEY} },)w3 = Web3(provider)
print(f"Connected: {w3.is_connected()}")print(f"Block: {w3.eth.block_number}")print(f"Balance: {w3.eth.get_balance('0x...')}")gRPC (Direct)
Section titled “gRPC (Direct)”For systems that connect directly via Protocol Buffers without the SDK. Download the proto definitions from the gRPC Reference.
grpcurl (CLI)
Section titled “grpcurl (CLI)”# Health check (no auth required)grpcurl \ hl.grpc.aleatoric.systems:443 \ grpc.health.v1.Health/Check
# Get BTC mid pricegrpcurl \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ hl.grpc.aleatoric.systems:443 \ hyperliquid.PriceService/GetMidPrice \ -d '{"coin": "BTC"}'
# Stream mid prices (server-streaming)grpcurl \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ hl.grpc.aleatoric.systems:443 \ hyperliquid.PriceService/StreamMids \ -d '{"coin": "BTC", "subscription": "allMids"}'
# List available servicesgrpcurl \ -H "x-api-key: ak_live_YOUR_KEY_HERE" \ hl.grpc.aleatoric.systems:443 \ listPython (grpcio)
Section titled “Python (grpcio)”import grpcfrom hypercore_bridge_pb2_grpc import PriceServiceStubfrom hypercore_bridge_pb2 import ( MidPriceRequest, StreamMidsRequest, L2BookRequest,)
API_KEY = "ak_live_YOUR_KEY_HERE"TARGET = "hl.grpc.aleatoric.systems:443"
# TLS channel (required — plaintext is not supported)channel = grpc.secure_channel(TARGET, grpc.ssl_channel_credentials())stub = PriceServiceStub(channel)metadata = [("x-api-key", API_KEY)]
# Unary: get current BTC mid pricemid = stub.GetMidPrice(MidPriceRequest(coin="BTC"), metadata=metadata)print(f"BTC mid: {mid.price}")
# Unary: get L2 order book snapshotbook = stub.GetL2Book( L2BookRequest(coin="BTC", depth=10), metadata=metadata,)for level in book.bids: print(f" Bid: {level.price} x {level.size}")for level in book.asks: print(f" Ask: {level.price} x {level.size}")
# Server-streaming: subscribe to live pricesstream = stub.StreamMids( StreamMidsRequest(coin="BTC", subscription="allMids"), metadata=metadata,)for update in stream: print(f"BTC: {update.price} (t={update.timestamp})")package main
import ( "context" "fmt" "log"
pb "github.com/aleatoric-systems/hypercore-bridge/proto" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata")
func main() { creds := credentials.NewClientTLSFromCert(nil, "") conn, err := grpc.Dial( "hl.grpc.aleatoric.systems:443", grpc.WithTransportCredentials(creds), ) if err != nil { log.Fatal(err) } defer conn.Close()
client := pb.NewPriceServiceClient(conn)
// Attach API key metadata ctx := metadata.AppendToOutgoingContext( context.Background(), "x-api-key", "ak_live_YOUR_KEY_HERE", )
// Unary call resp, err := client.GetMidPrice(ctx, &pb.MidPriceRequest{Coin: "BTC"}) if err != nil { log.Fatal(err) } fmt.Printf("BTC mid: %s\n", resp.Price)
// Server-streaming stream, err := client.StreamMids(ctx, &pb.StreamMidsRequest{ Coin: "BTC", Subscription: "allMids", }) if err != nil { log.Fatal(err) } for { update, err := stream.Recv() if err != nil { break } fmt.Printf("BTC: %s @ %d\n", update.Price, update.Timestamp) }}Unified Stream (SSE)
Section titled “Unified Stream (SSE)”Pre-decoded event feed via Server-Sent Events. The Unified Stream normalizes all Hyperliquid events into a consistent JSON schema, eliminating the need for client-side decoding.
Health Check
Section titled “Health Check”# No auth requiredcurl https://unified.grpc.aleatoric.systems/healthz
# Response: {"status":"ok","uptime_seconds":123456}Streaming Events
Section titled “Streaming Events”# Stream all eventscurl -N -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/stream"
# Filter by event type (comma-separated)curl -N -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/stream?types=trade,liquidation_warning"
# Filter by coincurl -N -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/stream?types=trade&coins=BTC,ETH"Each SSE frame is delivered as a data: line containing a JSON object:
data: {"event_type":"trade","coin":"BTC","price":"98423.50","size":"0.15","side":"buy","ts":1741871234567}
data: {"event_type":"funding","coin":"BTC","rate_bps":"1.23","next_settlement":"2026-03-13T08:00:00Z","ts":1741871235000}REST Endpoints
Section titled “REST Endpoints”The Unified Stream also exposes REST endpoints for point-in-time queries:
# L2 order book snapshotcurl -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/l2-book?coin=BTC&depth=10"
# Consensus pulse (network health)curl -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/consensus-pulse"
# Recent events (paginated)curl -H "x-api-key: ak_live_YOUR_KEY_HERE" \ "https://unified.grpc.aleatoric.systems/api/v1/unified/events?type=trade&limit=50"JavaScript EventSource
Section titled “JavaScript EventSource”const API_KEY = 'ak_live_YOUR_KEY_HERE';const BASE_URL = 'https://unified.grpc.aleatoric.systems';
// Note: native EventSource does not support custom headers.// Use the eventsource package (npm install eventsource) for header support.import EventSource from 'eventsource';
const es = new EventSource( `${BASE_URL}/api/v1/unified/stream?types=trade,liquidation_warning`, { headers: { 'x-api-key': API_KEY } });
es.onmessage = (event) => { const data = JSON.parse(event.data); console.log(`[${data.event_type}] ${data.coin}: ${JSON.stringify(data)}`);};
es.onerror = (err) => { console.error('SSE error:', err); // EventSource reconnects automatically};WebSocket (Disk-Sync)
Section titled “WebSocket (Disk-Sync)”Raw Hyperliquid replica command data over WebSocket. This is the lowest-level transport, delivering the exact command stream from the Hyperliquid validator set. Enterprise tier only.
JavaScript
Section titled “JavaScript”const API_KEY = 'ak_live_YOUR_KEY_HERE';
// Query parameter auth (browser-compatible)const ws = new WebSocket( `wss://disk.grpc.aleatoric.systems?api_key=${API_KEY}`);
ws.onopen = () => { console.log('Connected to Disk-Sync replica stream');};
ws.onmessage = (msg) => { const data = JSON.parse(msg.data); // data.type: 'replica_cmd' | 'heartbeat' // data.raw_hex: hex-encoded Hyperliquid command bytes // data.sequence: monotonically increasing sequence number // data.ts: server-side timestamp (nanoseconds) if (data.type === 'replica_cmd') { console.log(`Seq ${data.sequence}: ${data.raw_hex.slice(0, 40)}...`); }};
ws.onerror = (err) => console.error('WebSocket error:', err);ws.onclose = (event) => { console.log(`Disconnected: code=${event.code} reason=${event.reason}`); // Implement reconnection with backoff};Python (websockets)
Section titled “Python (websockets)”import asyncioimport jsonimport websockets
API_KEY = "ak_live_YOUR_KEY_HERE"
async def disk_sync(): uri = "wss://disk.grpc.aleatoric.systems" headers = {"x-api-key": API_KEY}
async with websockets.connect(uri, extra_headers=headers) as ws: print("Connected to Disk-Sync") async for message in ws: data = json.loads(message) if data["type"] == "replica_cmd": seq = data["sequence"] raw = data["raw_hex"] print(f"[{seq}] {raw[:40]}...") elif data["type"] == "heartbeat": print(f"Heartbeat @ {data['ts']}")
asyncio.run(disk_sync())Note — Disk-Sync delivers raw, unprocessed Hyperliquid commands. Your application is responsible for decoding and interpreting the command bytes. For most use cases, the Unified Stream or gRPC transports provide a better developer experience with pre-decoded data.
Choosing a Transport
Section titled “Choosing a Transport”The right transport depends on your latency requirements, message format preferences, and tier:
| Transport | Latency | Message Format | Streaming | Min. Tier |
|---|---|---|---|---|
| gRPC | p50 | Protobuf (binary) | Server-streaming, bidirectional | Pro |
| Unified Stream (SSE) | event delivery | JSON over SSE | Server-push | Pro |
| JSON-RPC | p50 | JSON over HTTPS | Request-response only | Basic |
| Disk-Sync WebSocket | Raw replica latency | Hex-encoded commands | Full-duplex | Enterprise |
For trading systems where latency is critical, the expected round-trip time for a gRPC unary call is:
For streaming RPCs, the first message incurs the connection setup cost, but subsequent messages arrive with only latency since authentication and connection state are cached.
Region Selection
Section titled “Region Selection”Both US and Japan endpoints are available for all transports. Set the region by changing the endpoint hostname:
| Transport | US Endpoint | Japan Endpoint |
|---|---|---|
| JSON-RPC | rpc.aleatoric.systems | rpc-jp.aleatoric.systems |
| gRPC | hl.grpc.aleatoric.systems:443 | jp.grpc.aleatoric.systems:443 |
| Unified Stream | unified.grpc.aleatoric.systems | unified-jp.grpc.aleatoric.systems |
| Disk-Sync WebSocket | disk.grpc.aleatoric.systems | disk-jp.grpc.aleatoric.systems |
SDK Region Configuration
Section titled “SDK Region Configuration”In the SDKs, switch to the Japan region via environment variables:
export HYPER_RPC_URL=https://rpc-jp.aleatoric.systems/export HYPER_GRPC_TARGET=jp.grpc.aleatoric.systems:443export HYPER_UNIFIED_STREAM_URL=https://unified-jp.grpc.aleatoric.systemsOr configure programmatically:
from hypercore_sdk import HyperCoreAPI
# Japan regionapi = HyperCoreAPI( rpc_url="https://rpc-jp.aleatoric.systems", grpc_target="jp.grpc.aleatoric.systems:443",)import { HyperCoreAPI } from 'hypercore-ts-sdk';
const api = new HyperCoreAPI({ rpcUrl: 'https://rpc-jp.aleatoric.systems', grpcTarget: 'jp.grpc.aleatoric.systems:443',});Connection Best Practices
Section titled “Connection Best Practices”-
Reuse connections — gRPC and WebSocket transports maintain persistent connections. Creating a new connection per request adds unnecessary latency and auth overhead.
-
Handle disconnections — All streaming transports can disconnect due to server deployments, network issues, or idle timeouts. Implement reconnection with exponential backoff.
-
Use the right transport — JSON-RPC for simple queries, gRPC for low-latency streaming, Unified Stream for pre-decoded event feeds, WebSocket for raw replica data.
-
Set timeouts — For JSON-RPC, set a reasonable HTTP timeout (e.g., 10s). For gRPC, use
deadlineortimeoutoptions. Hanging connections consume rate limit tokens. -
Monitor rate limits — Check
X-RateLimit-RemainingandX-RateLimit-Resetresponse headers to proactively back off before hitting the limit.
Next Steps
Section titled “Next Steps”- Python SDK Reference — Full API reference for
hypercore-sdk - TypeScript SDK Reference — Full API reference for
hypercore-ts-sdk - MCP Servers — Connect Aleatoric feeds to AI assistants
- JSON-RPC Reference — Complete method list with request/response schemas
- gRPC Reference — Proto definitions and streaming RPCs
- Rate Limits — Per-tier throughput limits and burst allowances
- Error Codes — Status codes, meanings, and handling strategies