Storage Formats
Price Storage Format and conversion
You may encounter price in a lot of places
14th (with index 13) element returned from getPoolStateAndConfiguration
Limit price for swap
Initial price for the pool during the creation
It is stored as sqrt of the real price (jetton0 in terms of jetton1) that is packed in 160 bits of Fixed Point Q64.96 (96 bits of the fractional part) Example how to pack price from virtual reserves. Same could be used if you have a price and want to pack it.
export function encodePriceSqrt(reserve1: bigint, reserve0: bigint): bigint
{
BigNumber.set({DECIMAL_PLACES: 60})
let result = BigNumber(reserve1.toString())
.div(reserve0.toString())
.sqrt()
.multipliedBy(new BigNumber(2).pow(96))
.integerValue(3);
return BigInt(result.toFixed(0));
}
export function encodePriceSqrt(price: number): bigint
{
BigNumber.set({DECIMAL_PLACES: 60})
let result = BigNumber(price.toString())
.sqrt()
.multipliedBy(new BigNumber(2).pow(96))
.integerValue(3);
return BigInt(result.toFixed(0));
}
Example how to invert price
// Don't use this in production. It's quite imprecise.
export function invertPriceSqrtX96(sqrtPriceX96: bigint): bigint {
return 2n ** (96n+96n) / sqrtPriceX96
}
Unpack the price
// Core to unpack to readable format (note: this loses precision)
export function getApproxFloatPrice(priceSqrt: bigint) : number {
let result = BigNumber(priceSqrt.toString())
.div(BigNumber(2).pow(48))
.pow(2)
.div(BigNumber(2).pow(96))
return Number(result.toPrecision(8));
}
Also note that if you request the price from the contract it there is a special case to handle. If the price moves outside of all active liquidity ranges it could take values MIN_SQRT_RATIO = 4295128739 MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342 To check for validity of the price you may check if current liquidity equals to zero. Current liquidity is also returned by getPoolStateAndConfiguration
Last updated