Skip to main content

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:

ProtocolNameCurve designTypical liquidity pools
curve_v1StableSwapstablecoin pools such as crvUSD/USDT and crvUSD/USDC, ETH and staked-ETH pools
curve_v2CryptoSwapvolatile 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) with Market: { 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 } and DEXTradeByTokens with Trade.Dex.ProtocolFamily: "Curve".
  • New liquidity pools: the deploy events of the Curve pool factories in the Events cube.
  • Token price and OHLC on Curve: Trading.Pairs filtered 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.

Run this query in the IDE

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.

Run this query in the IDE

{
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.

Run this query in the IDE

{
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.

Run this query in the IDE

{
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.

Run this query in the IDE

{
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.

Run this query in the IDE

{
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.

Run this query in the IDE

{
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:

Run this query in the IDE

{
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​

FieldCubeWhat it holds
Trade.Dex.ProtocolFamilyDEXTrades, DEXTradeByTokensCurve for every Curve liquidity pool
Trade.Dex.ProtocolNameDEXTrades, DEXTradeByTokenscurve_v1 (StableSwap) or curve_v2 (CryptoSwap)
Trade.Dex.SmartContractDEXTrades, DEXTradeByTokensThe Curve liquidity pool address
Trade.Dex.OwnerAddressDEXTrades, DEXTradeByTokensThe factory that deployed the liquidity pool, zero for older liquidity pools
Trade.Buy / Trade.SellDEXTradesThe two tokens of the swap with amount, USD amount and price
Transaction.Fromall EVM cubesThe account that sent the swap
Pair.Market.ProtocolTradingcurve_v1 or curve_v2
Pair.Pool.AddressTradingThe Curve liquidity pool address
Trader.AddressTradingThe trader of the swap
Price.OhlcTrading.PairsOpen, 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.SmartContract when 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_AmountInUSD on DEXTrades), not both.
  • StableSwap-NG deploys carry no pool address. The StableSwap-NG factory (0x6a8cbed756804b16e05e741edabd5cb544ae21bf) emits PlainPoolDeployed with 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 in DEXTrades.
  • Use ProtocolFamily for both designs. Filtering only on curve_v1 misses Tricrypto and Twocrypto liquidity pools, and only on curve_v2 misses the stablecoin liquidity pools.
  • Small liquidity pools can spike a candle. The DEXTradeByTokens OHLC 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 with Dex: {SmartContract: {is: "..."}}, or use Trading.Pairs, which gives one candle per liquidity pool.
  • The Trading cube keeps about 30 days. For older trades and candles use DEXTrades and DEXTradeByTokens.

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.

Build with Bitquery

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.