@kamino-finance/kliquidity-sdk
Version:
Typescript SDK for interacting with the Kamino Liquidity (kliquidity) protocol
220 lines • 12.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutodriftRebalanceTypeName = exports.DEFAULT_DIRECTION = exports.DEFAULT_STAKING_RATE_SOURCE_B = exports.DEFAULT_STAKING_RATE_SOURCE_A = exports.DEFAULT_FRONTRUN_MULTIPLIER_BPS = exports.DEFAULT_TICKS_ABOVE_MID = exports.DEFAULT_TICKS_BELOW_MID = exports.DEFAULT_DRIFT_TICKS_PER_EPOCH = void 0;
exports.getAutodriftRebalanceFieldInfos = getAutodriftRebalanceFieldInfos;
exports.getPositionRangeFromAutodriftParams = getPositionRangeFromAutodriftParams;
exports.getDefaultAutodriftRebalanceFieldInfos = getDefaultAutodriftRebalanceFieldInfos;
exports.readAutodriftRebalanceParamsFromStrategy = readAutodriftRebalanceParamsFromStrategy;
exports.readRawAutodriftRebalanceStateFromStrategy = readRawAutodriftRebalanceStateFromStrategy;
exports.readAutodriftRebalanceStateFromStrategy = readAutodriftRebalanceStateFromStrategy;
exports.deserializeAutodriftRebalanceFromOnchainParams = deserializeAutodriftRebalanceFromOnchainParams;
exports.deserializeAutodriftRebalanceWithStateOverride = deserializeAutodriftRebalanceWithStateOverride;
const decimal_js_1 = __importDefault(require("decimal.js"));
const utils_1 = require("../utils");
const whirlpool_sdk_1 = require("@orca-so/whirlpool-sdk");
const consts_1 = require("./consts");
const utils_2 = require("./utils");
const meteora_1 = require("../utils/meteora");
const lib_1 = require("@raydium-io/raydium-sdk-v2/lib");
exports.DEFAULT_DRIFT_TICKS_PER_EPOCH = new decimal_js_1.default(1);
exports.DEFAULT_TICKS_BELOW_MID = new decimal_js_1.default(10);
exports.DEFAULT_TICKS_ABOVE_MID = new decimal_js_1.default(10);
exports.DEFAULT_FRONTRUN_MULTIPLIER_BPS = new decimal_js_1.default(10_000);
exports.DEFAULT_STAKING_RATE_SOURCE_A = new decimal_js_1.default(0);
exports.DEFAULT_STAKING_RATE_SOURCE_B = new decimal_js_1.default(0);
exports.DEFAULT_DIRECTION = new decimal_js_1.default(1);
exports.AutodriftRebalanceTypeName = 'autodrift';
function getAutodriftRebalanceFieldInfos(dex, tokenADecimals, tokenBDecimals, tickSpacing, lastMidTick, initDriftTicksPerEpoch, ticksBelowMid, ticksAboveMid, frontrunMultiplierBps, stakingRateASource, stakingRateBSource, initialDriftDirection, enabled = true) {
const rebalanceType = {
label: consts_1.RebalanceTypeLabelName,
type: 'string',
value: exports.AutodriftRebalanceTypeName,
enabled,
};
const lastMidTickRebalanceFieldInfo = {
label: 'lastMidTick',
type: 'number',
value: lastMidTick,
enabled: false,
};
const initDriftTicksPerEpochRebalanceFieldInfo = {
label: 'initDriftTicksPerEpoch',
type: 'number',
value: initDriftTicksPerEpoch,
enabled,
};
const ticksBelowMidRebalanceFieldInfo = {
label: 'ticksBelowMid',
type: 'number',
value: ticksBelowMid,
enabled,
};
const ticksAboveMidRebalanceFieldInfo = {
label: 'ticksAboveMid',
type: 'number',
value: ticksAboveMid,
enabled,
};
const fronturnMultiplierBpsRebalanceFieldInfo = {
label: 'frontrunMultiplierBps',
type: 'number',
value: frontrunMultiplierBps,
enabled,
};
const stakingRateASourceRebalanceFieldInfo = {
label: 'stakingRateASource',
type: 'number',
value: stakingRateASource,
enabled,
};
const stakingRateBSourceRebalanceFieldInfo = {
label: 'stakingRateBSource',
type: 'number',
value: stakingRateBSource,
enabled,
};
const initialDriftDirectionRebalanceFieldInfo = {
label: 'initialDriftDirection',
type: 'number',
value: initialDriftDirection,
enabled,
};
const { lowerPrice, upperPrice } = getPositionRangeFromAutodriftParams(dex, tokenADecimals, tokenBDecimals, lastMidTick, ticksBelowMid, ticksAboveMid, tickSpacing);
const lowerRangeRebalanceFieldInfo = {
label: 'rangePriceLower',
type: 'number',
value: lowerPrice,
enabled: false,
};
const upperRangeRebalanceFieldInfo = {
label: 'rangePriceUpper',
type: 'number',
value: upperPrice,
enabled: false,
};
return [
rebalanceType,
ticksBelowMidRebalanceFieldInfo,
ticksAboveMidRebalanceFieldInfo,
initialDriftDirectionRebalanceFieldInfo,
lowerRangeRebalanceFieldInfo,
upperRangeRebalanceFieldInfo,
fronturnMultiplierBpsRebalanceFieldInfo,
stakingRateASourceRebalanceFieldInfo,
stakingRateBSourceRebalanceFieldInfo,
initDriftTicksPerEpochRebalanceFieldInfo,
lastMidTickRebalanceFieldInfo,
];
}
function getPositionRangeFromAutodriftParams(dex, tokenADecimals, tokenBDecimals, startMidTick, ticksBelowMid, ticksAboveMid, tickSpacing) {
const lowerTickIndex = startMidTick.sub(ticksBelowMid);
const upperTickIndex = startMidTick.add(ticksAboveMid);
if (dex == 'ORCA') {
const lowerPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(lowerTickIndex.toNumber(), tokenADecimals, tokenBDecimals);
const upperPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(upperTickIndex.toNumber(), tokenADecimals, tokenBDecimals);
return { lowerPrice, upperPrice };
}
else if (dex == 'RAYDIUM') {
const lowerPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(lowerTickIndex.toNumber()), tokenADecimals, tokenBDecimals);
const upperPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(upperTickIndex.toNumber()), tokenADecimals, tokenBDecimals);
return { lowerPrice, upperPrice };
}
else if (dex == 'METEORA') {
const lowerPrice = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(lowerTickIndex.toNumber(), tickSpacing, tokenADecimals, tokenBDecimals);
const upperPrice = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(upperTickIndex.toNumber(), tickSpacing, tokenADecimals, tokenBDecimals);
return { lowerPrice, upperPrice };
}
else {
throw new Error(`Unknown DEX ${dex}`);
}
}
// todo(silviu): get sensible default params from Matt
function getDefaultAutodriftRebalanceFieldInfos(dex, price, tokenADecimals, tokenBDecimals, tickSpacing) {
const currentTickIndex = (0, whirlpool_sdk_1.priceToTickIndex)(price, tokenADecimals, tokenBDecimals);
const startMidTick = new decimal_js_1.default(currentTickIndex);
return getAutodriftRebalanceFieldInfos(dex, tokenADecimals, tokenBDecimals, tickSpacing, startMidTick, exports.DEFAULT_DRIFT_TICKS_PER_EPOCH, exports.DEFAULT_TICKS_BELOW_MID, exports.DEFAULT_TICKS_ABOVE_MID, exports.DEFAULT_FRONTRUN_MULTIPLIER_BPS, exports.DEFAULT_STAKING_RATE_SOURCE_A, exports.DEFAULT_STAKING_RATE_SOURCE_B, exports.DEFAULT_DIRECTION);
}
function readAutodriftRebalanceParamsFromStrategy(rebalanceRaw) {
const paramsBuffer = Buffer.from(rebalanceRaw.params);
const params = {};
params['initDriftTicksPerEpoch'] = new decimal_js_1.default(paramsBuffer.readUInt32LE(0));
params['ticksBelowMid'] = new decimal_js_1.default(paramsBuffer.readInt32LE(4));
params['ticksAboveMid'] = new decimal_js_1.default(paramsBuffer.readInt32LE(8));
params['frontrunMultiplierBps'] = new decimal_js_1.default(paramsBuffer.readUInt16LE(12));
params['stakingRateASource'] = new decimal_js_1.default(paramsBuffer.readUint8(14));
params['stakingRateBSource'] = new decimal_js_1.default(paramsBuffer.readUint8(15));
params['initialDriftDirection'] = new decimal_js_1.default(paramsBuffer.readUint8(16));
return params;
}
function readRawAutodriftRebalanceStateFromStrategy(rebalanceRaw) {
const stateBuffer = Buffer.from(rebalanceRaw.state);
const state = {};
// prettier-ignore
{
let offset = 0;
[offset, state['last_window_staking_rate_a']] = (0, utils_1.readPriceOption)(stateBuffer, offset);
[offset, state['last_window_staking_rate_b']] = (0, utils_1.readPriceOption)(stateBuffer, offset);
[offset, state['last_window_epoch']] = [offset + 8, new decimal_js_1.default(stateBuffer.readBigUInt64LE(offset).toString())];
[offset, state['last_window_theoretical_tick']] = [offset + 4, new decimal_js_1.default(stateBuffer.readInt32LE(offset))];
[offset, state['last_window_strat_mid_tick']] = [offset + 4, new decimal_js_1.default(stateBuffer.readInt32LE(offset))];
[offset, state['current_window_staking_rate_a']] = (0, utils_1.readPriceOption)(stateBuffer, offset);
[offset, state['current_window_staking_rate_b']] = (0, utils_1.readPriceOption)(stateBuffer, offset);
[offset, state['current_window_epoch']] = [offset + 8, new decimal_js_1.default(stateBuffer.readBigUInt64LE(offset).toString())];
[offset, state['current_window_theoretical_tick']] = [offset + 4, new decimal_js_1.default(stateBuffer.readInt32LE(offset))];
[offset, state['current_window_strat_mid_tick']] = [offset + 4, new decimal_js_1.default(stateBuffer.readInt32LE(offset))];
[offset, state['autodrift_step']] = [offset + 1, new decimal_js_1.default(stateBuffer.readInt8(offset))];
}
return state;
}
function readAutodriftRebalanceStateFromStrategy(dex, tokenADecimals, tokenBDecimals, tickSpacing, rebalanceRaw) {
const params = readAutodriftRebalanceParamsFromStrategy(rebalanceRaw);
const state = readRawAutodriftRebalanceStateFromStrategy(rebalanceRaw);
const lastMidTick = state['current_window_strat_mid_tick'];
const ticksBelowMid = params['ticksBelowMid'];
const ticksAboveMid = params['ticksAboveMid'];
const lowerTickIndex = lastMidTick.sub(ticksBelowMid);
const upperTickIndex = lastMidTick.add(ticksAboveMid);
let lowerPrice, upperPrice;
if (dex == 'ORCA') {
lowerPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(lowerTickIndex.toNumber(), tokenADecimals, tokenBDecimals);
upperPrice = (0, whirlpool_sdk_1.tickIndexToPrice)(upperTickIndex.toNumber(), tokenADecimals, tokenBDecimals);
}
else if (dex == 'RAYDIUM') {
lowerPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(lowerTickIndex.toNumber()), tokenADecimals, tokenBDecimals);
upperPrice = (0, whirlpool_sdk_1.sqrtPriceX64ToPrice)(lib_1.SqrtPriceMath.getSqrtPriceX64FromTick(upperTickIndex.toNumber()), tokenADecimals, tokenBDecimals);
}
else if (dex == 'METEORA') {
lowerPrice = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(lowerTickIndex.toNumber(), tickSpacing, tokenADecimals, tokenBDecimals);
upperPrice = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(upperTickIndex.toNumber(), tickSpacing, tokenADecimals, tokenBDecimals);
}
else {
throw new Error(`Unknown DEX ${dex}`);
}
const lowerRangeRebalanceFieldInfo = {
label: 'rangePriceLower',
type: 'number',
value: lowerPrice,
enabled: false,
};
const upperRangeRebalanceFieldInfo = {
label: 'rangePriceUpper',
type: 'number',
value: upperPrice,
enabled: false,
};
return [lowerRangeRebalanceFieldInfo, upperRangeRebalanceFieldInfo];
}
function deserializeAutodriftRebalanceFromOnchainParams(dex, tokenADecimals, tokenBDecimals, tickSpacing, rebalanceRaw) {
const params = readAutodriftRebalanceParamsFromStrategy(rebalanceRaw);
const state = readRawAutodriftRebalanceStateFromStrategy(rebalanceRaw);
return getAutodriftRebalanceFieldInfos(dex, tokenADecimals, tokenBDecimals, tickSpacing, state['current_window_strat_mid_tick'], params['initDriftTicksPerEpoch'], params['ticksBelowMid'], params['ticksAboveMid'], params['frontrunMultiplierBps'], params['stakingRateASource'], params['stakingRateBSource'], params['initialDriftDirection']);
}
function deserializeAutodriftRebalanceWithStateOverride(dex, tokenADecimals, tokenBDecimals, tickSpacing, rebalanceRaw) {
const stateFields = readAutodriftRebalanceStateFromStrategy(dex, tokenADecimals, tokenBDecimals, tickSpacing, rebalanceRaw);
const fields = deserializeAutodriftRebalanceFromOnchainParams(dex, tokenADecimals, tokenBDecimals, tickSpacing, rebalanceRaw);
return (0, utils_2.upsertManyRebalanceFieldInfos)(fields, stateFields);
}
//# sourceMappingURL=autodriftRebalance.js.map