Uniswap Pools API: New Pools, Reserves, Liquidity and Pool Prices
List newly created Uniswap v2, v3 and v4 pools, read their reserves in USD, see the first deposits, rank a token's pools by liquidity and stream pool changes. Every query runs on the current API.

The 2020 version of this post listed newly created Uniswap v2 pairs with the first Bitquery GraphQL schema and read a pool's reserves from its token balances. That schema has been retired. This rewrite does the same four things on the current API, across Uniswap v2, v3 and v4: find new pools, learn about their tokens, read the first deposits, and read the reserves right now. It then goes further than the original could, with liquidity in USD, price impact per pool and a live stream of pool changes. Every query below was run against the live API before publishing.
What a Uniswap pool is, by version
Anyone can create a Uniswap pool for two tokens, and the first deposit sets the opening price. How the pool exists on chain changed with each version, and that decides which query finds it.
| v2 | v3 | v4 | |
|---|---|---|---|
| What gets deployed | One pair contract per token pair, itself an ERC-20 (the LP token) | One pool contract per token pair per fee tier | Nothing. Every pool is a state entry inside one PoolManager contract |
| Identity | Pair address | Pool address | PoolId, a hash of the tokens, fee, tick spacing and hooks |
| Creation event | PairCreated on the v2 factory | PoolCreated on the v3 factory | Initialize on the PoolManager |
| Where reserves live | In the pair contract | In the pool contract | In the PoolManager, keyed by PoolId |
The addresses used below are Ethereum mainnet; the same queries work on Base, Arbitrum, Optimism, Polygon and BNB Chain with that chain's factory addresses and network value.
Newly created pools
A v2 pool is announced by the factory's PairCreated event, which carries both token addresses and the new pair address. The Events query below returns the most recent ones, decoded, with the transaction that created them. Generate a token in the Bitquery IDE to run it.
query NewUniswapV2Pairs {
EVM(network: eth) {
Events(
orderBy: { descending: Block_Number }
limit: { count: 10 }
where: {
Log: {
SmartContract: { is: "0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f" }
Signature: { Name: { is: "PairCreated" } }
}
}
) {
Block {
Time
Number
}
Transaction {
Hash
}
Arguments {
Name
Value {
... on EVM_ABI_Address_Value_Arg {
address
}
... on EVM_ABI_BigInt_Value_Arg {
bigInteger
}
}
}
}
}
}
Each row's Arguments hold token0, token1 and pair, plus the running count of pairs the factory has created. v3 and v4 announce pools the same way with different events and arguments, so one query can watch all three factories at once:
query NewUniswapPoolsAllVersions {
EVM(network: eth) {
Events(
orderBy: { descending: Block_Number }
limit: { count: 20 }
where: {
Log: {
SmartContract: {
in: [
"0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f"
"0x1f98431c8ad98523631ae4a59f267346ea31f984"
"0x000000000004444c5dc75cb358380d2e3de08a90"
]
}
Signature: { Name: { in: ["PairCreated", "PoolCreated", "Initialize"] } }
}
}
) {
Block {
Time
}
Log {
SmartContract
Signature {
Name
}
}
Transaction {
Hash
}
Arguments {
Name
Value {
... on EVM_ABI_Address_Value_Arg {
address
}
... on EVM_ABI_Bytes_Value_Arg {
hex
}
... on EVM_ABI_BigInt_Value_Arg {
bigInteger
}
}
}
}
}
}
What each version's arguments give you:
- v2
PairCreated:token0,token1,pair. - v3
PoolCreated:token0,token1,tickSpacing,pool. - v4
Initialize:id(thePoolId),currency0,currency1,fee,tickSpacing,hooks, and the openingsqrtPriceX96andtick. A zerocurrency0means native ETH.
Swap query for subscription and the same filter becomes a live feed of pool creation; there is a saved stream in the IDE. For the full history, add dataset: combined and page through the results: the v2 factory alone has emitted several hundred thousand of these events since it went live, and the archive holds every one.
Learning about the tokens
The 2020 post looked each token up by address to get its symbol and decimals. The Tokens cube answers the same lookup with the fields you need next: current price, market cap, supply and volume, blended across every pool the token trades in.
query TokenSnapshot {
Trading {
Tokens(
where: {
Token: {
Address: { is: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" }
Network: { is: "Ethereum" }
}
Interval: { Time: { Duration: { eq: 60 } } }
}
orderBy: { descending: Block_Time }
limit: { count: 1 }
) {
Token {
Symbol
Name
Address
}
Price {
IsQuotedInUsd
Ohlc {
Close
}
}
Supply {
MarketCap
CirculatingSupply
}
Volume {
Usd
}
}
}
}
A token that has not traded yet has no row here, which is the usual case in the minutes after a pool is created. The creation event already carries the addresses, and the first trades appear in the DEX trades queries as soon as they land.
The first deposits into a pool
Whoever creates a pool seeds it with both tokens, and those first transfers set the opening price. Transfers into the pool address, oldest first, show exactly what was deposited. The example uses the original v2 USDC/WETH pair, so it reaches back to the pair's first block through the combined dataset.
query FirstDepositsIntoPool {
EVM(network: eth, dataset: combined) {
Transfers(
where: {
Transfer: {
Receiver: { is: "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc" }
Amount: { gt: "0" }
}
}
orderBy: { ascending: Block_Time }
limit: { count: 2 }
) {
Block {
Time
Number
}
Transaction {
Hash
}
Transfer {
Sender
Amount
Currency {
Symbol
SmartContract
}
}
}
}
}
For a pool created in the last few days, the DEXPoolEvents cube gives the same answer with more context: order it by ascending block time for the pool and the first row is the initial mint, with the reserves after it and their USD value.
Reserves right now
The 2020 post read a pool's reserves as the token balances of the pair address, and that still works, on the current Balances cube. Filter to the pool address and its two tokens; without the currency filter you also get the stray tokens people airdrop to well-known pool addresses.
query PoolReservesFromBalances {
EVM(network: eth, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc" } }
Currency: {
SmartContract: {
in: [
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
]
}
}
}
) {
Currency {
Symbol
SmartContract
}
Balance {
Amount
AmountInUSD
LastChangeTime
}
}
}
}
The pool-native view is DEXPoolEvents, which records reserves and spot prices in both directions after every swap, mint and burn. Its latest row for a pool is the current state, and the liquidity API guide has the pool-specific and protocol-wide variants.
query PoolReservesAndSpotPrice {
EVM(network: eth) {
DEXPoolEvents(
limit: { count: 1 }
orderBy: { descending: Block_Time }
where: {
PoolEvent: {
Pool: { SmartContract: { is: "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640" } }
}
}
) {
Block {
Time
}
PoolEvent {
AtoBPrice
BtoAPrice
Dex {
ProtocolName
}
Liquidity {
AmountCurrencyA
AmountCurrencyAInUSD
AmountCurrencyB
AmountCurrencyBInUSD
}
Pool {
SmartContract
PoolId
CurrencyA {
Symbol
}
CurrencyB {
Symbol
}
}
}
}
}
}
Which to use:
- Balances is current state for any address, however old the pool, and it is the right call for v2 and v3 pools that hold their own funds. It does not stream.
- DEXPoolEvents carries USD values, spot prices and a change history, and it streams. It keeps a short rolling window, days rather than weeks, so it is for live and recent state. For v4 pools it is the only option, because their funds sit in the PoolManager and the row is keyed by
PoolId.
A token's pools, ranked by liquidity
The same cube lists every pool a token trades in and ranks them by what they hold. This returns the deepest pools where the token is the first currency; the liquidity guide shows the matching half for the second currency, and the exclusion of the PoolManager keeps v4 rows from collapsing onto one address.
query TopPoolsForToken {
EVM(network: eth) {
DEXPoolEvents(
limit: { count: 10 }
orderBy: { descendingByField: "PoolEvent_Liquidity_AmountCurrencyA_maximum" }
where: {
PoolEvent: {
Pool: {
CurrencyA: { SmartContract: { is: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce" } }
SmartContract: { notIn: ["0x000000000004444c5dc75cb358380d2e3de08a90"] }
}
}
}
) {
PoolEvent {
Dex {
ProtocolName
}
Liquidity {
AmountCurrencyA(maximum: Block_Time)
AmountCurrencyAInUSD(maximum: Block_Time)
AmountCurrencyB(maximum: Block_Time)
}
Pool {
SmartContract
CurrencyA {
Symbol
}
CurrencyB {
Symbol
}
}
}
}
}
}
The maximum: Block_Time selector takes each pool's latest reserves rather than summing rows, which is what a ranking needs.
Price impact per pool
Reserves say how much a pool holds; the slippage cube says how much you can trade against it. For each pool and slippage tolerance it returns the largest input that stays within that tolerance, the guaranteed minimum output and the average execution price, in both directions. Tolerances run from a tenth of a percent to ten percent, and each snapshot also carries a zero-tolerance row with the spot price, so seven rows describe one moment for one pool.
query PoolPriceImpact {
EVM(network: eth) {
DEXPoolSlippages(
where: {
Price: {
Pool: { SmartContract: { is: "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640" } }
}
}
orderBy: { descending: Block_Time }
limit: { count: 7 }
) {
Block {
Time
}
Price {
SlippageBasisPoints
AtoB {
Price
MaxAmountIn
MinAmountOut
}
BtoA {
Price
MaxAmountIn
MinAmountOut
}
Pool {
CurrencyA {
Symbol
}
CurrencyB {
Symbol
}
}
}
}
}
}
The numbers come from simulating swaps against the pool's live tick state, which is why v3 and v4 concentrated liquidity is handled correctly rather than approximated from reserves. Uniswap v4 slippage and price impact explains why the v3 formula breaks on v4, and real-time liquidity for DEX routers shows how bots use this table.
Positions and v4 pool ids
Two things this post cannot cover in one section each have their own guide:
- v3 positions are NFTs minted by the position manager, and the Uniswap v3 position API tracks mints, burns and liquidity changes per position.
- v4 pools share one contract, so token-pair filters alone are ambiguous when two pools differ only by fee or hooks. The Uniswap v4 liquidity guide shows how to read one concrete pool by
PoolId.
Streaming pool changes
Every DEXPoolEvents query above becomes a stream by changing query to subscription. This one emits a row each time a Uniswap pool's reserves change, with the reserves after the change:
subscription UniswapPoolChanges {
EVM(network: eth) {
DEXPoolEvents(
where: {
PoolEvent: {
Dex: { ProtocolName: { in: ["uniswap_v2", "uniswap_v3", "uniswap_v4"] } }
}
}
) {
Block {
Time
}
PoolEvent {
Dex {
ProtocolName
}
Liquidity {
AmountCurrencyA
AmountCurrencyB
}
Pool {
SmartContract
PoolId
CurrencyA {
Symbol
}
CurrencyB {
Symbol
}
}
}
Transaction {
Hash
}
}
}
}
The same rows are published on the eth.dexpools.proto topic of the Kafka streams, which add replay from retained offsets and lower latency; Kafka credentials are separate from IDE tokens and come through sales.
Charts for a pool
Candles per pool come from the Pairs cube rather than from pool events, pre-aggregated from one second to one hour. The DEX data APIs post has the query, and the Pairs cube reference covers ranking a token's pools to get its most reliable price.
FAQ
How do I get every Uniswap pool that exists?
Sweep the creation events with dataset: combined, paging by block number: PairCreated on the v2 factory, PoolCreated on the v3 factory and Initialize on the PoolManager. For only the pools that are active right now, query DEXPoolEvents with limitBy on the pool address instead.
How far back does pool data go?
Creation events and transfers are in the archive back to each factory's first block. Balances is current state with no history. DEXPoolEvents and DEXPoolSlippages keep a rolling window of a few days; for historical reserves or depth, use a cloud export.
A v4 pool has no address. How do I query it?
By PoolId, which the Initialize event returns as id and which DEXPoolEvents carries on every row. Two v4 pools for the same tokens with different fees or hooks are different ids.
Does this work on other chains?
Yes. Change network and use that chain's factory addresses. The Uniswap API page links the Base, BNB Chain and Polygon variants, and the DEX API covers the full list of venues.
Related reading
Subscribe to our newsletter
Subscribe and never miss any updates related to our APIs, new developments & latest news etc. Our newsletter is sent once a week on Monday.