Reading Pool State
The readPoolState function decodes all on-chain state into a typedPoolState object. This is your entry point for any pool interaction.
Usage
import { readPoolState } from '@taurus-swap/sdk';
const poolState = await readPoolState(algodClient, POOL_APP_ID);PoolState Type
interface PoolState {
// Basic info
n: number; // Number of tokens
appId: number; // Contract app ID
// Consolidated state
sumX: bigint; // Sum of all reserves (∑xᵢ)
sumXSq: bigint; // Sum of squared reserves (∑xᵢ²)
rInt: bigint; // Interior radius
sBound: bigint; // Boundary effective radius
kBound: bigint; // Boundary hyperplane offset
totalR: bigint; // Total liquidity (sum of all tick radii)
// Scaling
virtualOffset: bigint; // AMOUNT_SCALE (1000)
// Fees
feeBps: number; // Fee in basis points
feeGrowth: bigint[]; // Fee growth per token (n values)
// Tick info
numTicks: number; // Number of active ticks
// Per-token data
reserves: bigint[]; // Reserve of each token (microunits)
tokenAsas: number[]; // ASA ID of each token
tokenDecimals: number[]; // Decimal places of each token
}Field Descriptions
Basic Info
n— Number of tokens in the pool. For a 5-stablecoin pool, n = 5.appId— The Algorand app ID. Used for all subsequent calls.
Consolidated State
sumX— Sum of all reserves. Used to compute α (position along equal-price axis).sumXSq— Sum of squared reserves. Used to compute ‖w‖ (orthogonal component).rInt— Interior radius. Sum of radii for all interior ticks.sBound— Boundary effective radius. Sum of effective radii for boundary ticks.kBound— The outermost boundary hyperplane offset.totalR— Total liquidity. Sum of all tick radii (interior + boundary).
Scaling
virtualOffset— Always 1000 (AMOUNT_SCALE). Used for unit conversions.
Fees
feeBps— Fee in basis points. 30 = 0.3%, 100 = 1%.feeGrowth— Array of n values. feeGrowth[i] is the cumulative fee growth for token i. Used for LP fee claims.
Tick Info
numTicks— Number of active ticks. A fresh pool starts with 0.
Per-Token Data
reserves— Array of n reserve values in microunits. Convert to display units using tokenDecimals.tokenAsas— Array of n ASA IDs. Use these to identify tokens.tokenDecimals— Array of n decimal places. USDC/USDT use 6.
Example: Displaying Reserves
const poolState = await readPoolState(algodClient, POOL_APP_ID);
// Format reserves for display
const formattedReserves = poolState.reserves.map((reserve, i) => {
const decimals = poolState.tokenDecimals[i];
const display = Number(reserve) / (10 ** decimals);
const token = poolState.tokenAsas[i];
return `${display.toLocaleString()} (ASA ${token})`;
});
console.log('Pool reserves:');
formattedReserves.forEach((r, i) => console.log(` Token ${i}: ${r}`));Handling Fresh Pools
A newly deployed pool may not have all boxes initialized. Handle gracefully:
import { readPoolState, BoxNotFoundError } from '@taurus-swap/sdk';
try {
const poolState = await readPoolState(algodClient, POOL_APP_ID);
console.log('Pool is initialized');
} catch (err) {
if (err instanceof BoxNotFoundError) {
console.log('Pool not initialized yet - waiting for first liquidity deposit');
// Show "Pool not ready" UI
} else {
throw err;
}
}Polling for Updates
Pool state changes with every swap and liquidity operation. Poll periodically:
import { useEffect, useState } from 'react';
import { readPoolState } from '@taurus-swap/sdk';
function usePoolState(appId: number) {
const [state, setState] = useState<PoolState | null>(null);
useEffect(() => {
const fetch = async () => {
const s = await readPoolState(algodClient, appId);
setState(s);
};
fetch();
const interval = setInterval(fetch, 30_000); // 30 seconds
return () => clearInterval(interval);
}, [appId]);
return state;
}Reading Tick State
import { readTickState } from '@taurus-swap/sdk';
const tick = await readTickState(algodClient, POOL_APP_ID, tickId);
console.log('Tick state:', {
r: tick.r, // Sphere radius
k: tick.k, // Hyperplane offset
state: tick.state, // 'INTERIOR' or 'BOUNDARY'
totalShares: tick.totalShares,
effectiveRadius: tick.effectiveRadius
});Reading Position State
import { readPosition } from '@taurus-swap/sdk';
const position = await readPosition(
algodClient,
POOL_APP_ID,
address,
tickId
);
console.log('Position:', {
shares: position.shares,
pendingFees: position.pendingFees, // Already computed!
feeCheckpoints: position.feeCheckpoints
});Note: The pendingFeesfield is computed client-side using the fee growth formula. It's not stored on-chain.