For the complete documentation index, see llms.txt. This page is also available as Markdown.

Reading pools and positions

Three ways to read pool state: directly via RPC (cheapest, freshest), via the Hasura indexer (best for ranges + history), and via the Exchange API (curated, cached).

Pool address from token + fee tier

Always derive the address with Kumbaya's pool init code hash, not Uniswap's. The @kumbaya_xyz/v3-sdk does it for you:

import { Pool, FeeAmount } from '@kumbaya_xyz/v3-sdk'
import { Token, ChainId } from '@kumbaya_xyz/sdk-core'

const A = new Token(ChainId.MEGAETH, '0x...', 18, 'A')
const B = new Token(ChainId.MEGAETH, '0x...', 6,  'B')

const poolAddress = Pool.getAddress(A, B, FeeAmount.MEDIUM) // 0.3%

If you implement the derivation yourself, see Pool Init Code Hash.

Reading current state via RPC

The two most useful reads are slot0 (current price + tick) and liquidity (active liquidity at the current tick).

import { createPublicClient, http, parseAbi } from 'viem'

const RPC = 'https://mainnet.megaeth.com/rpc'
const client = createPublicClient({ transport: http(RPC) })

const poolAbi = parseAbi([
  'function slot0() view returns (uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality, uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked)',
  'function liquidity() view returns (uint128)',
  'function token0() view returns (address)',
  'function token1() view returns (address)',
  'function fee() view returns (uint24)',
  'function tickSpacing() view returns (int24)',
])

const [slot0, liquidity, token0, token1, fee] = await Promise.all([
  client.readContract({ address: poolAddress, abi: poolAbi, functionName: 'slot0' }),
  client.readContract({ address: poolAddress, abi: poolAbi, functionName: 'liquidity' }),
  client.readContract({ address: poolAddress, abi: poolAbi, functionName: 'token0' }),
  client.readContract({ address: poolAddress, abi: poolAbi, functionName: 'token1' }),
  client.readContract({ address: poolAddress, abi: poolAbi, functionName: 'fee' }),
])

const [sqrtPriceX96, tick] = slot0
console.log({ tick, sqrtPriceX96, liquidity })

slot0() returns sqrtPriceX96 (a Q64.96 fixed-point number). To convert to a human-readable price the standard formula is:

You can also reach for the V3 SDK if you want typed Price / Token / Pool objects:

Tick liquidity via TickLens

For range UIs and depth charts you'll want the populated ticks around the current tick. Use TickLens:

Loop adjacent word indices to walk further from current tick.

Reading positions

Each LP position is an NFT held by NonfungiblePositionManager:

tokensOwed0 / tokensOwed1 show fees that have been "settled" but not yet collected. To see uncollected fees (including unsettled fee growth), the cleanest path is to construct a Position object via the SDK with current pool state.

Querying historical state via the indexer

For anything time-bounded - TVL over a week, swap volume, position changes - go through the Hasura GraphQL endpoint:

Or current pool state with relationships joined in:

Pool IDs are address-chainId (e.g. 0xabc...-4326).

Curated reads via the Exchange API

If you don't want to run the queries yourself:

Cached, paginated, and rate-limit friendly - use these for browser-grade UIs. See Pools endpoints.

Picking the right path

Task
Best path

One-time pool state read

RPC

Range / depth chart for one pool

RPC + TickLens

Time-series, aggregations, joins

Hasura indexer

Browser-grade UI feeding pool list / token detail

Exchange API

Position health for a known tokenId

RPC positions() + SDK

Last updated