Skip to main content

Arbitrum Liquidity API: Pool Reserves and Liquidity Changes in Real Time

The DEXPoolEvents cube under EVM(network: arbitrum) emits one row every time a pool's reserves change, whether by a swap, a deposit or a withdrawal. Each row carries the reserves of both tokens after the change, in token units and in USD, the spot price in both directions, the pool and its protocol, and the transaction that moved it. On Arbitrum the rows come from Uniswap v2, v3 and v4 pools and PancakeSwap v3 pools. Balancer, Curve, Fluid and DODO pools have their swaps in the DEX trades API but no reserve rows here, and Camelot is not indexed at all. The cube holds the recent realtime window only and has no archive dataset: to keep a history, record the stream. Every example runs in the IDE on a free account. The worked pool is the Uniswap v3 WETH/ARB pool, 0xc6f780497a95e246eb9449f5e4770916dcd6396a, one of the busiest on the chain.

Reserves of one pool now

The newest rows for a pool. AmountCurrencyA and AmountCurrencyB are the reserves after each change, the InUSD twins price them, and AtoBPrice is how much of B one unit of A buys at the spot. Saved query here.

{
EVM(network: arbitrum) {
DEXPoolEvents(
limit: { count: 10 }
orderBy: { descending: Block_Time }
where: {
PoolEvent: {
Pool: { SmartContract: { is: "0xc6f780497a95e246eb9449f5e4770916dcd6396a" } }
}
}
) {
Block {
Time
Number
}
PoolEvent {
AtoBPrice
BtoAPrice
Liquidity {
AmountCurrencyA
AmountCurrencyAInUSD
AmountCurrencyB
AmountCurrencyBInUSD
}
Pool {
SmartContract
CurrencyA {
Symbol
SmartContract
}
CurrencyB {
Symbol
SmartContract
}
}
Dex {
ProtocolName
}
}
Transaction {
Hash
}
}
}
}

Stream one pool

The same filter as a subscription delivers a row on every reserve change, which for this pool means several per minute. Saved stream here.

subscription {
EVM(network: arbitrum) {
DEXPoolEvents(
where: {
PoolEvent: {
Pool: { SmartContract: { is: "0xc6f780497a95e246eb9449f5e4770916dcd6396a" } }
}
}
) {
Block {
Time
Number
}
PoolEvent {
AtoBPrice
BtoAPrice
Liquidity {
AmountCurrencyA
AmountCurrencyAInUSD
AmountCurrencyB
AmountCurrencyBInUSD
}
Pool {
SmartContract
CurrencyA {
Symbol
}
CurrencyB {
Symbol
}
}
}
Transaction {
Hash
}
}
}
}

Every Uniswap v4 pool on Arbitrum

Filter on the protocol to follow a whole family of pools. Uniswap v4 keeps all pools inside one PoolManager contract, 0x360e68faccca8ca495c1b759fd9eee466db9fb32 on Arbitrum, so Pool.SmartContract is the same on every row and Pool.PoolId is the field that tells pools apart. For v2 and v3 pools PoolId is empty and SmartContract is the pool. Saved stream here.

subscription {
EVM(network: arbitrum) {
DEXPoolEvents(
where: { PoolEvent: { Dex: { ProtocolName: { is: "uniswap_v4" } } } }
) {
Block {
Time
}
PoolEvent {
Pool {
PoolId
SmartContract
CurrencyA {
Symbol
SmartContract
}
CurrencyB {
Symbol
SmartContract
}
}
Liquidity {
AmountCurrencyA
AmountCurrencyAInUSD
AmountCurrencyB
AmountCurrencyBInUSD
}
AtoBPrice
}
Transaction {
Hash
}
}
}
}

Other protocol names that report on Arbitrum: uniswap_v3, uniswap_v2 and pancake_swap_v3.

Pools that hold a token, with their current reserves

limitBy on the pool address keeps the newest row per pool, so the result is the current state of every pool that had the token as CurrencyA and changed inside the window. Run it a second time with the token under CurrencyB to catch pools that list it second. The example is ARB, 0x912ce59144191c1204e64559fe8253a0e49e6548; sort the rows by the USD reserve in your code to rank the pools. Saved query here.

{
EVM(network: arbitrum) {
DEXPoolEvents(
limit: { count: 20 }
limitBy: { by: PoolEvent_Pool_SmartContract, count: 1 }
orderBy: { descending: Block_Time }
where: {
PoolEvent: {
Pool: {
CurrencyA: { SmartContract: { is: "0x912ce59144191c1204e64559fe8253a0e49e6548" } }
}
}
Block: { Time: { since_relative: { hours_ago: 24 } } }
}
) {
Block {
Time
}
PoolEvent {
Dex {
ProtocolName
}
Pool {
SmartContract
PoolId
CurrencyB {
Symbol
SmartContract
}
}
Liquidity {
AmountCurrencyA
AmountCurrencyAInUSD
AmountCurrencyB
AmountCurrencyBInUSD
}
}
}
}
}

Fields on every row

FieldMeaning
PoolEvent.Liquidity.AmountCurrencyA, AmountCurrencyBReserves of each token after the change, in token units
AmountCurrencyAInUSD, AmountCurrencyBInUSDThe same reserves priced in USD
PoolEvent.AtoBPrice, BtoAPriceSpot price in each direction after the change
PoolEvent.Pool.SmartContract, PoolIdPool contract; for Uniswap v4 the PoolManager plus the pool id
PoolEvent.Dex.ProtocolNameuniswap_v2, uniswap_v3, uniswap_v4 or pancake_swap_v3
Transaction.HashThe transaction that changed the reserves

The same data over Kafka

The arbitrum.dexpools.proto topic carries the same rows as protobuf messages with lower latency and no WebSocket to keep alive. Kafka needs its own credentials, separate from the IDE token; see the Kafka streams hub. The slippage tables for the same pools are on the Arbitrum slippage API page.

Frequently Asked Questions

How do I get the reserves of a pool on Arbitrum?

Query DEXPoolEvents under EVM(network: arbitrum) with the pool contract in PoolEvent.Pool.SmartContract, ordered by Block_Time descending. The newest row holds both reserves in token units and USD plus the spot price.

Which DEXs does the Arbitrum liquidity cube cover?

Rows come from Uniswap v2, v3 and v4 pools and PancakeSwap v3 pools. Balancer, Curve, Fluid and DODO have swaps in the DEX trades cube but no reserve rows here, and Camelot is not indexed.

How do I tell Uniswap v4 pools apart?

All v4 pools share the PoolManager address 0x360e68faccca8ca495c1b759fd9eee466db9fb32, so filter and group on PoolEvent.Pool.PoolId instead of SmartContract.

How far back does liquidity data go on Arbitrum?

DEXPoolEvents keeps the recent realtime window only and has no archive dataset. Record the subscription or the Kafka topic to build a history.

Does a liquidity row tell me whether it was a swap or a deposit?

Not directly. Compare consecutive rows for the pool: a swap moves the two reserves in opposite directions, a deposit or withdrawal moves both the same way. The transaction hash links to the call for detail.

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.