Pools and liquidity
Pools, charts and analytics
The Pools page, the pool detail page, the Trade chart and the Analytics page all read from the event store: a record of every swap, liquidity add and liquidity removal on every pool the indexer knows, each valued in USD when it was recorded. This page explains what is recorded, how it's valued, and what each number means.
The event store
| What | Recorded from | Kept |
|---|---|---|
| Swaps | Swap events: Uniswap V2/V3/V4, Solidly/Velodrome, Slipstream, Algebra (1.9 and Integral) | 90 days (EVENTS_RETENTION_DAYS) |
| Liquidity adds / removes | V2/Solidly Mint/Burn, V3 Mint/Burn, v4 ModifyLiquidity (token amounts computed from the liquidity delta and the price range) | 90 days |
| Token prices | One sample per token per minute, for every token whose pool moved | 90 days |
| Pool TVL | Every 5 minutes in memory; one row per pool per hour | 90 days |
| Swaps routed through Lane | The Executor's Swapped event, plus the route (legs, venues) decoded from the transaction | Forever |
| Protocol revenue | The FeeCollector's Converted event | Forever |
| Quotes with no route | Each /quote answered 404 no route | 90 days |
It's a SQLite file (data/events.db, on the Railway volume in production), written by the API process as each block is indexed. When the API starts for the first time it also backfills the last EVENTS_BACKFILL_HOURS (default 168 = 7 days), once.
Reorgs: when the indexer rewinds and replays blocks, the events of those blocks are replaced, so orphaned transactions disappear.
How amounts become dollars
- A swap is valued on the side of the pool whose price is most trustworthy: USDC first, then WHYPE, then a verified token, and only then the other token. A memecoin quoted through a thin pool can be "worth" absurd amounts on paper; reading the USDC or WHYPE side avoids that.
- Liquidity and TVL: both sides when both tokens are equally trusted; otherwise twice the trusted side.
- Prices are the router's spot prices at the moment the event is recorded. Backfilled events are valued at backfill-time prices (they're flagged
approxin the database). - Fees of a swap = its USD volume × the pool's fee at that time (the v4 event carries the live fee, including dynamic ones).
Who traded
Pools only see the router contract, not the person. For events recorded live, the store looks up each transaction's sender (wallet, up to 100 transactions per block range). Backfilled events have no wallet.
Pools page
GET /v1/pools lists live pools with a TVL. Filters: venue (uniswap, aero, nest, solidly, a launchpad name), token; sort by tvl, volume24h, fees24h or newest.
| Column in the Figma | Field |
|---|---|
| Pool, pair | base, quote, venue, feeBps |
| TVL | tvlUsd |
| Volume 1h / 4h / 12h / 24h | volumeUsd["1h"] … ["24h"] |
| Fees | fees24hUsd |
| Price, 24h change | priceUsd, change24h (of base) |
| Market cap | marketCapUsd (total supply × price) |
| Age | createdAt |
| Pools for the pair | poolsInPair |
Header totals: GET /v1/pools/stats (TVL, 24h volume, fees, swaps). Open positions is null: counting every LP position on the chain needs position indexing (a wallet's own positions are in /v1/liquidity/positions).
Venue names come from the pool type (Uniswap V2/V3/V4, Aero CL, Nest CL, Solidly), or from venueLabels in the network file, a map from factory, PoolManager or hook address to a name ("0x0c83…": "Kleos"). Fill it on launch day.
How TVL is measured
| Pool type | TVL |
|---|---|
| V2, Solidly | Reserves |
| V3, Slipstream, Algebra | The pool's token balances |
| v4 | The in-range liquidity's virtual reserves (L/√P and L·√P) |
The v4 TVL is approximate: v4 pools don't hold their own balances (the PoolManager holds everything). It's exact for full-range positions (most launchpad pools) and overstates concentrated ones.
Pool detail page
| Element | Route |
|---|---|
| TVL (+7 d change), 24h volume and fees, APR, LP count, creation date | GET /v1/pools/{id}: tvlUsd, tvlChange7d, volumeUsd, fees24hUsd, aprPct, liquidityProviders, createdAt |
| TVL / Volume / Fees charts | GET /v1/pools/{id}/chart?interval=1h|1d&days= |
| Live activity (Swaps, Adds, Removes) | GET /v1/pools/{id}/activity then WS /v1/ws/activity with {"pools": [id]} |
- APR = 24h fees × 365 / TVL: a snapshot, not a promise.
- Liquidity providers counts distinct wallets that added liquidity, from live events only, so it starts at zero after deployment.
- In the activity feed,
typeisbuyorsellof thebasetoken, oradd/remove.
Trade chart
GET /v1/candles?token=&interval= returns OHLC candles of the token's USD price, built from the per-minute samples. Suggested mapping for the chart's buttons:
| Button | interval | Candles |
|---|---|---|
| 1H | 1m | 60 |
| 1D | 15m | 96 |
| 1W | 1h | 168 |
| 1M | 4h | 180 |
A minute without a sample (no pool moved) repeats the previous close. The 24h change is change24h. History starts when the event store does: the chart fills up over time after deployment.
Popular tokens
GET /v1/tokens?sort=volume ranks tokens by 24h volume across all their pools; each token also carries price, change24h and volume24hUsd.
Analytics page and landing numbers
GET /v1/stats:
| Figma | Field |
|---|---|
| Volume routed, swaps, average swap | totals.volumeUsd, totals.swaps, totals.avgSwapUsd |
| "$412.8K saved" | totals.savedUsd |
| Today's projection | today.projectedVolumeUsd (today's pace × 24 h) |
| Daily volume, transactions, revenue | daily[]: volume, swaps, fees |
| Protocol revenue | revenue.convertedUsd (fees converted by the FeeCollector) and totals.feesUsd (fees taken) |
| Most used routes | topRoutes |
| Volume per venue | volumeByVenue30d |
| Share of split swaps | splitShare30d |
| "No lane" | noRoute24h |
| "37 pools scanned" | scanned.pools in each /quote |
Savings are attributed to a swap when the transaction that lands is exactly the one /quote returned (matched by its calldata): the savings computed at quote time are then recorded with the swap. Swaps built by other means (or whose quote is older than the cache) count as volume with no savings.
Liquidity management
Live for Uniswap V3 and V4 (add, remove, collect, my positions, time in range, APR estimate); Aero Slipstream and Nest (Algebra) are built and switch on with their position managers: see Liquidity management.
What's not built
| Figma element | Why | What it needs |
|---|---|---|
| Liquidity on Aero Slipstream and Nest CL on Elysium | Built; waiting for their position managers (Nov 9) | Add them to positionManagers |
| Open positions count | Not built | Indexing of every LP position |
| LANE buybacks, liquidity added, token supply (circulating, locked, burned) | The FeeCollector sends fees to the treasury; the LANE token and its vesting aren't in this repo | The token and vesting contracts, and buyback logic in the FeeCollector |
| Comparison with KyberSwap | Needs their quotes on Elysium | A competitor-quote poller once their Elysium API exists |
| Screener "9 chains" | Lane serves Elysium only | Multichain indexing |