Curve DEX API on Ethereum — Trades, New Liquidity Pools and Token Prices
Curve is an Ethereum DEX built around liquidity pools for assets that trade close to each other (stablecoins, ETH and liquid staking tokens) and, since its second design, for volatile assets too. Bitquery decodes every Curve swap on Ethereum into the same cubes as every other DEX, under the protocol family Curve with two protocol names:
ProtocolName | Curve design | Typical liquidity pools |
|---|---|---|
curve_v1 | StableSwap | stablecoin pools such as crvUSD/USDT and crvUSD/USDC, ETH and staked-ETH pools |
curve_v2 | CryptoSwap | volatile pairs such as the Tricrypto (USDT/WBTC/WETH) and Twocrypto liquidity pools |
Filter on ProtocolFamily: "Curve" to get both, or on one ProtocolName to get one design. A Curve liquidity pool can hold more than two tokens, so a single liquidity pool shows up with several token pairs. Every example below runs in the IDE on a free account.
How to get Curve data
- Live and recent trades with USD price and trader: the Crypto Trades API (
Trading.Trades) withMarket: { Network: "Ethereum", ProtocolFamily: "Curve" }. The Trading cube keeps about the last 30 days. - Full history and per-swap detail: the chain cubes
EVM(network: eth) { DEXTrades }andDEXTradeByTokenswithTrade.Dex.ProtocolFamily: "Curve". - New liquidity pools: the deploy events of the Curve pool factories in the
Eventscube. - Token price and OHLC on Curve:
Trading.Pairsfiltered to the Curve markets.
Live Curve trades on Ethereum
A stream of every Curve swap on Ethereum with the trader, the amounts, USD values and the liquidity pool address. Market.ProtocolFamily: "Curve" covers both curve_v1 and curve_v2; Pair.Pool.Address is the liquidity pool and Pair.Market.Address the factory that deployed it.
subscription {
Trading {
Trades(
where: {Pair: {Market: {Network: {is: "Ethereum"}, ProtocolFamily: {is: "Curve"}}}}
) {
Block {
Time
}
Side
Trader {
Address
}
Amounts {
Base
Quote
}
AmountsInUsd {
Base
}
Price
PriceInUsd
Pair {
Currency {
Symbol
Id
}
QuoteCurrency {
Symbol
Id
}
Market {
Protocol
Address
}
Pool {
Address
}
}
TransactionHeader {
Hash
}
}
}
}
Latest Curve swaps with full history
The DEXTrades cube on network: eth goes back further than the Trading cube and returns both sides of each swap. Dex.SmartContract is the liquidity pool and Dex.OwnerAddress the factory that deployed it (zero for liquidity pools with no factory on record). Transaction.From is the account that sent the swap.
{
EVM(network: eth) {
DEXTrades(
where: {Trade: {Dex: {ProtocolFamily: {is: "Curve"}}}}
limit: {count: 20}
orderBy: {descending: Block_Time}
) {
Block {
Time
Number
}
Trade {
Dex {
ProtocolName
SmartContract
OwnerAddress
}
Buy {
Currency {
Symbol
SmartContract
}
Amount
AmountInUSD
}
Sell {
Currency {
Symbol
SmartContract
}
Amount
AmountInUSD
}
}
Transaction {
From
Hash
}
}
}
}
Top Curve liquidity pools by 24-hour volume
Group DEXTrades by the liquidity pool address to rank Curve liquidity pools by trade count and USD volume. The since_relative filter keeps the window at the last 24 hours whenever you run it.
{
EVM(network: eth) {
DEXTrades(
where: {Trade: {Dex: {ProtocolFamily: {is: "Curve"}}}, Block: {Time: {since_relative: {hours_ago: 24}}}}
orderBy: {descendingByField: "volumeUsd"}
limit: {count: 20}
) {
Trade {
Dex {
ProtocolName
SmartContract
}
}
trades: count
traders: uniq(of: Transaction_From)
volumeUsd: sum(of: Trade_Buy_AmountInUSD)
}
}
}
Trades in one Curve liquidity pool
Put the liquidity pool address in Dex.SmartContract. The example is the crvUSD/USDT liquidity pool 0x390f3595bca2df7d23783dfd126427cceb997bf4.
{
EVM(network: eth) {
DEXTrades(
where: {Trade: {Dex: {SmartContract: {is: "0x390f3595bca2df7d23783dfd126427cceb997bf4"}}}}
limit: {count: 20}
orderBy: {descending: Block_Time}
) {
Block {
Time
}
Trade {
Buy {
Currency {
Symbol
}
Amount
AmountInUSD
Price
}
Sell {
Currency {
Symbol
}
Amount
AmountInUSD
}
}
Transaction {
From
Hash
}
}
}
}
New Curve liquidity pools
New Curve liquidity pools are deployed by Curve's pool factories, and each deploy emits an event. On Ethereum the main CryptoSwap factories are the Twocrypto-NG factory 0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f (TwocryptoPoolDeployed) and the Tricrypto-NG factory 0x0c0e5f2ff0ff18a3be9b835635039256dc4b4963 (TricryptoPoolDeployed). Both events carry the new liquidity pool address in the pool argument, followed by its name, symbol, the token addresses and the deployer. The window is the last 30 days; widen days_ago if you want older liquidity pools.
{
EVM(network: eth) {
Events(
where: {Log: {SmartContract: {in: ["0x98ee851a00abee0d95d08cf4ca2bdce32aeaaf7f", "0x0c0e5f2ff0ff18a3be9b835635039256dc4b4963"]}, Signature: {Name: {in: ["TwocryptoPoolDeployed", "TricryptoPoolDeployed"]}}}, Block: {Time: {since_relative: {days_ago: 30}}}}
limit: {count: 20}
orderBy: {descending: Block_Time}
) {
Block {
Time
}
Log {
SmartContract
Signature {
Name
}
}
Transaction {
Hash
}
Arguments {
Name
Value {
... on EVM_ABI_Address_Value_Arg {
address
}
... on EVM_ABI_String_Value_Arg {
string
}
}
}
}
}
}
To follow new liquidity pools as they are deployed, change the opening { to subscription { and drop the Block filter, limit and orderBy.
Token price on Curve
Trading.Pairs gives the USD price of a token on each Curve liquidity pool as OHLC candles. The example is CRV (0xd533a949740bb3306d119cc777fa900ba034cd52) on Ethereum, one-minute candles (Duration: 60 seconds), latest first. IsQuotedInUsd: true returns the price in USD instead of in the quote token.
{
Trading {
Pairs(
where: {Token: {Address: {is: "0xd533a949740bb3306d119cc777fa900ba034cd52"}, Network: {is: "Ethereum"}}, Market: {ProtocolFamily: {is: "Curve"}}, Interval: {Time: {Duration: {eq: 60}}}, Price: {IsQuotedInUsd: true}}
limit: {count: 10}
orderBy: {descending: Block_Time}
) {
Block {
Time
}
Token {
Symbol
Address
}
QuoteToken {
Symbol
}
Market {
Protocol
}
Pool {
Address
}
Price {
Ohlc {
Open
High
Low
Close
}
}
Volume {
Usd
}
}
}
}
Hourly CRV OHLC on Curve from the chain cube
For candles older than the Trading cube keeps, build them from DEXTradeByTokens. Trade.Currency is the token you price, and Side.Currency is the token it traded against. The PriceInUSD filter drops zero-price rows that would pull the low to zero.
{
EVM(network: eth) {
DEXTradeByTokens(
where: {Trade: {Dex: {ProtocolFamily: {is: "Curve"}}, Currency: {SmartContract: {is: "0xd533a949740bb3306d119cc777fa900ba034cd52"}}, PriceInUSD: {gt: 0}}, Block: {Time: {since_relative: {days_ago: 3}}}}
orderBy: {descendingByField: "Block_Time"}
limit: {count: 72}
) {
Block {
Time(interval: {count: 1, in: hours})
}
Trade {
open: PriceInUSD(minimum: Block_Number)
high: PriceInUSD(maximum: Trade_PriceInUSD)
low: PriceInUSD(minimum: Trade_PriceInUSD)
close: PriceInUSD(maximum: Block_Number)
}
volumeUsd: sum(of: Trade_Side_AmountInUSD)
trades: count
}
}
}
Curve on other chains
Bitquery decodes Curve on other EVM chains too, for example Arbitrum, Base, BSC, Optimism and Polygon (Matic). The Trading cube queries above work on any of them by changing Network; the DEXTrades queries by changing network: (for example arbitrum, base, bsc, optimism, matic). Factory addresses differ per chain. This query lists the chains where Curve trades in the last 24 hours:
{
Trading {
Trades(
where: {Pair: {Market: {ProtocolFamily: {is: "Curve"}}}, Block: {Time: {since_relative: {hours_ago: 24}}}}
orderBy: {descendingByField: "count"}
limit: {count: 20}
) {
Pair {
Market {
Network
Protocol
}
}
count
}
}
}
Fields
| Field | Cube | What it holds |
|---|---|---|
Trade.Dex.ProtocolFamily | DEXTrades, DEXTradeByTokens | Curve for every Curve liquidity pool |
Trade.Dex.ProtocolName | DEXTrades, DEXTradeByTokens | curve_v1 (StableSwap) or curve_v2 (CryptoSwap) |
Trade.Dex.SmartContract | DEXTrades, DEXTradeByTokens | The Curve liquidity pool address |
Trade.Dex.OwnerAddress | DEXTrades, DEXTradeByTokens | The factory that deployed the liquidity pool, zero for older liquidity pools |
Trade.Buy / Trade.Sell | DEXTrades | The two tokens of the swap with amount, USD amount and price |
Transaction.From | all EVM cubes | The account that sent the swap |
Pair.Market.Protocol | Trading | curve_v1 or curve_v2 |
Pair.Pool.Address | Trading | The Curve liquidity pool address |
Trader.Address | Trading | The trader of the swap |
Price.Ohlc | Trading.Pairs | Open, high, low and close of the token in the interval |
Pitfalls
- One liquidity pool, several pairs. A Curve liquidity pool with three or more tokens (Tricrypto, 3pool-style pools) returns one row per token pair. Group by
Dex.SmartContractwhen you want liquidity pool totals. - Don't sum both sides for volume. Each swap has a buy side and a sell side of the same USD value. Sum one of them (
Trade_Buy_AmountInUSDonDEXTrades), not both. - StableSwap-NG deploys carry no pool address. The StableSwap-NG factory (
0x6a8cbed756804b16e05e741edabd5cb544ae21bf) emitsPlainPoolDeployedwith the coins, amplification, fee and deployer but not the new liquidity pool address. Use the transaction hash to find the liquidity pool, or wait for its first swap inDEXTrades. - Use
ProtocolFamilyfor both designs. Filtering only oncurve_v1misses Tricrypto and Twocrypto liquidity pools, and only oncurve_v2misses the stablecoin liquidity pools. - Small liquidity pools can spike a candle. The
DEXTradeByTokensOHLC example takes every Curve liquidity pool that trades the token, and a tiny swap in a thin liquidity pool can set an hourly high or low far from the market. Filter to one liquidity pool withDex: {SmartContract: {is: "..."}}, or useTrading.Pairs, which gives one candle per liquidity pool. - The Trading cube keeps about 30 days. For older trades and candles use
DEXTradesandDEXTradeByTokens.
Frequently Asked Questions
How do I get Curve trades on Ethereum?
Use Trading.Trades with Market Network Ethereum and ProtocolFamily Curve for live and recent trades with USD values, or EVM(network: eth) DEXTrades with Trade.Dex.ProtocolFamily Curve for full history.
What is the difference between curve_v1 and curve_v2?
curve_v1 is Curve's StableSwap design for assets that trade close to each other, such as stablecoins. curve_v2 is the CryptoSwap design for volatile pairs, such as the Tricrypto and Twocrypto liquidity pools.
How do I find new Curve liquidity pools?
Query the Events cube for TwocryptoPoolDeployed and TricryptoPoolDeployed on the Curve factory contracts. The pool argument is the new liquidity pool address.
Related pages
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.