@orca-so/whirlpool-sdk
Version:
Whirlpool SDK for the Orca protocol.
95 lines (94 loc) • 5.06 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLiquidityDistribution = void 0;
const whirlpool_client_sdk_1 = require("@orca-so/whirlpool-client-sdk");
const anchor_1 = require("@project-serum/anchor");
const decimal_js_1 = __importDefault(require("decimal.js"));
const __1 = require("..");
const address_1 = require("../utils/address");
const tick_util_1 = require("../utils/whirlpool/tick-util");
function getLiquidityDistribution(ctx, poolAddress, tickLower, tickUpper, refresh) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const datapoints = [];
const pool = yield ctx.accountFetcher.getPool(poolAddress, refresh);
if (!pool) {
throw new Error(`Whirlpool not found: ${(0, anchor_1.translateAddress)(poolAddress).toBase58()}`);
}
const tokenDecimalsA = (_a = (yield ctx.accountFetcher.getMintInfo(pool.tokenMintA, false))) === null || _a === void 0 ? void 0 : _a.decimals;
if (!tokenDecimalsA) {
throw new Error(`Token mint not found: ${pool.tokenMintA.toBase58()}`);
}
const tokenDecimalsB = (_b = (yield ctx.accountFetcher.getMintInfo(pool.tokenMintB, false))) === null || _b === void 0 ? void 0 : _b.decimals;
if (!tokenDecimalsB) {
throw new Error(`Token mint not found: ${pool.tokenMintB.toBase58()}`);
}
const tickArrayAddresses = getSurroundingTickArrayAddresses(pool, poolAddress, tickLower, tickUpper, ctx.program.programId);
const tickArrays = yield ctx.accountFetcher.listTickArrays(tickArrayAddresses, refresh);
const currentLiquidity = new decimal_js_1.default(pool.liquidity.toString());
let relativeLiquidity = currentLiquidity;
let minLiquidity = new decimal_js_1.default(0);
let liquidity = new decimal_js_1.default(0);
tickArrays.forEach((tickArray) => {
if (!tickArray) {
return;
}
const startIndex = tickArray.startTickIndex;
tickArray.ticks.forEach((tick, index) => {
const tickIndex = startIndex + index * pool.tickSpacing;
const price = (0, __1.tickIndexToPrice)(tickIndex, tokenDecimalsA, tokenDecimalsB);
const liquidityNet = new decimal_js_1.default(tick.liquidityNet.toString());
liquidity = liquidity.add(liquidityNet);
datapoints.push({ liquidity: new decimal_js_1.default(liquidity), price, tickIndex });
minLiquidity = liquidity.lt(minLiquidity) ? liquidity : minLiquidity;
if (tickIndex === pool.tickCurrentIndex) {
relativeLiquidity = relativeLiquidity.sub(liquidityNet);
}
});
});
if (!relativeLiquidity.eq(currentLiquidity)) {
minLiquidity = minLiquidity.add(relativeLiquidity);
datapoints.forEach((datapoint) => {
datapoint.liquidity = datapoint.liquidity.add(relativeLiquidity);
});
}
if (minLiquidity.lt(0)) {
datapoints.forEach((datapoint) => {
datapoint.liquidity = datapoint.liquidity.add(minLiquidity.neg());
});
}
return {
currentPrice: (0, __1.sqrtPriceX64ToPrice)(pool.sqrtPrice, tokenDecimalsA, tokenDecimalsB),
currentTickIndex: pool.tickCurrentIndex,
datapoints,
};
});
}
exports.getLiquidityDistribution = getLiquidityDistribution;
function getSurroundingTickArrayAddresses(pool, poolAddress, tickLower, tickUpper, programId) {
const tickArrayAddresses = [];
let startIndex = tick_util_1.TickUtil.getStartTickIndex(tickLower, pool.tickSpacing);
while (startIndex <= tickUpper) {
const address = (0, whirlpool_client_sdk_1.getTickArrayPda)((0, address_1.toPubKey)(programId), (0, address_1.toPubKey)(poolAddress), startIndex).publicKey;
tickArrayAddresses.push(address);
try {
startIndex = tick_util_1.TickUtil.getStartTickIndex(startIndex, pool.tickSpacing, 1);
}
catch (_e) {
return tickArrayAddresses;
}
}
return tickArrayAddresses;
}
;