Reading the chain
Everything a terminal, a bot or a chart needs is readable on Robinhood Chain, with no API key and nobody's permission.
Every number this app shows — price, market cap, curve progress, the trade tape — is derived from the chain. None of it is privileged: the same reads are open to anyone, and if this app disappeared tomorrow the data would still be there.
This page is the map. It is what you would implement to put a coin on a trading terminal.
Read it yourself rather than trusting a feed. Everything below is a public view call or an
event log, so any number here can be reproduced from the chain at any block.
The two contracts that matter
LaunchPad created every coin and knows where each one trades. QuoteBookHook prices the leveraged stock tokens those coins are paired against.
You need both, because a coin's price is expressed in a leveraged token, and only the hook knows what that token is worth in dollars.
Finding every coin
The launcher keeps its own list, so there is nothing to crawl:
launchPad.tokenCount() -> uint256
launchPad.allTokens(i) -> addressFor history, index the Launched event instead. It carries the metadata URI — the coin's
image and links — which is deliberately not stored on chain, so the event is the only place
it exists:
event Launched(
address indexed token, address indexed pool, address indexed creator,
uint256 supply, int24 tickLower, int24 tickUpper, uint128 liquidity, string metadataUri
);Finding every market
The hook's books is a mapping and cannot be enumerated, so the list comes from events:
event BookRegistered(bytes32 indexed id, address indexed asset, uint256 assetUnit, bool numeraireIsCurrency0);One per pool opened against the hook. Index those and you have every asset the venue makes a market in, including ones listed after you wrote your integration. Don't hard-code the set.
What state a coin is in
launchPad.launches(token) -> (
address pool, int24 tickLower, int24 tickUpper, uint128 liquidity,
bool tokenIsToken0, bool graduated, address creator, uint64 createdAt,
uint256 threshold, uint16 reserveBps
)
launchPad.curveProgress(token) -> (uint256 raised, uint256 threshold)graduated decides where you read the price from: the v3 curve pool before, the v4 pool
after. raised / threshold is the progress bar, and both numbers come from the coin's own
record — the threshold is fixed at launch, so a coin's finish line is whatever it was on the
day it opened.
pool == address(0) means this launcher did not create that token. That is the check to run
before showing anyone a coin address they were handed somewhere else.
Pricing a coin
Two steps, because a coin does not trade against dollars.
1. The coin's price in its pairing asset, from the pool's sqrtPriceX96:
ratio = (sqrtPriceX96 / 2^96)^2 // token1 base units per token0 base unit
numeraire/coin = tokenIsToken0 ? ratio : 1 / ratio2. The pairing asset's price in dollars, from the book. buyPrice and sellPrice are
USDG base units per 1e18 of the asset; the mid is the fair value between them:
hook.books(bookId) -> (uint128 buyPrice, uint128 sellPrice, uint64 updatedAt, ...)Multiply the two and adjust for decimals: USDG is 6, coins and leveraged tokens are 18. That mismatch is the most common integration bug on this chain.
Two prices that both look right and are not the same number.
The pool's price is where the last trade left the pool. The execution price is what that
trade paid. A buy that walks a long way up a curve pays its average on the way, well below
where it ends up: one buy of 75% of a supply executed at $8.08e-7 and left the pool at
$2.70e-6. Charts and market caps use the pool price; a fills tape uses execution. Mixing
them misstates a coin threefold.
A price sitting on a tick boundary is not a price. A swap that exhausts a curve walks to
the very end of the range, where sqrtPriceX96 squares to 3.4e38 — a coin apparently worth
$2.8e37, seconds before it graduated. Treat the boundaries as "no price", not as a number.
Is the price live?
The book carries its own timestamp, and the venue refuses to trade on a stale one:
hook.books(id).updatedAt // unix seconds of the last quote
hook.maxQuoteAge() // how old a quote may be, in secondsQuotes refresh roughly every 10 seconds. Past maxQuoteAge every fill reverts with
QuoteStale() — so a price derived from an expired quote is a price nobody can actually
trade at. hook.nav() reverts rather than returning a stale number, which makes it the
safer read of the two.
The trade tape
Fills against the book emit an event that describes itself:
event Filled(
bytes32 indexed poolId, address indexed sender, bool takerBuys,
uint256 assetAmount, uint256 numeraireAmount, uint128 buyPrice, uint128 sellPrice
);It carries the two quotes that fill executed against, so the price paid and the spread earned are computable from the log alone — you never have to reconstruct what the market looked like at that block. Anything derived from a current price would value every historic fill at today's number.
HookSwap is emitted alongside it for hook-aware indexers, following the usual convention:
positive amounts flow into the hook, negative flow out, which is how you recover direction.
Coin trades are ordinary Uniswap events — v3 Swap on the curve, v4 on graduated pools.
Keying history by token rather than by pool is what keeps a chart continuous through
graduation: the venue underneath a coin changes, the coin does not.
Market cap and holders
Market cap is the pool price against totalSupply(), which is fixed at 1,000,000,000 and
never changes — there is no mint function after launch.
Holder counts have to come from Transfer logs; nothing on chain keeps a count. Addresses
belonging to the protocol — the curve position, the hook's own inventory, the redemption
wallet — are holders in the ERC-20 sense but are not public float.
Fees
A graduated coin charges 1% on trades, of which 30% goes to the coin's creator. Both are readable rather than assumed:
feeHook.creatorBps() -> uint16
feeHook.treasury() -> addressWant to trade, not just read?
The router is one call to buy or sell any coin, paying in ETH or USDG, with the whole route assembled for you.