Pairs Cube
What it is
The Pairs cube is one row per pool, quote token and interval: a base token traded against a quote token on one DEX market. Each row carries the pool's OHLC, volume, liquidity and its Ranking in the token's price blend.
It answers two questions: what does this token trade at on its main market, and which pools price it. Pairs is Tokens plus venue and quote identity; there are no Tokens-only fields. If you do not need Market, Pool or QuoteToken, query Tokens instead, it is the cheaper shape for the same price and volume data.
How to get it
The most accurate token price: rank 1
Query the Pairs cube with Ranking: { Position: { eq: 1 } }. This returns the token's price on its top market: the pool holding the largest share of the token's liquidity in the blend, after the staleness discount. It is a single-market price, not a value blended across every pool the token trades in.
Filters that matter:
- Token:
Token: { Address: ..., Network: ... }orToken: { Id: { is: "bid:<chain>:<address>" } }. - Rank:
Ranking: { Position: { eq: 1 } }for the top market,in: [1, 2, 3]for the main venues. - Interval:
Interval: { Time: { Duration: { eq: 60 } } }. Durations are 1, 3, 5, 10, 30, 60, 300, 900, 1800 and 3600 seconds. - Denomination:
Price: { IsQuotedInUsd: true }. Rank 1 selects the market, not the currency the price is quoted in. - A known pool:
Pool: { Address: ... }works on every chain. See theMarket.Addresspitfall below before filtering by market.
Change query to subscription for a stream. The same rows are published on Kafka as trading.prices; see Kafka: trading.prices.
| You want | Use |
|---|---|
| The price of one specific token | Pairs + Ranking: { Position: { eq: 1 } } |
| A firehose of every token on a chain, or one chain-wide number per token | Tokens |
| One number for an asset across all chains (BTC, ETH) | Currencies |
| A specific pool you already know the address of | Pairs + Pool: { Address: ... } |
Why the top market, and not the blended token price
The Tokens cube reports one price per token per chain. That price is a liquidity-weighted blend of every pool where the token is the base asset (see Price Index Algorithm). It is the right answer for a single chain-wide number, and for a token whose liquidity sits in one deep pool it agrees closely with the rank-1 price.
Fragmented tokens behave differently. Thin pools get little weight because they hold little liquidity, but a pool with a large reserve that is stale, or whose reserve is only estimated from volume, can outweigh the pool where the trading actually happens. The blend can then sit at a price nobody is trading at.
Filtering Pairs to Ranking.Position = 1 avoids that. You get one market's quote, the one the index trusts most, which is the closest thing to an executable price.
How it is derived
Quote token choice
Every pair has a base and a quote; the price is quote units per 1 base. Stablecoins win the quote slot, then native tokens. The full rules are in Breaking Down Price Streams in Detail.
A pool's price is the latest trade price, normalised to USD when the quote token has a USD price:
if quoteInUsd {
vol.AveragePrice.Price = vol.AveragePrice.Usd / vol.AveragePrice.BaseAttributedToUsd
} else {
vol.AveragePrice.Price = vol.AveragePrice.Quote / vol.AveragePrice.Base
}
Ranking: how Position and Weight behave
Ranking.Weight is the pool's share of the token's liquidity, after the staleness discount, so the weights of a token's pools sum to 1.
Liquidity.Usd is the measured reserve where one is known (Source real or real_stale), a launch-curve balance (migration), or an estimate from the last hour's decay-weighted volume (volume). For volume pools weight therefore still follows volume. See How liquidity is calculated.
Ranking.Position orders a token's pools by Weight descending. It is a competition rank, not a dense index:
- Ties occur, and are followed by a skipped value.
- Additional gaps appear that ties alone do not explain, so the highest
Positionalways exceeds the row count. Positioncan be0, paired withWeight0.RankingDetail.Verdictis""on such rows: not ranked in this batch.
Normalise before treating weights as shares. Weight is in [0, 1] per row and the per-token sum is centred on 1.0, but it is not guaranteed to equal it; sums above and below 1 both occur. Pools that did not trade in the interval hold weight but have no Pairs row, so the rows you fetch cover only part of the sum.
Weight and Position are recomputed every batch from the current liquidity state, not from the row's own interval. A rank-1 row can report less Volume.Usd for its interval than a lower-ranked row does. On BSC on 2026-10-22, the rank-1 WBNB pool carried 2.9 % of hourly volume and 50.6 % of liquidity; the rank-2 pool carried 78 % of volume.
Verdict gating applies before weighting. Pools the blend rejected (outlier, ineligible, no_price, retired) keep a row and a Position; filter on RankingDetail.Verdict: { is: "priced" } for the pools whose price the token actually uses. See RankingDetail.
Since 2026-10-19 the blend is liquidity-weighted. Rows before that date in the 30-day history are volume-weighted: Liquidity fields are 0 on them and Weight is the pool's share of decay-weighted volume.
Reading Ranking.Weight
Treat Weight as a confidence signal on the blended price:
- Weight close to 1. One pool holds essentially all the liquidity. The blended
Tokensprice and the rank-1 price will be nearly identical, so either works. - Low weight. Liquidity is spread across many pools and the blend mixes all of them. This is where the rank-1 price and the blended price diverge, and the rank-1 price is the one you want.
Fields
| Field | Type | Meaning |
|---|---|---|
Token { Address Id Symbol Name Network NetworkBid IsNative TokenId Did } | String / Boolean | The base token being priced. Id is bid:<chain>:<address>; Address is empty for native assets. |
QuoteToken { ... } | same as Token | The quote token of this row. |
Currency { Id Name Symbol } / QuoteCurrency { ... } | String | The cross-chain currency each token belongs to, for example bid:bitcoin for WBTC. |
Market { Address Id Name Network NetworkBid Program Protocol ProtocolFamily } | String | The DEX market. Address is the factory on EVM and Tron and the pool on Solana; Program is the pool contract on EVM and the DEX program on Solana. |
Pool { Address Id } | String | Address is the portable pool key on every chain. Id is empty except on singleton-contract protocols (Uniswap v4, PancakeSwap Infinity), where it carries the pool identity. |
Block { Date Time Timestamp } | String / DateTime / String | Time of the last update in the interval. |
Interval { Time { Start End Duration } } | DateTime / DateTime / Int | The bar. Duration in seconds. |
Price.Ohlc { Open High Low Close } | Float | OHLC for the interval, from trades with known USD values. |
Price.Average { Estimate Mean SimpleMoving WeightedSimpleMoving ExponentialMoving } | Float | Averages over the interval and a 5-entry moving window. Estimate is the price Supply.MarketCap and FullyDilutedValuationUsd are built from. |
Price.IsQuotedInUsd | Boolean | true: prices in USD. false: prices in quote-token units. |
PoolPrice { Price Ohlc { Open High Low Close } Average { … } Source UpdatedAt } | Float / String / DateTime | The liquidity pool's own price from its curve after the last swap, next to the traded Price. null with Source: "" when the pool reports no price. See PoolPrice fields. |
Volume.Base | Float | Base token amount traded in the interval. |
Volume.Quote | Float | Sum of quote-token amounts. Not USD, even for stablecoin quotes; use Volume.Usd. |
Volume.Usd | Float | Trade volume in USD. |
Volume.BaseAttributedToUsd | Float | Part of Volume.Base traded against quote tokens with a known USD price. Used for the USD average price. |
Liquidity { Usd Source RealShare BaseReserve QuoteReserve QuoteReserveUsd DepthUsd NetQuoteUsd UpdatedAt } | Float / String / DateTime | The pool's balance of the row's quote token, valued in USD, plus how it was measured. See Liquidity fields. |
Ranking { Position Weight } | Int / Float | The pool's rank and liquidity share in the token's blend, above. |
RankingDetail { Verdict StaleMultiplier } | String / Float | Why the pool got that rank. See RankingDetail. |
Supply { CirculatingSupply TotalSupply MaxSupply MarketCap FullyDilutedValuationUsd } | Float | Currency-level figures, repeated on every row of the asset. See Supply fields. |
Row fan-out. One row per (Market.Address, Pool.Address, Pool.Id, QuoteToken.Id) per token per interval, not one row per market. A token quoted against two assets on the same market produces two rows.
Liquidity.Usd values the quote leg only and can be an estimate. Read Liquidity, RankingDetail and LeadingPool fields before ranking pools by it. For full pool state use the chain-level DEXPools cube, or a cloud export for historical depth.
Examples
What is a token's latest price on its top market?
{
Trading {
Pairs(
where: {
Token: {
Address: { is: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" }
Network: { is: "Solana" }
}
Ranking: { Position: { eq: 1 } }
Interval: { Time: { Duration: { eq: 60 } } }
Price: { IsQuotedInUsd: true }
}
limit: { count: 1 }
orderBy: { descending: Block_Time }
) {
Token {
Symbol
Address
}
QuoteToken {
Symbol
}
Market {
Protocol
Address
Network
}
Price {
IsQuotedInUsd
Ohlc {
Open
High
Low
Close
}
}
Ranking {
Position
Weight
}
Volume {
Usd
}
Block {
Time
}
}
}
}
Price.Ohlc.Closeis the token's latest price on its top market.Ranking.Weightsays how much of the token's liquidity that market holds.
How do I stream the top-market price?
Change query to subscription and drop limit/orderBy to receive top-market updates as they happen:
subscription {
Trading {
Pairs(
where: {
Token: {
Address: { is: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" }
Network: { is: "Solana" }
}
Ranking: { Position: { eq: 1 } }
Interval: { Time: { Duration: { eq: 1 } } }
Price: { IsQuotedInUsd: true }
}
) {
Token {
Symbol
Address
}
QuoteToken {
Symbol
}
Market {
Protocol
Address
}
Price {
IsQuotedInUsd
Ohlc {
Close
}
}
Ranking {
Position
Weight
}
}
}
}
- To stream the top market of every token on a chain, replace the
Token.Addressfilter withToken: { Network: { is: "Solana" } }and keep the rank filter. - The rank-1 pool can change mid-stream. Key your state on
Market.Addressfrom each message.
How do I get the top-market price for several tokens at once?
Add limitBy to collapse the result to one current row per token:
{
Trading {
Pairs(
where: {
Token: {
Address: {
in: [
"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263"
"So11111111111111111111111111111111111111112"
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
]
}
Network: { is: "Solana" }
}
Ranking: { Position: { eq: 1 } }
Interval: { Time: { Duration: { eq: 60 } } }
Price: { IsQuotedInUsd: true }
Block: { Time: { since_relative: { minutes_ago: 10 } } }
}
limit: { count: 10 }
limitBy: { by: Token_Id, count: 1 }
orderBy: { descending: Block_Time }
) {
Token {
Symbol
Address
}
QuoteToken {
Symbol
}
Market {
Protocol
}
Price {
Ohlc {
Close
}
}
Ranking {
Position
Weight
}
Block {
Time
}
}
}
}
- Group by
Token_Id, notToken_Address: native assets share an emptyToken.Address. - Widen
minutes_agofor tokens whose top market trades rarely.
How do I get candles for one pool I know the address of?
{
Trading {
Pairs(
where: {Market: {Network: {is: "Solana"}}, Pool: {Address: {is: "58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2"}}, Interval: {Time: {Duration: {eq: 300}}}, Price: {IsQuotedInUsd: true}}
limit: {count: 10}
orderBy: {descendingByField: "Block_Time"}
) {
Market {
Protocol
Program
Network
Name
Address
}
Block {
Date
Time
Timestamp
}
Interval {
Time {
Start
Duration
End
}
}
Volume {
Base
Quote
Usd
}
Supply {
TotalSupply
FullyDilutedValuationUsd
MarketCap
}
Price {
Ohlc {
Close
High
Low
Open
}
IsQuotedInUsd #Are the values in USD or Native
}
}
}
}
- The address is the Raydium AMM v4 SOL/USDC pool. Filter by
Pool.Address, which is the pool on every chain. - One row per quote token of the pool; add
QuoteToken { Symbol }if the pool has more than one.
Pitfalls
Position: { eq: 1 }silently drops tokens. Rank 1 returns only tokens whose top market traded in that interval. A token whose rank-1 market was quiet is omitted, a few percent of tokens per interval, varying by chain. Widen the interval or fall back toTokensfor coverage.- Rank 1 does not imply USD. Always pair the rank filter with
Price: { IsQuotedInUsd: true }, or readIsQuotedInUsdon each row. - The top market can change. Ranking is recomputed every batch as liquidity and staleness change, so a token's rank-1 pool, and its quote token, may flip during a stream. Key your state on
Market.Addressfrom each message. - Always scope the query. An unscoped rank-1 query across a whole chain scans very wide and can time out. Filter by
Token.AddresswithNetwork(orMarket: { NetworkBid: { is: "bid:eth" } }for lower latency), and addBlock: { Time: { since_relative: { minutes_ago: N } } }for broad queries. Chain-wide rank-1 sweeps take a few seconds for a short interval, longer for hour-to-day windows. Price.IsQuotedInUsdselects a denomination, it does not de-duplicate. Markets are not published twice: an unfiltered query returns the USD rendering only, byte-identical toIsQuotedInUsd: true.falsere-renders the same rows in quote-token units; onlyPrice.*changes,Volume,RankingandSupplyare identical. Prices are in USD even when the quote token is WSOL, because the index normalises the quote side; see How Pool Prices Are Normalized.- Group by
Token_Id, notToken_Address. ETH on Ethereum, Arbitrum, Base and Optimism, BNB on BSC and MATIC on Matic all carry""asToken.Address. Grouping by address collapses them into one row. - Want the runner-up markets too? Use
Ranking: { Position: { in: [1, 2, 3] } }to compare a token's main venues, ororderBy: { descending: Ranking_Weight }. Rankingdoes not exist onCurrencies. It is available onTrades,PairsandTokensonly.Market.Addressis not the pool on EVM. It is the protocol factory there, and an empty string for singleton protocols (uniswap_v4, balancer_v2, curve, fluid_dex). Filtering an EVM pool byMarket: { Address: ... }matches the factory and silently returns a different pool's data. UsePool.Address.
| Chain family | Market.Address | Market.Program | Pool.Address |
|---|---|---|---|
| EVM and Tron | the protocol factory, empty for singleton protocols | the pool contract | the pool |
| Solana | the pool | the DEX program | the pool |
Related
Ready to run this in production?
Get an API key and run these queries in minutes, or talk to us about plans and enterprise delivery.