Price Helpers
Price Helpers
Utility functions for price conversions between human-readable formats and protocol values. Essential helpers for working with DLMM's bin-based pricing system.
Core Price Functions
// Convert bin ID to price
function getPriceFromBinId(binId: number, binStep: number): number {
const base = 1 + binStep / 10000;
const exponent = binId - 8388608;
return Math.pow(base, exponent);
}
// Convert price to bin ID
function getBinIdFromPrice(price: number, binStep: number): number {
const base = 1 + binStep / 10000;
const binId = Math.log(price) / Math.log(base) + 8388608;
return Math.round(binId);
}
// Get price with high precision
function getPriceFromBinIdPrecise(binId: number, binStep: number): string {
const base = 1 + binStep / 10000;
const exponent = binId - 8388608;
const price = Math.pow(base, exponent);
return price.toPrecision(18);
}
Price Formatting
// Format price for display
function formatPrice(price: number, decimals: number = 4): string {
if (price > 10000) {
return price.toLocaleString('en-US', {
maximumFractionDigits: 0
});
} else if (price > 1) {
return price.toFixed(decimals);
} else {
return price.toPrecision(decimals);
}
}
// Smart format based on value
function autoFormatPrice(price: number): string {
if (price >= 1000) return formatPrice(price, 0);
if (price >= 1) return formatPrice(price, 2);
if (price >= 0.01) return formatPrice(price, 4);
return price.toPrecision(4);
}
Price Range Calculations
// Get price range from bin range
function getPriceRange(
centerBinId: number,
binRadius: number,
binStep: number
): { min: number, max: number, spread: number } {
const minPrice = getPriceFromBinId(centerBinId - binRadius, binStep);
const maxPrice = getPriceFromBinId(centerBinId + binRadius, binStep);
return {
min: minPrice,
max: maxPrice,
spread: ((maxPrice - minPrice) / minPrice) * 100
};
}
// Calculate bins needed for price range
function getBinsForPriceRange(
currentPrice: number,
minPrice: number,
maxPrice: number,
binStep: number
): { lower: number, upper: number, total: number } {
const currentBin = getBinIdFromPrice(currentPrice, binStep);
const minBin = getBinIdFromPrice(minPrice, binStep);
const maxBin = getBinIdFromPrice(maxPrice, binStep);
return {
lower: currentBin - minBin,
upper: maxBin - currentBin,
total: maxBin - minBin + 1
};
}
Price Conversions
// Convert between token ratios
function calculateTokenRatio(
amountX: bigint,
amountY: bigint,
decimalsX: number,
decimalsY: number
): number {
const x = Number(amountX) / (10 ** decimalsX);
const y = Number(amountY) / (10 ** decimalsY);
return y / x; // Price of X in terms of Y
}
// Normalize price for different decimals
function normalizePrice(
price: number,
decimalsX: number,
decimalsY: number
): number {
const decimalDiff = decimalsY - decimalsX;
return price * Math.pow(10, decimalDiff);
}
Bin Navigation
// Get next/previous bin prices
function getAdjacentPrices(
binId: number,
binStep: number,
count: number = 5
): { below: number[], current: number, above: number[] } {
const below = [];
const above = [];
for (let i = 1; i <= count; i++) {
below.push(getPriceFromBinId(binId - i, binStep));
above.push(getPriceFromBinId(binId + i, binStep));
}
return {
below: below.reverse(),
current: getPriceFromBinId(binId, binStep),
above
};
}
// Find nearest bin to target price
function getNearestBin(
targetPrice: number,
binStep: number
): { binId: number, actualPrice: number, difference: number } {
const binId = getBinIdFromPrice(targetPrice, binStep);
const actualPrice = getPriceFromBinId(binId, binStep);
return {
binId,
actualPrice,
difference: Math.abs(targetPrice - actualPrice)
};
}
Price Validation
// DLMM constants
const PRICE_BOUNDS = {
MIN_BIN_ID: 0,
MAX_BIN_ID: 16777215, // 2^24 - 1
REFERENCE_BIN_ID: 8388608 // Price = 1.0
};
// Validate price is within DLMM bounds
function isValidPrice(price: number, binStep: number): boolean {
try {
const binId = getBinIdFromPrice(price, binStep);
return binId >= PRICE_BOUNDS.MIN_BIN_ID &&
binId <= PRICE_BOUNDS.MAX_BIN_ID;
} catch {
return false;
}
}
// Get max/min prices for bin step
function getPriceBounds(binStep: number): { min: number, max: number } {
return {
min: getPriceFromBinId(PRICE_BOUNDS.MIN_BIN_ID, binStep),
max: getPriceFromBinId(PRICE_BOUNDS.MAX_BIN_ID, binStep)
};
}
Utility Functions
// Quick helpers
const priceHelpers = {
// Get current price from pair
getCurrentPrice: (pair: LBPair) =>
getPriceFromBinId(pair.parameters.active_id, Number(pair.binStep)),
// Calculate price impact
getPriceImpact: (startBin: number, endBin: number, binStep: number) => {
const startPrice = getPriceFromBinId(startBin, binStep);
const endPrice = getPriceFromBinId(endBin, binStep);
return ((endPrice - startPrice) / startPrice) * 100;
},
// Format pair price for display
formatPairPrice: (pair: LBPair, decimals?: number) => {
const price = getPriceFromBinId(pair.parameters.active_id, Number(pair.binStep));
return autoFormatPrice(price);
}
};
Last updated