barcus indexer api
checking… Robinhood Chain (4663)Real-time launchpad data: REST for initial render, WebSocket deltas for live updates. Everything on this page runs against this deployment — press Run.
Conventions
- Addresses are lowercase
0x…strings. - On-chain amounts are raw-unit strings (uint256-safe): divide quote amounts by
10^quoteDecimalsand token amounts by10^18. Prices (priceQuote, candle OHLC) are already decimal-adjusted floats. - Timestamps are unix milliseconds, except candle
t— unix seconds. - Every chain-derived row carries
confirmed: false until it is 20 blocks deep; a reorg inside that window can drop or rewrite unconfirmed rows.
Lanes
Single mechanic: a bonding-curve launchpad (BarcusLaunchpad UUPS proxy) whose tokens graduate into locked Uniswap V3 1% pools held by the immutable BarcusLocker.
| lane | mechanism | quote | launchpad | locker |
|---|---|---|---|---|
launchpad | launchpad | native ETH (WETH, 18dp) | 0x63ac8e55bee9d545be626b6bcad78f678aa7b29c | 0x0fa85225572b94401fe626f162f9c59ffe457a3d |
REST
GET /feed/:column
One feed column, ordered for the UI: new = newest launch first, bonding = curve progress desc, graduated = graduation time desc.
Served from Redis zsets with a Postgres fallback on cold cache.
→ { column, tokens: TokenSnapshot[], ethUsd }
GET /feed/trending
Coins ranked by the transparent barcus score: 40·log10(1+uniqueTraders) + 25·min(1, liquidityUsd/2000) + 20·progress + 15·tradeDiversity.
Computed at read time (the liquidity term needs ETH→USD). signals maps each address to its score breakdown. With ethUsd null the liquidity term contributes 0.
→ { column: 'trending', tokens: TokenSnapshot[], signals: { [addr]: Signals }, ethUsd }
GET /tokens/:address
Full snapshot for one token (identity + live curve state).
400 on a malformed address, 404 when unknown.
→ { token: TokenSnapshot, ethUsd }
GET /tokens/:address/holders
Trade-derived holder balances: top 100 plus concentration stats (top-10 %, creator %).
An ESTIMATE by construction: only indexed launchpad trades count, so post-graduation Uniswap swaps and raw ERC-20 transfers are invisible (hence estimate: true). Buys credit the recipient, sells debit the trader. 404 for unknown tokens.
→ { token, creator, holders: [{address, balance, pct}], holderCount, totalHeld, top10Pct, top10PctExCreator, creatorBalance, creatorPct, estimate }
GET /tokens/:address/trades
Trade history, newest first, keyset-paginated.
Pass the returned nextCursor back as cursor for the next (older) page; null means you reached the first trade. 404 for unknown tokens — mind that quoteToken (WETH) is not a launched token.
→ { trades: TradeRow[], nextCursor: string | null }
GET /tokens/:address/candles
OHLCV candles, computed from trades at read time (nothing to lag or roll back after reorgs).
Ascending, empty buckets omitted. Opens stitch to the previous bucket's close (the first-ever bucket opens at its own first trade). Keep the newest candle live by applying trade deltas from the token:0x… WS channel. A full page returns nextBefore — pass it back as before for older history. 404 for unknown tokens.
→ { interval, candles: Candle[], nextBefore: number | null }
GET /trades/recent
Latest trades across all tokens (the global ticker).
→ { trades: TradeDelta[] }
GET /wallets/:address
Wallet overview: profile trade stats + portfolio positions with average-cost PNL.
Derived figures are decimal floats in QUOTE (ETH) units — multiply by ethUsd for dollars. Cost basis is average buy price and only claimed when the indexer saw the buys (costBasisKnown); a missing price can't masquerade as price = 0 (priceKnown). Open bags sort first (value desc), then closed positions by realized PNL. Returns empty positions (200) for wallets that never traded.
→ { address, stats: {coinsTraded, buys, sells, firstTradeAt, lastTradeAt}, positions: WalletPosition[], totals, estimate, ethUsd }
GET /creators/:address
Creator reputation surface: launch count, lifetime claimed creator fees, and their coins (newest first).
feesClaimedQuoteRaw is the wei-string sum of the launchpad's CreatorFeesClaimed events; unclaimed accruals live on-chain only (read the locker directly). Returns zeros (200) for addresses that never launched.
→ { address, launches, feesClaimedQuoteRaw, feesClaimedQuote, tokens: TokenSnapshot[], ethUsd }
GET /search
Token search: name/symbol substring (trigram-indexed) or 0x… address-prefix lookup.
Ranked exact-symbol first, then prefix matches, then by activity. Minimum 2 characters.
→ { query, tokens: TokenSnapshot[] }
GET /sparklines
Batch mini price series + windowed change % for board rows — one request for up to 50 tokens.
spark holds points bucket closes over the window, forward-filled from the last trade before the window (empty when the token never traded). changePct compares the latest price to the window-start price (or the first in-window trade for younger coins); null when unknowable.
→ { window, points, series: { [addr]: { spark: number[], changePct, lastPrice } } }
GET /stats
Aggregate counts, the ingest cursor, and the current ETH→USD spot.
ethUsd comes from the on-chain USDG/WETH V3 pool (~60s cache) — the only USD source on this chain. It is null when unknowable (e.g. testnet): render “—”, never a fake price.
→ { tokens, trades, graduated, lastProcessedBlock, ethUsd }
GET /health
Liveness: checks Postgres and Redis reachability. ALB target-group health check.
503 with { ok: false } when a dependency is unreachable.
→ { ok, mode, lastProcessedBlock, tokens, trades }
GET /metrics
Prometheus text exposition, scraped task-locally by the Datadog agent sidecar.
Not routed through the ALB — the Run button only works against a task directly (e.g. local compose).
→ text/plain (Prometheus exposition format)
Payload reference
TokenSnapshot
address, curve, pool, creator, quoteToken | lowercase 0x… addresses (curve/pool nullable) |
mechanism / mode / lane | always "launchpad" / "eth" / "launchpad" (single mechanic) |
name, symbol, metadataUri, meta | identity; meta is resolved metadata JSON or null |
quoteDecimals | 18 — the quote is native ETH (represented by the WETH address) |
priceQuote, mcapQuote | decimal-adjusted floats; mcap = price × 1e9 (fixed 1B supply) |
progressBps | bonding-curve progress in basis points (0–10000, of the 800M curve supply) |
graduated, graduatedAt, pool | graduation state; pool is the locked Uniswap V3 1% pool (set at migration) |
buyVolumeQuote, sellVolumeQuote | raw-unit strings — divide by 10^quoteDecimals |
createdAt, lastTradeAt | unix milliseconds |
createdBlock | launch block number (string) |
virtualQuote, virtualToken, tokensSold | post-trade virtual AMM reserves + contract tokensSold (wei strings; reserves null before the first trade — launch seeds apply) |
tradeCount, confirmed | lifetime trades; confirmed = past the confirmation depth |
buys, sells, uniqueTraders | trade-shape signals (uniqueTraders = distinct non-creator actors) — trending-score inputs |
TradeDelta / trade rows
token, trader | lowercase addresses |
isBuy | true = buy, false = sell |
quoteAmount, tokenAmount | raw-unit strings (quote: 10^quoteDecimals, token: 10^18) |
price | decimal-adjusted quote per token (float, null if amount was 0) |
blockNumber, txHash, logIndex | chain coordinates (blockNumber as string) |
ts | block time, unix milliseconds |
confirmed | past the confirmation depth |
Candle
t | bucket start, unix SECONDS (lightweight-charts convention) |
o, h, l, c | decimal-adjusted quote-per-token floats |
v, tv | quote / token volume, raw-unit strings |
n | trades in the bucket |
WalletPosition
token, name, symbol, quoteToken, graduated | coin identity |
buys, sells | this wallet's trade counts on the coin |
tokensBought/Sold, quoteSpentRaw/ReceivedRaw | exact raw-unit strings |
netTokens, avgCostQuote, priceQuote, valueQuote | decimal floats, quote (ETH) units |
realizedQuote, unrealizedQuote, totalPnlQuote | average-cost PNL, quote units — × ethUsd for dollars |
priceKnown, costBasisKnown | honesty flags: false means the figure is 0 because it is UNKNOWN, not zero |
Signals (trending)
uniqueTraders | distinct non-creator counterparties (buys→recipient, sells→trader) |
liquidityUsd | net quote committed (buys − sells) × ethUsd, 0 when ethUsd is null |
progressPct, tradeDiversity | curve progress 0–100; 1 − |buys−sells|/total (anti-wash) |
score | 40·log10(1+traders) + 25·min(1, liq/2000) + 20·progress + 15·diversity, rounded to 0.1 |
WebSocket
Connect to , subscribe to channels, receive a
snapshot per channel, then live delta messages. Deltas carry
absolute state with a global monotonic seq — on a seq gap, resubscribe.
| channel | snapshot payload | delta events |
|---|---|---|
feed:new | TokenSnapshot[] | token_created, token_updated, reorg |
feed:bonding | TokenSnapshot[] | progress_update, graduated, reorg |
feed:graduated | TokenSnapshot[] | graduated, reorg |
trades | TradeDelta[] (latest 50) | trade, reorg |
token:0x… | TokenSnapshot | trade, progress_update, graduated, token_created, token_updated |
| event | data | notes |
|---|---|---|
token_created | TokenSnapshot | new launch |
trade | TradeDelta | every buy/sell, one per fill |
progress_update | TokenSnapshot | coalesced to ≤1/token/500ms, always freshest state |
graduated | TokenSnapshot | curve completed; token moves bonding → graduated |
token_updated | TokenSnapshot | e.g. metadata resolved |
reorg | { depth, fromBlock, tokens[] } | chain rewrote history — refetch listed tokens |
Client → server ops: {"op":"subscribe","channels":[…]},
{"op":"unsubscribe","channels":[…]}, {"op":"ping","id":…} →
pong. Server error codes: bad_json, bad_op,
bad_channel, too_many_subscriptions (max 32
per connection), snapshot_failed. Server pings every 30000ms
(browsers answer automatically).