UNPKG

@drift-labs/sdk

Version:
165 lines (164 loc) • 6.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateBudgetedPeg = exports.calculateBudgetedK = exports.calculateBudgetedKBN = exports.calculateRepegCost = exports.calculateAdjustKCost = void 0; const anchor_1 = require("@coral-xyz/anchor"); const assert_1 = require("../assert/assert"); const numericConstants_1 = require("../constants/numericConstants"); /** * Helper function calculating adjust k cost * @param amm * @param numerator * @param denomenator * @returns cost : Precision QUOTE_ASSET_PRECISION */ function calculateAdjustKCost(amm, numerator, denomenator) { // const k = market.amm.sqrtK.mul(market.amm.sqrtK); const x = amm.baseAssetReserve; const y = amm.quoteAssetReserve; const d = amm.baseAssetAmountWithAmm; const Q = amm.pegMultiplier; const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION); const p = numerator.mul(numericConstants_1.PRICE_PRECISION).div(denomenator); const cost = quoteScale .mul(numericConstants_1.PERCENTAGE_PRECISION) .mul(numericConstants_1.PERCENTAGE_PRECISION) .div(x.add(d)) .sub(quoteScale .mul(p) .mul(numericConstants_1.PERCENTAGE_PRECISION) .mul(numericConstants_1.PERCENTAGE_PRECISION) .div(numericConstants_1.PRICE_PRECISION) .div(x.mul(p).div(numericConstants_1.PRICE_PRECISION).add(d))) .div(numericConstants_1.PERCENTAGE_PRECISION) .div(numericConstants_1.PERCENTAGE_PRECISION) .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO) .div(numericConstants_1.PEG_PRECISION); return cost.mul(new anchor_1.BN(-1)); } exports.calculateAdjustKCost = calculateAdjustKCost; // /** // * Helper function calculating adjust k cost // * @param amm // * @param numerator // * @param denomenator // * @returns cost : Precision QUOTE_ASSET_PRECISION // */ // export function calculateAdjustKCost2( // amm: AMM, // numerator: BN, // denomenator: BN // ): BN { // // const k = market.amm.sqrtK.mul(market.amm.sqrtK); // const directionToClose = amm.baseAssetAmountWithAmm.gt(ZERO) // ? PositionDirection.SHORT // : PositionDirection.LONG; // const [newQuoteAssetReserve, _newBaseAssetReserve] = // calculateAmmReservesAfterSwap( // amm, // 'base', // amm.baseAssetAmountWithAmm.abs(), // getSwapDirection('base', directionToClose) // ); // } /** * Helper function calculating adjust pegMultiplier (repeg) cost * * @param amm * @param newPeg * @returns cost : Precision QUOTE_ASSET_PRECISION */ function calculateRepegCost(amm, newPeg) { const dqar = amm.quoteAssetReserve.sub(amm.terminalQuoteAssetReserve); const cost = dqar .mul(newPeg.sub(amm.pegMultiplier)) .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO) .div(numericConstants_1.PEG_PRECISION); return cost; } exports.calculateRepegCost = calculateRepegCost; function calculateBudgetedKBN(x, y, budget, Q, d) { (0, assert_1.assert)(Q.gt(new anchor_1.BN(0))); const C = budget.mul(new anchor_1.BN(-1)); let dSign = new anchor_1.BN(1); if (d.lt(new anchor_1.BN(0))) { dSign = new anchor_1.BN(-1); } const pegged_y_d_d = y .mul(d) .mul(d) .mul(Q) .div(numericConstants_1.AMM_RESERVE_PRECISION) .div(numericConstants_1.AMM_RESERVE_PRECISION) .div(numericConstants_1.PEG_PRECISION); const numer1 = pegged_y_d_d; const numer2 = C.mul(d) .div(numericConstants_1.QUOTE_PRECISION) .mul(x.add(d)) .div(numericConstants_1.AMM_RESERVE_PRECISION) .mul(dSign); const denom1 = C.mul(x) .mul(x.add(d)) .div(numericConstants_1.AMM_RESERVE_PRECISION) .div(numericConstants_1.QUOTE_PRECISION); const denom2 = pegged_y_d_d; // protocol is spending to increase k if (C.lt(numericConstants_1.ZERO)) { // thus denom1 is negative and solution is unstable if (denom1.abs().gt(denom2.abs())) { console.log('denom1 > denom2', denom1.toString(), denom2.toString()); console.log('budget cost exceeds stable K solution'); return [new anchor_1.BN(10000), new anchor_1.BN(1)]; } } const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO); const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO); return [numerator, denominator]; } exports.calculateBudgetedKBN = calculateBudgetedKBN; function calculateBudgetedK(amm, cost) { // wolframalpha.com // (1/(x+d) - p/(x*p+d))*y*d*Q = C solve for p // p = (d(y*d*Q - C(x+d))) / (C*x(x+d) + y*d*d*Q) // numer // = y*d*d*Q - Cxd - Cdd // = y/x*Q*d*d - Cd - Cd/x // = mark - C/d - C/(x) // = mark/C - 1/d - 1/x // denom // = C*x*x + C*x*d + y*d*d*Q // = x/d**2 + 1 / d + mark/C // todo: assumes k = x * y // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p const x = amm.baseAssetReserve; const y = amm.quoteAssetReserve; const d = amm.baseAssetAmountWithAmm; const Q = amm.pegMultiplier; const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d); return [numerator, denominator]; } exports.calculateBudgetedK = calculateBudgetedK; function calculateBudgetedPeg(amm, budget, targetPrice) { let perPegCost = amm.quoteAssetReserve .sub(amm.terminalQuoteAssetReserve) .div(numericConstants_1.AMM_RESERVE_PRECISION.div(numericConstants_1.PRICE_PRECISION)); if (perPegCost.gt(numericConstants_1.ZERO)) { perPegCost = perPegCost.add(numericConstants_1.ONE); } else if (perPegCost.lt(numericConstants_1.ZERO)) { perPegCost = perPegCost.sub(numericConstants_1.ONE); } const targetPeg = targetPrice .mul(amm.baseAssetReserve) .div(amm.quoteAssetReserve) .div(numericConstants_1.PRICE_DIV_PEG); const pegChangeDirection = targetPeg.sub(amm.pegMultiplier); const useTargetPeg = (perPegCost.lt(numericConstants_1.ZERO) && pegChangeDirection.gt(numericConstants_1.ZERO)) || (perPegCost.gt(numericConstants_1.ZERO) && pegChangeDirection.lt(numericConstants_1.ZERO)); if (perPegCost.eq(numericConstants_1.ZERO) || useTargetPeg) { return targetPeg; } const budgetDeltaPeg = budget.mul(numericConstants_1.PEG_PRECISION).div(perPegCost); const newPeg = anchor_1.BN.max(numericConstants_1.ONE, amm.pegMultiplier.add(budgetDeltaPeg)); return newPeg; } exports.calculateBudgetedPeg = calculateBudgetedPeg;