UNPKG

@renec-foundation/redex-sdk

Version:

Typescript SDK to interact with Orca's Whirlpool program.

91 lines (90 loc) 4.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.adjustForSlippage = exports.getNextSqrtPrice = exports.getAmountDeltaB = exports.getAmountDeltaA = void 0; const common_sdk_1 = require("@orca-so/common-sdk"); const anchor_1 = require("@project-serum/anchor"); const errors_1 = require("../../errors/errors"); const public_1 = require("../../types/public"); const bit_math_1 = require("./bit-math"); function getAmountDeltaA(currSqrtPrice, targetSqrtPrice, currLiquidity, roundUp) { let [sqrtPriceLower, sqrtPriceUpper] = toIncreasingPriceOrder(currSqrtPrice, targetSqrtPrice); let sqrtPriceDiff = sqrtPriceUpper.sub(sqrtPriceLower); let numerator = currLiquidity.mul(sqrtPriceDiff).shln(64); let denominator = sqrtPriceLower.mul(sqrtPriceUpper); let quotient = numerator.div(denominator); let remainder = numerator.mod(denominator); let result = roundUp && !remainder.eq(common_sdk_1.ZERO) ? quotient.add(new anchor_1.BN(1)) : quotient; if (result.gt(common_sdk_1.U64_MAX)) { throw new errors_1.WhirlpoolsError("Results larger than U64", errors_1.TokenErrorCode.TokenMaxExceeded); } return result; } exports.getAmountDeltaA = getAmountDeltaA; function getAmountDeltaB(currSqrtPrice, targetSqrtPrice, currLiquidity, roundUp) { let [sqrtPriceLower, sqrtPriceUpper] = toIncreasingPriceOrder(currSqrtPrice, targetSqrtPrice); let sqrtPriceDiff = sqrtPriceUpper.sub(sqrtPriceLower); return bit_math_1.BitMath.checked_mul_shift_right_round_up_if(currLiquidity, sqrtPriceDiff, roundUp, 128); } exports.getAmountDeltaB = getAmountDeltaB; function getNextSqrtPrice(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput, aToB) { if (amountSpecifiedIsInput === aToB) { return getNextSqrtPriceFromARoundUp(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput); } else { return getNextSqrtPriceFromBRoundDown(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput); } } exports.getNextSqrtPrice = getNextSqrtPrice; function adjustForSlippage(n, { numerator, denominator }, adjustUp) { if (adjustUp) { return n.mul(denominator.add(numerator)).div(denominator); } else { return n.mul(denominator).div(denominator.add(numerator)); } } exports.adjustForSlippage = adjustForSlippage; function toIncreasingPriceOrder(sqrtPrice0, sqrtPrice1) { if (sqrtPrice0.gt(sqrtPrice1)) { return [sqrtPrice1, sqrtPrice0]; } else { return [sqrtPrice0, sqrtPrice1]; } } function getNextSqrtPriceFromARoundUp(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput) { if (amount.eq(common_sdk_1.ZERO)) { return sqrtPrice; } let p = bit_math_1.BitMath.mul(sqrtPrice, amount, 256); let numerator = bit_math_1.BitMath.mul(currLiquidity, sqrtPrice, 256).shln(64); if (bit_math_1.BitMath.isOverLimit(numerator, 256)) { throw new errors_1.WhirlpoolsError("getNextSqrtPriceFromARoundUp - numerator overflow u256", errors_1.MathErrorCode.MultiplicationOverflow); } let currLiquidityShiftLeft = currLiquidity.shln(64); if (!amountSpecifiedIsInput && currLiquidityShiftLeft.lte(p)) { throw new errors_1.WhirlpoolsError("getNextSqrtPriceFromARoundUp - Unable to divide currLiquidityX64 by product", errors_1.MathErrorCode.DivideByZero); } let denominator = amountSpecifiedIsInput ? currLiquidityShiftLeft.add(p) : currLiquidityShiftLeft.sub(p); let price = bit_math_1.BitMath.divRoundUp(numerator, denominator); if (price.lt(new anchor_1.BN(public_1.MIN_SQRT_PRICE))) { throw new errors_1.WhirlpoolsError("getNextSqrtPriceFromARoundUp - price less than min sqrt price", errors_1.TokenErrorCode.TokenMinSubceeded); } else if (price.gt(new anchor_1.BN(public_1.MAX_SQRT_PRICE))) { throw new errors_1.WhirlpoolsError("getNextSqrtPriceFromARoundUp - price less than max sqrt price", errors_1.TokenErrorCode.TokenMaxExceeded); } return price; } function getNextSqrtPriceFromBRoundDown(sqrtPrice, currLiquidity, amount, amountSpecifiedIsInput) { let amountX64 = amount.shln(64); let delta = bit_math_1.BitMath.divRoundUpIf(amountX64, currLiquidity, !amountSpecifiedIsInput); if (amountSpecifiedIsInput) { sqrtPrice = sqrtPrice.add(delta); } else { sqrtPrice = sqrtPrice.sub(delta); } return sqrtPrice; }