Calculate Pool Metrics
Calculate key performance indicators for liquidity pools.
Quick Start
// Get pool and calculate basic metrics
const pool = await sdk.Pool.getPool(poolId)
// Current price
const price = TickMath.sqrtPriceX64ToPrice(
pool.current_sqrt_price,
9, // decimalsA
6 // decimalsB
)
// TVL in tokens
const tvlA = Number(pool.coinAmountA) / 10**9
const tvlB = Number(pool.coinAmountB) / 10**6
console.log({
price: price.toFixed(4),
tvlSUI: tvlA,
tvlUSDC: tvlB
})
Price Calculations
Current Price
import { TickMath } from '@ferra-labs/clmm'
// From sqrt price
const price = TickMath.sqrtPriceX64ToPrice(
pool.current_sqrt_price,
pool.coinTypeA.decimals,
pool.coinTypeB.decimals
)
// From tick index
const priceFromTick = TickMath.tickIndexToPrice(
pool.current_tick_index,
decimalsA,
decimalsB
)
Price Range
// Get min/max prices for a position
const position = await sdk.Position.getPositionById(positionId)
const minPrice = TickMath.tickIndexToPrice(
position.tick_lower_index,
decimalsA,
decimalsB
)
const maxPrice = TickMath.tickIndexToPrice(
position.tick_upper_index,
decimalsA,
decimalsB
)
console.log(`Price range: ${minPrice} - ${maxPrice}`)
TVL Calculation
Pool TVL
async function calculatePoolTVL(pool: Pool, priceInUSD: number) {
// Get token amounts
const amountA = Number(pool.coinAmountA) / 10**decimalsA
const amountB = Number(pool.coinAmountB) / 10**decimalsB
// Calculate USD values (assuming token B is USD stable)
const tvlB_USD = amountB
const tvlA_USD = amountA * priceInUSD
const totalTVL = tvlA_USD + tvlB_USD
return {
tvl: totalTVL,
breakdown: {
tokenA: { amount: amountA, usd: tvlA_USD },
tokenB: { amount: amountB, usd: tvlB_USD }
}
}
}
Position Value
async function calculatePositionValue(positionId: string) {
const position = await sdk.Position.getPositionById(positionId)
const pool = await sdk.Pool.getPool(position.pool)
// Get token amounts from liquidity
const amounts = ClmmPoolUtil.getCoinAmountFromLiquidity(
new BN(pool.current_sqrt_price),
position.tick_lower_index,
position.tick_upper_index,
new BN(position.liquidity),
false
)
const valueA = Number(amounts.coinA) / 10**decimalsA
const valueB = Number(amounts.coinB) / 10**decimalsB
return { valueA, valueB }
}
APR Calculations
Fee APR
async function calculateFeeAPR(poolId: string, period = 7) {
// Get historical fees (from your API/indexer)
const historicalFees = await getPoolFees(poolId, period)
// Get current TVL
const pool = await sdk.Pool.getPool(poolId)
const tvl = await calculatePoolTVL(pool, currentPrice)
// Calculate daily average
const avgDailyFees = historicalFees.total / period
// Annualize
const annualFees = avgDailyFees * 365
const feeAPR = (annualFees / tvl.tvl) * 100
return feeAPR
}
Total APR with Rewards
async function calculateTotalAPR(poolId: string) {
// Fee APR
const feeAPR = await calculateFeeAPR(poolId)
// Reward APR
const emissions = await sdk.Rewarder.emissionsEveryDay(poolId)
const pool = await sdk.Pool.getPool(poolId)
const tvl = await calculatePoolTVL(pool, currentPrice)
let rewardAPR = 0
if (emissions) {
emissions.forEach(emission => {
const yearlyEmissions = emission.emissions * 365
const emissionValueUSD = yearlyEmissions * tokenPriceUSD
rewardAPR += (emissionValueUSD / tvl.tvl) * 100
})
}
return {
feeAPR,
rewardAPR,
totalAPR: feeAPR + rewardAPR
}
}
Volume Metrics
Estimate from Fees
function estimateVolume(fees: number, feeRate: number) {
// Volume = Fees / Fee Rate
const feePercent = feeRate / 1000000 // Convert from basis points
return fees / feePercent
}
// Example: 24h volume from fees
async function get24hVolume(poolId: string) {
const pool = await sdk.Pool.getPool(poolId)
const feeRate = Number(pool.fee_rate)
// Get 24h fees (from your data source)
const fees24h = await get24hFees(poolId)
return estimateVolume(fees24h, feeRate)
}
Price Impact
Calculate for Swap
async function calculatePriceImpact(
pool: Pool,
amount: BN,
a2b: boolean,
byAmountIn: boolean
) {
// Get ticks for calculation
const ticks = await sdk.Pool.fetchTicks({
pool_id: pool.poolAddress,
coinTypeA: pool.coinTypeA,
coinTypeB: pool.coinTypeB
})
// Calculate swap result
const result = sdk.Swap.calculateRates({
currentPool: pool,
coinTypeA: pool.coinTypeA,
coinTypeB: pool.coinTypeB,
decimalsA: 9,
decimalsB: 6,
a2b,
byAmountIn,
amount,
swapTicks: ticks
})
return {
priceImpact: result.priceImpactPct,
effectivePrice: calculateEffectivePrice(result),
isExceed: result.isExceed
}
}
Liquidity Distribution
Active Liquidity
async function getActiveLiquidity(poolId: string) {
const pool = await sdk.Pool.getPool(poolId)
const currentTick = pool.current_tick_index
// Get positions
const positions = await sdk.Pool.getPositionList(
pool.position_manager.positions_handle
)
// Calculate in-range liquidity
let activeLiquidity = new BN(0)
let totalLiquidity = new BN(0)
positions.data.forEach(pos => {
const liquidity = new BN(pos.liquidity)
totalLiquidity = totalLiquidity.add(liquidity)
if (pos.tick_lower_index <= currentTick &&
currentTick < pos.tick_upper_index) {
activeLiquidity = activeLiquidity.add(liquidity)
}
})
return {
active: activeLiquidity.toString(),
total: totalLiquidity.toString(),
utilization: activeLiquidity.mul(new BN(100)).div(totalLiquidity)
}
}
Complete Example
async function getPoolMetrics(poolId: string) {
const pool = await sdk.Pool.getPool(poolId)
// 1. Price metrics
const currentPrice = TickMath.sqrtPriceX64ToPrice(
pool.current_sqrt_price, 9, 6
)
// 2. TVL calculation
const tvl = await calculatePoolTVL(pool, currentPrice.toNumber())
// 3. Volume (24h)
const volume24h = await get24hVolume(poolId)
// 4. APR calculation
const apr = await calculateTotalAPR(poolId)
// 5. Liquidity metrics
const liquidity = await getActiveLiquidity(poolId)
// 6. Fee tier
const feeTier = Number(pool.fee_rate) / 10000 // basis points to percent
return {
price: currentPrice.toFixed(6),
tvl: {
usd: tvl.tvl.toFixed(2),
tokenA: tvl.breakdown.tokenA,
tokenB: tvl.breakdown.tokenB
},
volume24h: volume24h.toFixed(2),
apr: {
fee: apr.feeAPR.toFixed(2),
rewards: apr.rewardAPR.toFixed(2),
total: apr.totalAPR.toFixed(2)
},
liquidity: {
utilization: `${liquidity.utilization}%`,
active: liquidity.active,
total: liquidity.total
},
feeTier: `${feeTier}%`
}
}
// Usage
const metrics = await getPoolMetrics(poolId)
console.log('Pool Metrics:', metrics)
Important Notes
TVL calculation requires external price feeds
APR is estimated based on historical data
Volume calculation depends on fee collection data
Price impact varies with liquidity distribution
Metrics should be cached for performance
Consider using indexer for historical data
Last updated