Migration

Migrating from Dwellir

We serve Dwellir's gateway service — hyperliquid_l1_gateway.v2.HyperliquidL1Gateway — with compatible service and message types on our endpoint. Generated stubs and response decoding work unchanged; the migration is an endpoint string, an x-api-key header, and a validation run against the history semantics documented here.

What stays the same

The full six-method gateway surface is present. Existing stubs call the same methods; the final column states our precise behavior:

MethodTypeCarriesStatus
StreamBlocksstreamL1 blocks, Dwellir wire formatunchanged
StreamFillsstreamExecuted fills, Dwellir wire formatunchanged
StreamOrderbookSnapshotsstreamCurrent full snapshot every secondcurrent state
GetBlockunaryLatest or retained block_heightUltra · 6h
GetFillsunaryLatest or retained block_heightUltra · 6h
GetOrderBookSnapshotunaryLatest full book snapshotcurrent state

Reflection is enabled, so grpcurl … list will show the gateway alongside our native packages — see SDKs & protos.

The migration

  1. Swap the endpoint

    Replace the Dwellir endpoint with ours wherever the channel is built. TLS over HTTP/2, port 443:

    grpc endpointdiff
    removed: ENDPOINT = "your-current-dwellir-endpoint:443"
    added: ENDPOINT = "stream.hyperliquidrpc.com:443"
  2. Move auth to x-api-key metadata

    Authentication is an API key sent as gRPC metadata on each call — replace your previous credential mechanism with the x-api-key pair. Keys come from the console; see Authentication.

    client.pydiff
    removed: channel = grpc.secure_channel(ENDPOINT, grpc.ssl_channel_credentials())
    removed: gateway = HyperliquidL1GatewayStub(channel)
    removed: fills = gateway.StreamFills(request)
    added: channel = grpc.secure_channel(ENDPOINT, grpc.ssl_channel_credentials())
    added: gateway = HyperliquidL1GatewayStub(channel)
    added: fills = gateway.StreamFills(request, metadata=(("x-api-key", "YOUR_KEY"),))
  3. Check your channel options

    • Message size. StreamOrderbookSnapshots and GetOrderBookSnapshot responses can be large on liquid markets — set max receive message size to at least 256 MB.
    • Reconnects. Streams are long-lived but not eternal; reconnect with backoff. A DATA_LOSS status means your consumer fell behind — reconnect, and use the gateway's point-in-time GetFills / GetBlock (or native replay from height) to close the gap.
    • History addressing. On Ultra, block_height reads and replay are retained for up to 6 hours. timestamp_ms inputs and order-book snapshot methods resolve to current state; historical timestamp snapshots are not promised.
    channel = grpc.secure_channel(    "stream.hyperliquidrpc.com:443",    grpc.ssl_channel_credentials(),    options=[        # order-book snapshots can exceed default limits — allow >=256 MB        ("grpc.max_receive_message_length", 268_435_456),    ],)
  4. Validate side by side

    Run both endpoints in parallel before cutting over. Fills and blocks carry their height, so per-block equality is mechanical:

    validate.pypython
    # run both providers in parallel and diff fills per block.# uses the hyperliquid_l1_gateway.v2 stubs you already generated.import grpc OLD = "your-current-dwellir-endpoint:443"NEW = "stream.hyperliquidrpc.com:443" def fills(endpoint, metadata=()):    channel = grpc.secure_channel(        endpoint,        grpc.ssl_channel_credentials(),        options=[("grpc.max_receive_message_length", 268_435_456)],    )    gateway = HyperliquidL1GatewayStub(channel)    return gateway.StreamFills(StreamFillsRequest(), metadata=metadata) old = fills(OLD)                                          # existing authnew = fills(NEW, metadata=(("x-api-key", "YOUR_KEY"),))   # ours # align on a common block height, then compare per-block fill setsfor a, b in zip(old, new):    assert a.block_height == b.block_height, (a.block_height, b.block_height)    assert {(f.oid, f.px, f.sz) for f in a.fills} == \           {(f.oid, f.px, f.sz) for f in b.fills}    print("block", a.block_height, "ok:", len(a.fills), "fills") # current snapshot methods are easy to spot-check too:# gateway.GetOrderBookSnapshot(Timestamp()) against both endpoints

    Let it run through a busy period — funding intervals and a volatility burst are the interesting cases — then cut over.

What you gain

The gateway gets you migrated; the native packages on the same endpoint and key are why you move:

  • Attribution-rich trades — the hyperliquid_swaps.v1 flat schema adds trader wallet, realized PnL, fees and rebate flag, maker/taker, and position context to every fill: trades stream.
  • Surfaces beyond the gateway order lifecycle, raw book diffs, full L4 book, TWAPs, and funding/liquidation events.
  • Server-side filtering and replay — subscribe by coin and wallet; on Ultra, replay native stream data from a block within the last 6 hours.
  • Manual historical exports — request captured order events or book updates for a confirmed range, using the raw live field names.
  • RPC on the same key HyperEVM JSON-RPC and the HyperCore /info API.