Skip to main content

Who it’s for

Teams building trading terminals, charting UIs, market-data backends, and trading bots need live, owned market data keyed by pool/pair or by token. The goal is your own market-data store: every fill on a pool, every trade touching a token, OHLCV candles, current pool reserves, and a USD mark for every asset, all reorg-safe and current at the chain head.

The recipe bundle

This use case combines the markets recipes. Swaps by Pair is the trade backbone (one row per fill); Pair OHLCV is a downstream aggregation of that same trade ingest; Swaps by Token re-keys the trades for token-centric views; Pair Reserves and Token Prices add live state and valuation.
Swaps by Pair, Swaps by Token, and Pair OHLCV share one trade projection. They are the same trade ingest shaped three ways: one row per fill keyed by pool, the same fills re-keyed by token, and those fills bucketed into candles. Pick the keys your screens read; you don’t need all three if one access pattern covers your UI.

How the pieces fit

  • The swap recipes all draw from the same normalized in-block trade events, direct pool fills (tokenSwaps) and aggregator-routed trades (aggregateTokenSwaps), so every fill lands exactly once. Key by pool for a pool’s tape, by token for a token’s tape.
  • Pair OHLCV is a downstream aggregation of that ingest: the same trades land, then a candle surface buckets them per (pool, hour). “Price” per fill is the bought-leg in-block USD mark; volume is summed notional; trades is the count.
  • Pair Reserves reads the pool’s absolute token0PostBalance / token1PostBalance from each swap, so current reserves are simply the latest observation per pair: live depth without reconstructing a running sum.
  • Token Prices is the connective tissue for valuation: join any trade, balance, or position to the token’s mark, and use the latest-mark dictionary to value quiet positions with no fresh update.

Building a pool overview

A trading terminal’s pool screen wants the live tape, the candles, the current depth, and a mark: each from its own recipe, keyed by the same pool. Read ClickHouse with FINAL or a sign-aware aggregate so reorg ±1 pairs collapse before you aggregate; never a bare WHERE sign = 1. The trade tape for a pool, newest first:
The hourly candles backing the chart (fast sign-aware accelerator):
The current depth (latest reserves; FINAL collapses reorg pairs before argMax):
And the latest USD mark for either side, via the Token Prices dictionary (O(1), refreshes every 30–60s, no fresh trade required):
For a token’s market overview across all its pools, swap fact_swaps_by_pair for recipe_swaps_by_token.fact_swaps_by_token keyed on token_address.

Notes and considerations

  • EVM + Solana. The trade, candle, reserve, and price recipes are chain-parametrized. On Solana, repeated logIndex within one instruction means the pool-fill vendor_event_id should be widened (e.g. with the token addresses/amounts) to keep rows distinct; the candle math is chain-agnostic.
  • One trade, two pool addresses. A fill observed both as a direct pool fill (pairAddress) and as part of an aggregator route (aggregatorAddress) appears under both; they are distinct events by design. source_kind (pool_fill vs aggregator) tells them apart.
  • USD is in-block only. Trades, candles, and notional are enriched from same-block tokenPriceUpdates. No cross-block carry-forward. Illiquid or brand-new tokens with no in-block mark leave price_usd / notional_usd NULL (and produce candle gaps for that hour). For valuing quiet positions, use the Token Prices latest-mark dictionary, which carries the last on-chain mark forward.
  • OHLCV is fixed 1-hour and trade-reconstructed. Candles are built from on-chain swap fills, so they can differ slightly from a DEX’s own reported OHLC. For other intervals, re-bucket the trade ingest. Use candles for the fast accelerator and candles_exact (over fact_swaps FINAL) when post-reorg precision on high/low matters; volume and trades are sign-weighted and always exact.
  • Reserves need an in-window swap. Current reserves come from swap post-balances, so a pool appears only if it had at least one swap with resolved post-balances in the ingested window. Quiet pools have unchanged reserves by definition. Widen the window to pick them up.
  • Run ClickHouse in hybrid for live terminals. It backfills history then hands off to a seamless, reorg-safe realtime tail at the chain head. Postgres/MySQL are first-class for historical backfill; the trade recipes expand many rows per block, so live/reorg-safe ingestion is ClickHouse-only.
  • Pair with other bundles. Add Swaps by Wallet for per-user trade history, or see Token Analytics and Portfolio Tracking for adjacent recipe bundles.

Get started

Data Feeds is in early access.

Try it today

Build a live, owned market-data backend with the Moralis team.