UNPKG

@kamino-finance/kliquidity-sdk

Version:

Typescript SDK for interacting with the Kamino Liquidity (kliquidity) protocol

292 lines 12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReferencePriceType = exports.Dex = exports.RebalanceParamOffset = exports.ProportionalMintingMethod = exports.DollarBasedMintingMethod = void 0; exports.sleep = sleep; exports.dexToNumber = dexToNumber; exports.numberToDex = numberToDex; exports.numberToReferencePriceType = numberToReferencePriceType; exports.getStrategyConfigValue = getStrategyConfigValue; exports.buildStrategyRebalanceParams = buildStrategyRebalanceParams; exports.doesStrategyHaveResetRange = doesStrategyHaveResetRange; exports.numberToDriftDirection = numberToDriftDirection; exports.numberToStakingRateSource = numberToStakingRateSource; exports.numberToAutodriftStep = numberToAutodriftStep; exports.numberToRebalanceType = numberToRebalanceType; exports.getUpdateStrategyConfigIx = getUpdateStrategyConfigIx; exports.collToLamportsDecimal = collToLamportsDecimal; exports.lamportsToNumberDecimal = lamportsToNumberDecimal; exports.readBigUint128LE = readBigUint128LE; exports.readPriceOption = readPriceOption; exports.rebalanceFieldsDictToInfo = rebalanceFieldsDictToInfo; exports.isVaultInitialized = isVaultInitialized; exports.sqrtPriceToPrice = sqrtPriceToPrice; exports.stripTwapZeros = stripTwapZeros; exports.percentageToBPS = percentageToBPS; exports.keyOrDefault = keyOrDefault; exports.optionGetValue = optionGetValue; exports.optionGetValueOrUndefined = optionGetValueOrUndefined; exports.optionGetValueOrDefault = optionGetValueOrDefault; const kit_1 = require("@solana/kit"); const bytes_1 = require("./bytes"); const decimal_js_1 = __importDefault(require("decimal.js")); const types_1 = require("../@codegen/kliquidity/types"); const instructions_1 = require("../@codegen/kliquidity/instructions"); const raydiumBridge_1 = require("./raydiumBridge"); const priceReferenceTypes_1 = require("./priceReferenceTypes"); const numericalValues_1 = require("../constants/numericalValues"); const raydiumSdkCompat_1 = require("./raydiumSdkCompat"); const pubkeys_1 = require("../constants/pubkeys"); const system_1 = require("@solana-program/system"); const whirlpools_core_1 = require("@orca-so/whirlpools-core"); exports.DollarBasedMintingMethod = new decimal_js_1.default(0); exports.ProportionalMintingMethod = new decimal_js_1.default(1); exports.RebalanceParamOffset = new decimal_js_1.default(256); function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } exports.Dex = ['ORCA', 'RAYDIUM', 'METEORA']; exports.ReferencePriceType = [priceReferenceTypes_1.PoolPriceReferenceType, priceReferenceTypes_1.TwapPriceReferenceType]; function dexToNumber(dex) { for (let i = 0; i < exports.Dex.length; i++) { if (exports.Dex[i] === dex) { return i; } } throw new Error(`Unknown DEX ${dex}`); } function numberToDex(num) { const dex = exports.Dex[num]; if (!dex) { throw new Error(`Unknown DEX ${num}`); } return dex; } function numberToReferencePriceType(num) { const referencePriceType = exports.ReferencePriceType[num]; if (!referencePriceType) { throw new Error(`Strategy has invalid reference price type set: ${num}`); } return referencePriceType; } function getStrategyConfigValue(value) { const buf = new Uint8Array(128); const dv = new DataView(buf.buffer); dv.setBigUint64(0, BigInt(value.toString()), true); return [...buf]; } function buildStrategyRebalanceParams(params, rebalance_type, tokenADecimals, tokenBDecimals) { const buf = new Uint8Array(128); const dv = new DataView(buf.buffer); if (rebalance_type === types_1.RebalanceType.Manual) { // Manual has no params } else if (rebalance_type === types_1.RebalanceType.PricePercentage) { dv.setUint16(0, params[0].toNumber(), true); dv.setUint16(2, params[1].toNumber(), true); } else if (rebalance_type === types_1.RebalanceType.PricePercentageWithReset) { dv.setUint16(0, params[0].toNumber(), true); dv.setUint16(2, params[1].toNumber(), true); dv.setUint16(4, params[2].toNumber(), true); dv.setUint16(6, params[3].toNumber(), true); } else if (rebalance_type === types_1.RebalanceType.Drift) { dv.setInt32(0, params[0].toNumber(), true); dv.setInt32(4, params[1].toNumber(), true); dv.setInt32(8, params[2].toNumber(), true); dv.setBigUint64(12, BigInt(params[3].toString()), true); dv.setUint8(20, params[4].toNumber()); } else if (rebalance_type === types_1.RebalanceType.TakeProfit) { // TODO: fix this for meteora const lowerPrice = raydiumSdkCompat_1.RaydiumSqrtPriceMath.priceToSqrtPriceX64(params[0], tokenADecimals, tokenBDecimals); const upperPrice = raydiumSdkCompat_1.RaydiumSqrtPriceMath.priceToSqrtPriceX64(params[1], tokenADecimals, tokenBDecimals); (0, bytes_1.writeU128LE)(dv, 0, (0, raydiumBridge_1.fromBN)(lowerPrice)); (0, bytes_1.writeU128LE)(dv, 16, (0, raydiumBridge_1.fromBN)(upperPrice)); dv.setUint8(32, params[2].toNumber()); } else if (rebalance_type === types_1.RebalanceType.PeriodicRebalance) { dv.setBigUint64(0, BigInt(params[0].toString()), true); dv.setUint16(8, params[1].toNumber(), true); dv.setUint16(10, params[2].toNumber(), true); } else if (rebalance_type === types_1.RebalanceType.Expander) { dv.setUint16(0, params[0].toNumber(), true); dv.setUint16(2, params[1].toNumber(), true); dv.setUint16(4, params[2].toNumber(), true); dv.setUint16(6, params[3].toNumber(), true); dv.setUint16(8, params[4].toNumber(), true); dv.setUint16(10, params[5].toNumber(), true); dv.setUint8(12, params[6].toNumber()); } else if (rebalance_type === types_1.RebalanceType.Autodrift) { dv.setUint32(0, params[0].toNumber(), true); dv.setInt32(4, params[1].toNumber(), true); dv.setInt32(8, params[2].toNumber(), true); dv.setUint16(12, params[3].toNumber(), true); dv.setUint8(14, params[4].toNumber()); dv.setUint8(15, params[5].toNumber()); dv.setUint8(16, params[6].toNumber()); } else { throw 'Rebalance type not valid ' + rebalance_type; } return [...buf]; } function doesStrategyHaveResetRange(rebalanceTypeNumber) { const rebalanceType = numberToRebalanceType(rebalanceTypeNumber); return rebalanceType === types_1.RebalanceType.PricePercentageWithReset || rebalanceType === types_1.RebalanceType.Expander; } function numberToDriftDirection(value) { if (value == 0) { return types_1.DriftDirection.Increasing; } else if (value == 1) { return types_1.DriftDirection.Decreasing; } else { throw new Error(`Invalid drift direction ${value.toString()}`); } } function numberToStakingRateSource(value) { if (value == 0) { return types_1.StakingRateSource.Constant; } else if (value == 1) { return types_1.StakingRateSource.Scope; } else { throw new Error(`Invalid staking rate source ${value.toString()}`); } } function numberToAutodriftStep(value) { if (value == 0) { return types_1.RebalanceAutodriftStep.Uninitialized; } else if (value == 1) { return types_1.RebalanceAutodriftStep.Autodrifting; } else { throw new Error(`Invalid autodrift step ${value.toString()}`); } } function numberToRebalanceType(rebalance_type) { if (rebalance_type == 0) { return types_1.RebalanceType.Manual; } else if (rebalance_type == 1) { return types_1.RebalanceType.PricePercentage; } else if (rebalance_type == 2) { return types_1.RebalanceType.PricePercentageWithReset; } else if (rebalance_type == 3) { return types_1.RebalanceType.Drift; } else if (rebalance_type == 4) { return types_1.RebalanceType.TakeProfit; } else if (rebalance_type == 5) { return types_1.RebalanceType.PeriodicRebalance; } else if (rebalance_type == 6) { return types_1.RebalanceType.Expander; } else if (rebalance_type == 7) { return types_1.RebalanceType.Autodrift; } else { throw new Error(`Invalid rebalance type ${rebalance_type.toString()}`); } } async function getUpdateStrategyConfigIx(signer, globalConfig, strategy, mode, amount, programId, newAccount = pubkeys_1.DEFAULT_PUBLIC_KEY) { return (0, instructions_1.getUpdateStrategyConfigInstruction)({ adminAuthority: signer, newAccount, globalConfig, strategy, systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS, mode, value: new Uint8Array(getStrategyConfigValue(amount)), }, { programAddress: programId }); } function collToLamportsDecimal(amount, decimals) { const factor = new decimal_js_1.default(10).pow(decimals); return amount.mul(factor); } function lamportsToNumberDecimal(amount, decimals) { const factor = new decimal_js_1.default(10).pow(decimals); return new decimal_js_1.default(amount).div(factor); } function readBigUint128LE(buf, offset) { const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); return (0, bytes_1.readU128LE)(dv, offset); } function readPriceOption(buf, offset) { const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength); if (dv.getUint8(offset) == 0) { return [offset + 1, new decimal_js_1.default(0)]; } const value = dv.getBigUint64(offset + 1, true); const exp = dv.getBigUint64(offset + 9, true); return [offset + 17, new decimal_js_1.default(value.toString()).div(new decimal_js_1.default(10).pow(exp.toString()))]; } function rebalanceFieldsDictToInfo(rebalanceFields) { const rebalanceFieldsInfo = []; for (const key in rebalanceFields) { const value = rebalanceFields[key]; rebalanceFieldsInfo.push({ label: key, type: 'number', value: value, enabled: false, }); } return rebalanceFieldsInfo; } function isVaultInitialized(vault, decimals) { return vault !== pubkeys_1.DEFAULT_PUBLIC_KEY && decimals > 0n; } function sqrtPriceToPrice(sqrtPrice, dexNo, decimalsA, decimalsB) { const dex = numberToDex(dexNo); if (dex == 'ORCA') { return new decimal_js_1.default((0, whirlpools_core_1.sqrtPriceToPrice)(sqrtPrice, decimalsA, decimalsB)); } if (dex == 'RAYDIUM') { return raydiumSdkCompat_1.RaydiumSqrtPriceMath.sqrtPriceX64ToPrice((0, raydiumBridge_1.toBN)(sqrtPrice), decimalsA, decimalsB); } if (dex == 'METEORA') { const price = new decimal_js_1.default(sqrtPrice.toString()); return price.div(new decimal_js_1.default(numericalValues_1.U64_MAX)); } throw new Error(`Got invalid dex number ${dex}`); } // Zero is not a valid TWAP component as that indicates the SOL price function stripTwapZeros(chain) { return chain.filter((component) => component > 0); } function percentageToBPS(pct) { return pct * 100; } function keyOrDefault(key, defaultKey) { if (key === pubkeys_1.DEFAULT_PUBLIC_KEY) { return defaultKey; } return key; } // Extract value from Option if Some, otherwise return null function optionGetValue(option) { return (0, kit_1.isSome)(option) ? option.value : null; } // Extract value from Option if Some, otherwise return undefined function optionGetValueOrUndefined(option) { return (0, kit_1.isSome)(option) ? option.value : undefined; } // Extract value from Option if Some, otherwise return provided default function optionGetValueOrDefault(option, defaultValue) { return (0, kit_1.isSome)(option) ? option.value : defaultValue; } //# sourceMappingURL=utils.js.map