Move from raw RPC calls to the Crius API on Robinhood Chain
Replace eth_getLogs scans, slot0 math and Transfer replays with Crius API calls on Robinhood Chain: a mapping table, before/after code and credit costs.
Keep your RPC for writes (eth_sendRawTransaction, gas, nonces) and your own contracts. Replace the reads you index yourself: Swap logs with GET /token/{address}/trades, slot0 and reserve math with /pool/{pool} or /token/{address}/price, Transfer replays with /holders, ERC-20 metadata calls with /token/{address} or /tokens/batch, and eth_subscribe logs with the WebSocket stream.
A Robinhood Chain RPC node answers one question about raw chain state at a time: a block, a log range, a contract call. Market data (prices, trades, candles, holders) is built on top of millions of those answers: decoding every DEX’s events, routing prices to USD, finding the real trader behind routers, replaying transfers, handling reorgs. The Crius API is that work already done, from block 0. This guide maps the RPC reads apps usually build themselves onto single Crius calls, and says which RPC calls to keep.
What to replace, and what to keep
| What you do over RPC | What it takes | Crius call | Credits |
|---|---|---|---|
eth_getLogs for Swap events, then decode and price them | ABIs for Uniswap v2, v3, v4 and each launch curve, pool-to-token maps, decimals, a USD route, block-range caps | /token/{address}/trades | 2 |
| Aggregate swaps into OHLCV | Storage, bucketing, spike filtering | /token/{address}/candles | 2 |
eth_call slot0 / getReserves, then price math | Per pool type; v4 needs the PoolManager and pool id | /pool/{pool}, /token/{address}/price | 1 |
Replay Transfer logs (or balanceOf scans) for holders | Every transfer since the token's first block, kept current | /token/{address}/holders (Free plan) | 2 |
name, symbol, decimals, totalSupply calls | Four calls per token, plus metadata and logos | /token/{address}, /tokens/batch (100 per call) | 1 |
owner(), tax and limit getters, a simulated sell | Per contract; simulation infrastructure | /token/{address}/security | 1 |
eth_subscribe to logs | No replay after a disconnect; reorgs are yours to undo | WebSocket stream: trades:, pools:new, launches:all | 1 per connection |
Keep the RPC for eth_sendRawTransaction, eth_estimateGas, nonces, eth_call against your own contracts and simulations of your own transactions. Crius is read-only.
Endpoints used: GET/token/{address}/trades GET/token/{address}/candles GET/pool/{pool} GET/token/{address}/price GET/token/{address}/holders POST/tokens/batch GET/token/{address}/security
One pool: slot0 math versus one call
The WETH/USDG Uniswap v3 pool, decoded
What is WETH worth in the 0.01% WETH/USDG pool (0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca), and how deep is it?
curl "https://api.crius.sh/v1/robinhood/pool/0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca"const res = await fetch("https://api.crius.sh/v1/robinhood/pool/0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca");const { data, meta } = await res.json();import requests
r = requests.get( "https://api.crius.sh/v1/robinhood/pool/0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca",)body = r.json()print(body["data"])Real response 200 Captured Oct 28, 2026 · 191 lines (arrays trimmed)
{ "data": { "created_block": 1506281, "created_ts": 1783025467340, "currency0": { "address": "0x0bd7d308f8e1639fab988df18a8011f41eacad73", "decimals": 18, "logo": null, "price_usd": 2355.49, "symbol": "WETH" }, "currency1": { "address": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "decimals": 6, "logo": null, "price_usd": 1, "symbol": "USDG" }, "dex": "uniswap_v3", "dynamic_fee": false, "factory": "0x1f7d7550b1b028f7571e69a784071f0205fd2efa", "fee": 100, "fee_bps": 1, "hook": null, "lp": null, "pool": "0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca", "pool_manager": null, "state": { "initialized_ticks": 2234, "last_block": 100409961, "liquidity": 1994488602507464498, "price_0_in_1": 2357.32, "price_1_in_0": 0.000424211, "real_quote_raised": null, "reserve0": 0, "reserve1": 0, "reserves": { "currency0": 3815.33, "currency1": 3821317, "kind": "real" }, "sqrt_price_x96": 3846701614108804881326106, "tick": -198668 }, "stats": { "all_time": { "buy_volume_usd": 13612852311, "buys": 24419328, "first_trade_ts": 1783530660000, "sell_volume_usd": 13597498410, "sells": 23196198, "since": "chain_start", "trades": 47615526, "volume_usd": 27210350721 }, "avg_trade_usd": { "1h": 278.58, "1m": 337.523, "1s": 835.826, "24h": 665.311, "30s": 298.573, "4h": 669.733, "5m": 261.935, "6h": 732.144 }, "buy_volume_usd": { "1h": 3415833, "1m": 55762.5, "1s": 13.1165, "24h": 71952485, "30s": 20837.4, "4h": 27415158, "5m": 336149, "6h": 37164488 }, "buyers": { "1h": 2322, "1m": 87, "1s": 1, "24h": 10385, "30s": 47, "4h": 4124, "5m": 569, "6h": 4935 }, "buys": { "1h": 11720, "1m": 131, "1s": 1, "24h": 105661, "30s": 65, "4h": 38476, "5m": 1420, "6h": 47760 }, "last_trade_ts": 1793225401000, "sell_volume_usd": { "1h": 3448384, "1m": 52919.9, "1s": 12524.3, "24h": 71729997, "30s": 20962.8, "4h": 27060933, "5m": 349335, "6h": 36625426 }, "sellers": { "1h": 2408, "1m": 119, "1s": 7, "24h": 11079, "30s": 54, "4h": 4805, "5m": 556, "6h": 5661 }, "sells": { "1h": 12920, "1m": 191, "1s": 14, "24h": 110302, "30s": 75, "4h": 42864, "5m": 1197, "6h": 53026 }, "traders": { "1h": 3245, "1m": 194, "1s": 8, "24h": 15793, "30s": 97, "4h": 6304, "5m": 894, "6h": 7551 }, "trades": { "1h": 24640, "1m": 322, "1s": 15, "24h": 215963, "30s": 140, "4h": 81340, "5m": 2617, "6h": 100786 }, "txns": { "1h": 24522, "1m": 322, "1s": 15, "24h": 212815, "30s": 140, "4h": 80538, "5m": 2564, "6h": 99706 }, "volume_eth": { "1h": 2908.97, "1m": 46.14, "1s": 5.32262, "24h": 61121.5, "30s": 17.7459, "4h": 23102.1, "5m": 291.015, "6h": 31357.2 }, "volume_usd": { "1h": 6864217, "1m": 108682, "1s": 12537.4, "24h": 143682482, "30s": 41800.2, "4h": 54476091, "5m": 685484, "6h": 73789914 } }, "swaps_indexed": 1956380, "tick_spacing": 1, "tvl_usd": 12808300 }, "meta": { "block": 100409961, "block_age_ms": 1256, "block_ts": 1793225401000, "chain": "robinhood", "finalized_block": 100401329, "lag_ms": 22, "safe_block": 100405028 }}What this tells you
state.sqrt_price_x96(3846701614108804881326106) andstate.tick(−198668) are the raw slot0 values an RPC call returns. Crius also returns the result of the math:state.price_0_in_12357.32 USDG per WETH andprice_1_in_00.000424211.currency0is WETH with 18 decimals,currency1USDG with 6: the decimals you would otherwise fetch with two more calls.fee: 100is 1 basis point (fee_bps: 1).state.reservesholds 3,815.33 WETH and 3,821,317 USDG (kind: "real"), andtvl_usdis 12,808,300.stats.all_timecounts 47,615,526 trades sincefirst_trade_ts1783530660000, with per-window volume and traders from1sto24h: numbers an RPC can’t give you without indexing every swap.
// Before: WETH price from slot0 over JSON-RPC (the public RPC is shared and rate limited: use a provider in production)const RPC = "https://rpc.mainnet.chain.robinhood.com";const POOL = "0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca"; // Uniswap v3 WETH/USDG, 0.01%const rpc = await fetch(RPC, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_call", params: [{ to: POOL, data: "0x3850c7bd" }, "latest"] }), // slot0()});const sqrtPriceX96 = BigInt("0x" + (await rpc.json()).result.slice(2, 66));// token1 per token0, adjusted for WETH's 18 and USDG's 6 decimals (you must already know them)console.log("slot0:", Number((sqrtPriceX96 * sqrtPriceX96 * 10n ** 12n * 10n ** 6n) >> 192n) / 1e6);
// After: the same price, plus reserves, TVL and volume, in one callconst { data } = await (await fetch(`https://api.crius.sh/v1/robinhood/pool/${POOL}`)).json();console.log("crius:", data.state.price_0_in_1, "tvl", data.tvl_usd, "24h volume", data.stats.volume_usd["24h"]);For the sample above, the slot0 math gives 2357.316, the same as price_0_in_1. The difference is everything around it: that’s one pool type, one pool, at the latest block. A token’s USD price needs its deepest pool, the quote’s own USD route and a check that the pool isn’t too thin, which /token/{address}/price does in one call.
Swap logs: what decoding gives you
Three WETH trades, already attributed
What does the decoded version of a Swap log look like?
curl "https://api.crius.sh/v1/robinhood/token/0x0bd7d308f8e1639fab988df18a8011f41eacad73/trades?limit=3"const res = await fetch("https://api.crius.sh/v1/robinhood/token/0x0bd7d308f8e1639fab988df18a8011f41eacad73/trades?limit=3");const { data, meta } = await res.json();import requests
r = requests.get( "https://api.crius.sh/v1/robinhood/token/0x0bd7d308f8e1639fab988df18a8011f41eacad73/trades?limit=3",)body = r.json()print(body["data"])Real response 200 Captured Oct 28, 2026 · 144 lines (arrays trimmed)
{ "data": [ { "amount_base": 0.241346083005198446, "amount_quote": 569.019791, "block": 100406784, "dex": "uniswap_v3", "eth_usd_at_trade": 2356.9, "executor": null, "fees": { "gas": { "gas_price_gwei": 0.021, "gas_used": 239930, "gas_used_l1": 0, "l1_eth": 0, "l2_eth": 0.00000503853, "total_eth": 0.00000503853, "usd": 0.0118753 }, "token_tax": { "pct": null } }, "finality": "latest", "id": "100406784-6-44", "market_cap_usd_at_trade": 90494155, "pool": "0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca", "price_eth": 1.00034, "price_usd": 2357.69, "quote": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "quote_symbol": "USDG", "signer": "0xe950337f36e45c316c53c69a5f285487b54f0bad", "signer_label": null, "trader": "0xe950337f36e45c316c53c69a5f285487b54f0bad", "trader_app": null, "trader_label": "fomo_relayer_3", "ts": 1793225076000, "tx": "0x5b474612139f91cb226cf9e5097244dbb896a86834d8adbd263641c96d67b9f7", "tx_index": 6, "type": "buy", "value_eth": 0.241428, "value_usd": 569.02, "via": [] }, { "amount_base": 0.021222351350879784, "amount_quote": 50.025498, "block": 100406784, "dex": "uniswap_v3", "eth_usd_at_trade": 2356.9, "executor": null, "fees": { "gas": { "gas_price_gwei": 0.021, "gas_used": 455557, "gas_used_l1": 0, "l1_eth": 0, "l2_eth": 0.0000095667, "total_eth": 0.0000095667, "usd": 0.0225477 }, "token_tax": { "pct": null } }, "finality": "latest", "id": "100406784-1-12", "market_cap_usd_at_trade": 90475571, "pool": "0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca", "price_eth": 1.00013, "price_usd": 2357.21, "quote": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "quote_symbol": "USDG", "signer": "0x800539138ff0510191277f6b5c58fb94ae700064", "signer_label": null, "trader": "0x800539138ff0510191277f6b5c58fb94ae700064", "trader_app": null, "trader_label": null, "ts": 1793225076000, "tx": "0x0bde8abf03edce0f2ba13a3398ec2575b177c3f2d85eef77c25c7899a9949311", "tx_index": 1, "type": "sell", "value_eth": 0.0212252, "value_usd": 50.0255, "via": [ "uniswap_universal_router" ] }, { "amount_base": 0.011210844980975568, "amount_quote": 26.431588, "block": 100406782, "dex": "uniswap_v3", "eth_usd_at_trade": 2356.9, "executor": null, "fees": { "gas": { "gas_price_gwei": 0.020904, "gas_used": 315171, "gas_used_l1": 0, "l1_eth": 0, "l2_eth": 0.00000658833, "total_eth": 0.00000658833, "usd": 0.015528 }, "token_tax": { "pct": null } }, "finality": "latest", "id": "100406782-10-32", "market_cap_usd_at_trade": 90493695, "pool": "0x52e65b17fb6e5ba00ed806f37afcd2daa50271ca", "price_eth": 1.00033, "price_usd": 2357.68, "quote": "0x5fc5360d0400a0fd4f2af552add042d716f1d168", "quote_symbol": "USDG", "signer": "0x8a2a3d6fcefd9427ac46b07c91d21207aaa0e168", "signer_label": null, "trader": "0x8a2a3d6fcefd9427ac46b07c91d21207aaa0e168", "trader_app": null, "trader_label": null, "ts": 1793225076000, "tx": "0xa3a9ddaaa96d7cc4d300eb5ae37d174755cee56aec3e5e15ae7c3adf437a113b", "tx_index": 10, "type": "buy", "value_eth": 0.0112146, "value_usd": 26.4316, "via": [ "gmgn_swap_router" ] } ], "meta": { "block": 100406789, "block_age_ms": 367, "block_ts": 1793225077000, "chain": "robinhood", "finalized_block": 100397649, "lag_ms": 7, "next_cursor": "100406782-32", "safe_block": 100401329 }}What this tells you
- Each trade has a
type, amounts in human units (amount_base0.241346083005198446 WETH foramount_quote569.019791 USDG),price_usdandvalue_usd: noint256deltas orsqrtPriceX96to convert. traderis the wallet whose balance changed. The routing is reported separately:via: ["uniswap_universal_router"]andvia: ["gmgn_swap_router"], andtrader_label: "fomo_relayer_3"names known infrastructure.fees.gasgives the L2 and L1 cost in ETH and USD (usd0.0118753 for the first trade), andfinality: "latest"says the block isn’t safe yet.id(100406784-6-44) is block, transaction index and log index, so trades join with logs you already store.
Plan the move
-
List your reads. Group the RPC calls in your app by the question they answer (price, trades, holders, metadata, risk). Each group maps to a row of the table above.
-
Start with the expensive ones. Log scans and transfer replays cost the most to run yourself: Robinhood Chain makes a block about every 100 ms and has passed 100 million blocks, so a full backfill over a shared RPC endpoint can take weeks. Replace those first.
-
Swap subscriptions for the stream.
eth_subscribegives you logs with no replay. The Crius stream adds per-channelseqnumbers, a 60-second resume buffer and explicit reorg messages (trades stream guide). -
Keep identifiers. Addresses are lowercase hex, v4 pools are 32-byte pool ids, trade ids are
block-tx-log, amounts are human units and timestamps unix milliseconds (conventions).
Frequently asked questions
Do I still need an RPC provider if I use Crius?
Only to write to the chain or to read data no index models (your own contracts' state, eth_call simulations of your transactions, gas estimates, nonces). Crius is a read-only API and doesn't relay transactions.
Is an indexed API slower than calling the RPC myself?
An indexer decodes a block before serving it, so there is a small delay. Crius streams events as each block is decoded, typically well under a second after the block, and every REST response reports meta.block, meta.lag_ms and the safe and finalized blocks.
How do reorgs work after migrating?
Every trade carries finality (latest, safe, finalized) and every response meta.safe_block and meta.finalized_block. The stream sends a reorg message and re-sends affected events with removed: true, or holds events until safe if you subscribe with "finality": "safe". See Finality.
Can I migrate gradually?
Yes. Trade ids (block-tx-log) and pool keys (v2/v3 address, v4 pool id) are the chain's own identifiers, so Crius data joins with what you already store. Move one read path at a time and compare.
Related
Get your free Crius API key
Every example on this page works with a free key: higher rate limits than the anonymous plan, holders, wallets and the WebSocket stream. No card needed.
- Robinhood Chain (4663) only, from our own archive nodes
- REST + WebSocket
- Pay on-chain or by card