Migrating from Dwellir
We serve Dwellir's gateway service — robinhoodrpc_l1_gateway.v2.Robinhood ChainL1Gateway — 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:
Reflection is enabled, so grpcurl … list will show the gateway alongside our native packages — see SDKs & protos.
The migration
Swap the endpoint
Replace the Dwellir endpoint with ours wherever the channel is built. 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 your previous credential mechanism with the
x-api-keypair. Keys come from the console; see Authentication.client.pydiffCheck your channel options
- Message size.
StreamOrderbookSnapshotsandGetOrderBookSnapshotresponses 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_LOSSstatus means your consumer fell behind — reconnect, and use the gateway's point-in-timeGetFills/GetBlock(or native replay from height) to close the gap. - History addressing. On Scale,
block_heightreads and replay are retained for up to 6 hours.timestamp_msinputs and order-book snapshot methods resolve to current state; historical timestamp snapshots are not promised.
channel = grpc.secure_channel( "grpc.robinhoodrpc.io:443", grpc.ssl_channel_credentials(), options=[ # order-book snapshots can exceed default limits — allow >=256 MB ("grpc.max_receive_message_length", 268_435_456), ],)- Message size.
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 robinhoodrpc_l1_gateway.v2 stubs you already generated.import grpc OLD = "your-current-dwellir-endpoint:443"NEW = "grpc.robinhoodrpc.io:443" def fills(endpoint, metadata=()): channel = grpc.secure_channel( endpoint, grpc.ssl_channel_credentials(), options=[("grpc.max_receive_message_length", 268_435_456)], ) gateway = Robinhood ChainL1GatewayStub(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 endpointsLet 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
robinhoodrpc_swaps.v1flat 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, the consolidated tape, TWAPs, and funding/liquidation events.
- Server-side filtering and replay — subscribe by coin and wallet; on Scale, 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 — Robinhood Chain JSON-RPC and the the equities REST API API.