Uniswap Subgraph Query Examples for Crypto Traders
Learn how to query Uniswap's subgraph to pull real-time DeFi data — pool stats, swap history, liquidity — with practical GraphQL examples.
Learn how to query Uniswap's subgraph to pull real-time DeFi data — pool stats, swap history, liquidity — with practical GraphQL examples.
If you trade DeFi seriously, you already know that Uniswap is the beating heart of decentralized token swaps. But most traders only interact with it through a UI — they never tap into the raw data flowing underneath. Uniswap's subgraph changes that. It gives you programmatic access to every swap, every pool, every liquidity position — historical and real-time — through a simple GraphQL API. Whether you're building a bot, backtesting a strategy, or just trying to understand what whales are doing, subgraph queries are one of the most powerful tools in a DeFi trader's arsenal.
Ethereum's raw blockchain data is not easy to query. Imagine trying to find every swap involving USDC in the last 24 hours by reading raw transaction logs — you'd need to scan millions of blocks, decode ABI-encoded calldata, and piece together state changes manually. That's impractical for most use cases.
A subgraph solves this by indexing on-chain events into a structured database as they happen. The Graph Protocol — a decentralized indexing network — runs these subgraphs and exposes them through a standard GraphQL endpoint. Uniswap V2 and V3 each have their own official subgraphs. Think of it like a live, pre-sorted spreadsheet that someone else is maintaining for you, pulled directly from the blockchain.
Key Takeaway: A subgraph is an indexed, queryable database built on top of blockchain event data. You query it with GraphQL — no node required, no raw log parsing.
Uniswap V3 on Ethereum mainnet has an official subgraph hosted by The Graph. To use it, you need a free API key from The Graph's hosted service or their decentralized network. For development and testing, the public endpoint works fine with rate limits.
The base endpoint for Uniswap V3 mainnet looks like this:
https://gateway.thegraph.com/api/{YOUR_API_KEY}/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV
For quick exploration without an API key, you can also use The Graph's hosted service playground at thegraph.com and run queries interactively. Once you have your endpoint, all requests are standard HTTP POST with a JSON body containing your GraphQL query. You can call it from Python, JavaScript, a cURL command, or any tool that speaks HTTP.
Let's start with something immediately useful — fetching the top liquidity pools sorted by total value locked. This is the equivalent of pulling up the Uniswap analytics page, but programmatically and in a format you can pipe into anything downstream.
const query = `
{
pools(
first: 10
orderBy: totalValueLockedUSD
orderDirection: desc
) {
id
token0 {
symbol
decimals
}
token1 {
symbol
decimals
}
feeTier
totalValueLockedUSD
volumeUSD
token0Price
token1Price
}
}
`;
const response = await fetch(SUBGRAPH_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query })
});
const data = await response.json();
console.log(data.data.pools);
This returns the 10 largest pools with token symbols, fee tiers, TVL in USD, and current prices. The feeTier field is in basis points — 500 means 0.05%, 3000 means 0.3%, 10000 means 1%. This matters if you're routing trades or analyzing which fee tier captures the most volume for a given pair.
Key Takeaway: Pool queries return both tokens, the fee tier, TVL, and price — all the context you need to evaluate a pair without hitting any external price API.
This is where it gets genuinely powerful. Every swap on Uniswap is an on-chain event, and the subgraph indexes them all. You can pull the last 100 swaps for any pool, filter by size, or look for specific wallets. Traders use this to detect large buys and sells before they show up on centralized platforms like Binance or Coinbase.
import requests
SUBGRAPH_URL = "https://gateway.thegraph.com/api/YOUR_KEY/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV"
# WETH/USDC 0.05% pool address
POOL_ID = "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"
query = """
{
swaps(
first: 50
orderBy: timestamp
orderDirection: desc
where: { pool: "%s" }
) {
id
timestamp
sender
recipient
amount0
amount1
amountUSD
sqrtPriceX96
tick
}
}
""" % POOL_ID
response = requests.post(SUBGRAPH_URL, json={"query": query})
swaps = response.json()["data"]["swaps"]
for swap in swaps:
print(f"{swap['timestamp']} | ${float(swap['amountUSD']):.2f} | {swap['sender'][:10]}...")
The amountUSD field tells you the dollar value of the swap immediately. If you see a cluster of large swaps — say, $500k+ in a short window — that's a signal. Platforms like VoiceOfChain automate exactly this kind of detection, surfacing whale-level on-chain activity as real-time trading signals so you don't have to run these queries manually around the clock.
Compare what you find here with order book data from OKX or Bybit — when on-chain buying pressure spikes on Uniswap but centralized exchange spot books haven't caught up, you often have a short window before the price adjusts.
Pools give you pair-level data, but sometimes you want the aggregate picture for a single token across all its pools. The subgraph's Token entity aggregates this.
const TOKEN_ADDRESS = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; // WETH
const query = `
{
token(id: "${TOKEN_ADDRESS.toLowerCase()}") {
symbol
name
decimals
totalSupply
volume
volumeUSD
txCount
totalValueLocked
totalValueLockedUSD
derivedETH
tokenDayData(
first: 7
orderBy: date
orderDirection: desc
) {
date
volumeUSD
priceUSD
open
high
low
close
}
}
}
`;
The tokenDayData nested query gives you OHLC candles for the last 7 days — directly from on-chain data. These are Uniswap's own TWAP-derived prices, not a centralized feed. For tokens that trade primarily on DEXs and don't have deep liquidity on Bitget or KuCoin, this is often your most reliable price source.
| Entity | What It Contains | Best For |
|---|---|---|
| Pool | TVL, volume, fee tier, token prices | Monitoring specific pairs |
| Token | Aggregated volume, TVL, OHLC history | Token-wide analytics |
| Swap | Individual trades, wallet addresses, USD value | Whale tracking, flow analysis |
| Tick | Liquidity distribution at price levels | LP range analysis |
| PoolDayData | Daily OHLC, volume, TVL per pool | Backtesting, trend analysis |
| Transaction | All events in a single tx | Tracing complex multi-step trades |
The subgraph has a hard limit of 1000 records per query. For anything larger — like pulling all swaps in a 24-hour window — you need to paginate using the skip parameter or, more reliably, using timestamp-based cursor pagination.
import requests
import time
SUBGRAPH_URL = "https://gateway.thegraph.com/api/YOUR_KEY/subgraphs/id/5zvR82QoaXYFyDEKLZ9t6v9adgnptxYpKpSbxtgVENFV"
def fetch_swaps_since(pool_id: str, since_timestamp: int) -> list:
"""Cursor-paginate all swaps after a given timestamp."""
all_swaps = []
last_ts = since_timestamp
while True:
query = """
{
swaps(
first: 1000
orderBy: timestamp
orderDirection: asc
where: {
pool: "%s"
timestamp_gt: %d
}
) {
id
timestamp
amountUSD
sender
}
}
""" % (pool_id, last_ts)
resp = requests.post(SUBGRAPH_URL, json={"query": query})
swaps = resp.json()["data"]["swaps"]
if not swaps:
break
all_swaps.extend(swaps)
last_ts = int(swaps[-1]["timestamp"])
if len(swaps) < 1000:
break
return all_swaps
# Fetch last 24 hours
since = int(time.time()) - 86400
pool = "0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"
swaps = fetch_swaps_since(pool, since)
print(f"Total swaps: {len(swaps)}")
This cursor approach is more reliable than skip-based pagination because it doesn't break if new records are inserted mid-query. Use it any time you're pulling bulk historical data. For production systems, cache aggressively — subgraph data is eventual consistency, not real-time. For true real-time needs, combine subgraph queries with direct event subscriptions via WebSocket RPC.
Key Takeaway: Always paginate using timestamp_gt cursor logic, not skip. The 1000-record limit is hard, and skip-based pagination becomes unreliable on live data.
For traders who want this data without writing code, VoiceOfChain aggregates on-chain Uniswap flow alongside centralized exchange signals, so you can act on whale movements without building your own subgraph pipeline. But if you're building automated strategies — bots that route around liquidity fragmented across Binance spot, Coinbase Pro, and Uniswap pools simultaneously — direct subgraph access is essential.
Uniswap subgraph queries are the closest thing DeFi has to a brokerage API. In a few lines of code you get swap history, pool liquidity, token prices, and wallet-level activity — all sourced directly from the blockchain, no intermediary required. Traders who learn to read this data gain an edge that's simply not available through centralized exchange APIs alone.
Start small: pull the top 10 pools, get comfortable with the schema, then build up to swap monitoring for specific pairs. Once you're pulling data reliably, layer it on top of your existing signals — whether those come from Gate.io or KuCoin order books, or from platforms like VoiceOfChain that already process this on-chain flow for you. The traders who win in DeFi are the ones who see the chain clearly.