Migrating from QuickNode
Our endpoint is wire-compatible with QuickNode's Hyperliquid gRPC services — the hyperliquid.* proto package. Your generated stubs, message types, and decoding logic work unchanged: the migration is one endpoint string and one auth header, then a side-by-side validation run.
What stays the same
Every QuickNode-shape service is served, same package, same wire format. Nothing in this table requires a code change:
gRPC reflection is enabled on our side too, so grpcurl … list and stub generation straight from the endpoint both work — see SDKs & protos.
The migration
Swap the endpoint
Wherever your client constructs its channel, replace the QuickNode endpoint with ours. TLS over HTTP/2, port 443:
grpc endpointdiffMove auth to x-api-key metadata
Authentication is an API key sent as gRPC metadata on each call — replace whatever credential mechanism your QuickNode setup used with the
x-api-keypair. Keys come from the console; see Authentication.client.pydiffCheck your channel options
Two settings bite migrators in production rather than in the first test:
- Message size. First messages on L4/book streams are full snapshots and can be large — set max receive message size to at least 256 MB.
- Reconnects. Streams are long-lived but not eternal. Reconnect with backoff; a
DATA_LOSSstatus means your consumer fell behind — reconnect, optionally replaying from a block height to backfill the gap.
channel = grpc.secure_channel( "stream.hyperliquidrpc.com:443", grpc.ssl_channel_credentials(), options=[ # full L4/book snapshots can exceed default limits — allow >=256 MB ("grpc.max_receive_message_length", 268_435_456), ],)Validate side by side
Run both endpoints in parallel before cutting over. Trades carry a globally unique
tidand every message carries its block height, so per-block equality is a one-screen script:validate.pypython# run both providers in parallel and diff per-block content.# uses the stubs you already generated — field names per your proto version.import grpc OLD = "your-current-quicknode-endpoint:443"NEW = "stream.hyperliquidrpc.com:443" def trades(endpoint, metadata=()): channel = grpc.secure_channel( endpoint, grpc.ssl_channel_credentials(), options=[("grpc.max_receive_message_length", 268_435_456)], ) stub = StreamingStub(channel) req = StreamDataRequest(stream_type=TRADES, coins=["BTC"]) return stub.StreamData(req, metadata=metadata) old = trades(OLD) # existing authnew = trades(NEW, metadata=(("x-api-key", "YOUR_KEY"),)) # ours # align on a common block height, then compare trade ids per blockfor a, b in zip(old, new): assert a.block_height == b.block_height, (a.block_height, b.block_height) assert {t.tid for t in a.trades} == {t.tid for t in b.trades} print("block", a.block_height, "ok:", len(a.trades), "trades")Let it run through a busy period, then cut over by deleting the old endpoint. Keep the validator around — it is also a fine canary for your own consumer's health.
What you gain
The point of the move is not just parity. Same stubs, more surface:
- Attribution on every fill — trader wallet, realized PnL (
closed_pnl), fee and rebate flag, maker/taker, and position context on the trades stream. - Replay from height — start any stream from a past block to backfill, then continue live without a gap.
- Server-side filtering — subscribe by
coins,wallets, andmarket_type; pay bandwidth only for what you take. - The historical archive, same schema — 1.65B+ order events and 1B+ book updates, queryable with the field names your live code already uses.
- Extra native streams — the flat
hyperliquid_swaps.v1trade schema and the dedicated BTC price ticker.
Also moving RPC?
The same key serves HyperEVM JSON-RPC (standard eth_* set including eth_sendRawTransaction) and the HyperCore /info API — point your existing JSON-RPC client at https://rpc.hyperliquidrpc.com with the x-api-key header and you are done.