UNPKG

@marinade.finance/kamino-sdk

Version:
302 lines (275 loc) 9.82 kB
import Decimal from 'decimal.js'; import { PositionRange, RebalanceFieldInfo, RebalanceFieldsDict } from '../utils/types'; import { DefaultLowerPercentageBPSDecimal, DefaultUpperPercentageBPSDecimal, FullBPSDecimal, } from '../utils/CreationParameters'; import { RebalanceRaw } from '../kamino-client/types'; import { RebalanceTypeLabelName } from './consts'; import { Dex, readBigUint128LE } from '../utils'; import { sqrtPriceX64ToPrice } from '@orca-so/whirlpool-sdk'; import BN from 'bn.js'; import { upsertManyRebalanceFieldInfos } from './utils'; import { getPriceRangeFromPriceAndDiffBPS, getResetRangeFromPriceAndDiffBPS } from './math_utils'; export const PricePercentageWithResetRebalanceTypeName = 'pricePercentageWithReset'; export function getPricePercentageWithResetRebalanceFieldInfos( price: Decimal, lowerPercentageBPS: Decimal, upperPercentageBPS: Decimal, resetLowerPercentageBPS: Decimal, resetUpperPercentageBPS: Decimal, enabled: boolean = true ): RebalanceFieldInfo[] { let rebalanceType: RebalanceFieldInfo = { label: RebalanceTypeLabelName, type: 'string', value: PricePercentageWithResetRebalanceTypeName, enabled, }; let lowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'lowerRangeBps', type: 'number', value: lowerPercentageBPS, enabled, }; let upperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'upperRangeBps', type: 'number', value: upperPercentageBPS, enabled, }; let resetLowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetLowerRangeBps', type: 'number', value: resetLowerPercentageBPS, enabled, }; let resetUpperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetUpperRangeBps', type: 'number', value: resetUpperPercentageBPS, enabled, }; let { lowerPrice, upperPrice } = getPositionRangeFromPricePercentageWithResetParams( price, lowerPercentageBPS, upperPercentageBPS ); let lowerRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'rangePriceLower', type: 'number', value: lowerPrice, enabled: false, }; let upperRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'rangePriceUpper', type: 'number', value: upperPrice, enabled: false, }; let { lowerPrice: resetLowerPrice, upperPrice: resetUpperPrice } = getPositionResetRangeFromPricePercentageWithResetParams( price, lowerPercentageBPS, upperPercentageBPS, resetLowerPercentageBPS, resetUpperPercentageBPS ); let resetLowerRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetPriceLower', type: 'number', value: resetLowerPrice, enabled: false, }; let resetUpperRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetPriceUpper', type: 'number', value: resetUpperPrice, enabled: false, }; return [ rebalanceType, lowerBpsRebalanceFieldInfo, upperBpsRebalanceFieldInfo, resetLowerBpsRebalanceFieldInfo, resetUpperBpsRebalanceFieldInfo, lowerRangeRebalanceFieldInfo, upperRangeRebalanceFieldInfo, resetLowerRangeRebalanceFieldInfo, resetUpperRangeRebalanceFieldInfo, ]; } export function getPositionRangeFromPricePercentageWithResetParams( price: Decimal, lowerPercentageBPS: Decimal, upperPercentageBPS: Decimal ): PositionRange { return getPriceRangeFromPriceAndDiffBPS(price, lowerPercentageBPS, upperPercentageBPS); } export function getPositionResetRangeFromPricePercentageWithResetParams( price: Decimal, lowerPercentageBPS: Decimal, upperPercentageBPS: Decimal, resetLowerPercentageBPS: Decimal, resetUpperPercentageBPS: Decimal ): PositionRange { return getResetRangeFromPriceAndDiffBPS( price, lowerPercentageBPS, upperPercentageBPS, resetLowerPercentageBPS, resetUpperPercentageBPS ); } export function getDefaultPricePercentageWithResetRebalanceFieldInfos(price: Decimal): RebalanceFieldInfo[] { let fieldInfos = getPricePercentageWithResetRebalanceFieldInfos( price, DefaultLowerPercentageBPSDecimal, DefaultUpperPercentageBPSDecimal, DefaultLowerPercentageBPSDecimal, DefaultUpperPercentageBPSDecimal ); return fieldInfos; } export function readPricePercentageWithResetRebalanceParamsFromStrategy( rebalanceRaw: RebalanceRaw ): RebalanceFieldInfo[] { let paramsBuffer = Buffer.from(rebalanceRaw.params); let lowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'lowerRangeBps', type: 'number', value: new Decimal(paramsBuffer.readUint16LE(0)), enabled: true, }; let upperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'upperRangeBps', type: 'number', value: new Decimal(paramsBuffer.readUint16LE(2)), enabled: true, }; let resetLowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetLowerRangeBps', type: 'number', value: new Decimal(paramsBuffer.readUint16LE(4)), enabled: true, }; let resetUpperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetUpperRangeBps', type: 'number', value: new Decimal(paramsBuffer.readUint16LE(6)), enabled: true, }; return [ lowerBpsRebalanceFieldInfo, upperBpsRebalanceFieldInfo, resetLowerBpsRebalanceFieldInfo, resetUpperBpsRebalanceFieldInfo, ]; } export function readRawPricePercentageWithResetRebalanceStateFromStrategy( rebalanceRaw: RebalanceRaw ): RebalanceFieldInfo[] { let stateBuffer = Buffer.from(rebalanceRaw.state); let lowerRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'lastRebalanceLowerResetPoolPrice', type: 'number', value: new Decimal(readBigUint128LE(stateBuffer, 0).toString()), enabled: false, }; let upperRangeRebalanceFieldInfo: RebalanceFieldInfo = { label: 'lastRebalanceUpperResetPoolPrice', type: 'number', value: new Decimal(readBigUint128LE(stateBuffer, 16).toString()), enabled: false, }; return [lowerRangeRebalanceFieldInfo, upperRangeRebalanceFieldInfo]; } export function readPricePercentageWithResetRebalanceStateFromStrategy( dex: Dex, tokenADecimals: number, tokenBDecimals: number, rebalanceRaw: RebalanceRaw ): RebalanceFieldInfo[] { let stateBuffer = Buffer.from(rebalanceRaw.state); let params = readPricePercentageWithResetRebalanceParamsFromStrategy(rebalanceRaw); let resetLowerRangeBps = new Decimal(params.find((param) => param.label == 'resetLowerRangeBps')?.value.toString()!); let resetUpperRangeBps = new Decimal(params.find((param) => param.label == 'resetUpperRangeBps')?.value!.toString()!); let lowerResetSqrtPriceX64 = new Decimal(readBigUint128LE(stateBuffer, 0).toString()); let upperResetSqrtPriceX64 = new Decimal(readBigUint128LE(stateBuffer, 16).toString()); let lowerResetPrice: Decimal, upperResetPrice: Decimal; if (dex == 'ORCA') { lowerResetPrice = sqrtPriceX64ToPrice(new BN(lowerResetSqrtPriceX64.toString()), tokenADecimals, tokenBDecimals); upperResetPrice = sqrtPriceX64ToPrice(new BN(upperResetSqrtPriceX64.toString()), tokenADecimals, tokenBDecimals); } else if (dex == 'RAYDIUM') { lowerResetPrice = sqrtPriceX64ToPrice(new BN(lowerResetSqrtPriceX64.toString()), tokenADecimals, tokenBDecimals); upperResetPrice = sqrtPriceX64ToPrice(new BN(upperResetSqrtPriceX64.toString()), tokenADecimals, tokenBDecimals); } else { throw new Error(`Unknown DEX ${dex}`); } let lowerPositionPrice = lowerResetPrice.mul(FullBPSDecimal).div(resetLowerRangeBps); let upperPositionPrice = upperResetPrice.div(FullBPSDecimal).mul(resetUpperRangeBps); let lowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'rangePriceLower', type: 'number', value: lowerPositionPrice, enabled: true, }; let upperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'rangePriceUpper', type: 'number', value: upperPositionPrice, enabled: true, }; let resetLowerBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetPriceLower', type: 'number', value: lowerResetPrice, enabled: true, }; let resetUpperBpsRebalanceFieldInfo: RebalanceFieldInfo = { label: 'resetPriceUpper', type: 'number', value: upperResetPrice, enabled: true, }; return [ lowerBpsRebalanceFieldInfo, upperBpsRebalanceFieldInfo, resetLowerBpsRebalanceFieldInfo, resetUpperBpsRebalanceFieldInfo, ]; } export function deserializePricePercentageWithResetRebalanceFromOnchainParams( price: Decimal, rebalanceRaw: RebalanceRaw ): RebalanceFieldInfo[] { let params = readPricePercentageWithResetRebalanceParamsFromStrategy(rebalanceRaw); let lowerRangeBps = new Decimal(params.find((param) => param.label == 'lowerRangeBps')?.value.toString()!); let upperRangeBps = new Decimal(params.find((param) => param.label == 'upperRangeBps')?.value.toString()!); let lowerResetRangeBps = new Decimal(params.find((param) => param.label == 'resetLowerRangeBps')?.value.toString()!); let upperResetRangeBps = new Decimal(params.find((param) => param.label == 'resetUpperRangeBps')?.value.toString()!); return getPricePercentageWithResetRebalanceFieldInfos( price, lowerRangeBps, upperRangeBps, lowerResetRangeBps, upperResetRangeBps ); } export function deserializePricePercentageWithResetRebalanceWithStateOverride( dex: Dex, tokenADecimals: number, tokenBDecimals: number, price: Decimal, rebalanceRaw: RebalanceRaw ): RebalanceFieldInfo[] { const stateFields = readPricePercentageWithResetRebalanceStateFromStrategy( dex, tokenADecimals, tokenBDecimals, rebalanceRaw ); let fields = deserializePricePercentageWithResetRebalanceFromOnchainParams(price, rebalanceRaw); return upsertManyRebalanceFieldInfos(fields, stateFields); }