@kamino-finance/kliquidity-sdk
Version:
Typescript SDK for interacting with the Kamino Liquidity (kliquidity) protocol
180 lines • 9.61 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.DriftRebalanceTypeName = exports.DEFAULT_DIRECTION = exports.DEFAULT_SECONDS_PER_TICK = exports.DEFAULT_TICKS_ABOVE_MID = exports.DEFAULT_TICKS_BELOW_MID = void 0;
exports.getDriftRebalanceFieldInfos = getDriftRebalanceFieldInfos;
exports.getPositionRangeFromDriftParams = getPositionRangeFromDriftParams;
exports.getDefaultDriftRebalanceFieldInfos = getDefaultDriftRebalanceFieldInfos;
exports.readDriftRebalanceParamsFromStrategy = readDriftRebalanceParamsFromStrategy;
exports.readRawDriftRebalanceStateFromStrategy = readRawDriftRebalanceStateFromStrategy;
exports.readDriftRebalanceStateFromStrategy = readDriftRebalanceStateFromStrategy;
exports.deserializeDriftRebalanceFromOnchainParams = deserializeDriftRebalanceFromOnchainParams;
exports.deserializeDriftRebalanceWithStateOverride = deserializeDriftRebalanceWithStateOverride;
const decimal_js_1 = __importDefault(require("decimal.js"));
const whirlpool_sdk_1 = require("@orca-so/whirlpool-sdk");
const consts_1 = require("./consts");
const utils_1 = require("./utils");
const meteora_1 = require("../utils/meteora");
const lib_1 = require("@raydium-io/raydium-sdk-v2/lib");
exports.DEFAULT_TICKS_BELOW_MID = new decimal_js_1.default(10);
exports.DEFAULT_TICKS_ABOVE_MID = new decimal_js_1.default(10);
exports.DEFAULT_SECONDS_PER_TICK = new decimal_js_1.default(60 * 60 * 24 * 3); // 3 days; todo: get a reasonable default from Matt
exports.DEFAULT_DIRECTION = new decimal_js_1.default(1);
exports.DriftRebalanceTypeName = 'drift';
function getDriftRebalanceFieldInfos(dex, tickSpacing, tokenADecimals, tokenBDecimals, startMidTick, ticksBelowMid, ticksAboveMid, secondsPerTick, direction, enabled = true) {
const rebalanceType = {
label: consts_1.RebalanceTypeLabelName,
type: 'string',
value: exports.DriftRebalanceTypeName,
enabled,
};
const startMidTickRebalanceFieldInfo = {
label: 'startMidTick',
type: 'number',
value: startMidTick,
enabled,
};
const ticksBelowMidRebalanceFieldInfo = {
label: 'ticksBelowMid',
type: 'number',
value: ticksBelowMid,
enabled,
};
const ticksAboveMidRebalanceFieldInfo = {
label: 'ticksAboveMid',
type: 'number',
value: ticksAboveMid,
enabled,
};
const secondsPerTickRebalanceFieldInfo = {
label: 'secondsPerTick',
type: 'number',
value: secondsPerTick,
enabled,
};
const directionRebalanceFieldInfo = {
label: 'direction',
type: 'number',
value: direction,
enabled,
};
const { lowerPrice, upperPrice } = getPositionRangeFromDriftParams(dex, tokenADecimals, tokenBDecimals, tickSpacing, startMidTick, ticksBelowMid, ticksAboveMid);
const lowerRangeRebalanceFieldInfo = {
label: 'rangePriceLower',
type: 'number',
value: lowerPrice,
enabled: false,
};
const upperRangeRebalanceFieldInfo = {
label: 'rangePriceUpper',
type: 'number',
value: upperPrice,
enabled: false,
};
return [
rebalanceType,
startMidTickRebalanceFieldInfo,
ticksBelowMidRebalanceFieldInfo,
ticksAboveMidRebalanceFieldInfo,
secondsPerTickRebalanceFieldInfo,
directionRebalanceFieldInfo,
lowerRangeRebalanceFieldInfo,
upperRangeRebalanceFieldInfo,
];
}
function getPositionRangeFromDriftParams(dex, tickSpacing, tokenADecimals, tokenBDecimals, startMidTick, ticksBelowMid, ticksAboveMid) {
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 getDefaultDriftRebalanceFieldInfos(dex, tickSpacing, price, tokenADecimals, tokenBDecimals) {
const currentTickIndex = (0, whirlpool_sdk_1.priceToTickIndex)(price, tokenADecimals, tokenBDecimals);
const startMidTick = new decimal_js_1.default(currentTickIndex);
return getDriftRebalanceFieldInfos(dex, tickSpacing, tokenADecimals, tokenBDecimals, startMidTick, exports.DEFAULT_TICKS_BELOW_MID, exports.DEFAULT_TICKS_ABOVE_MID, exports.DEFAULT_SECONDS_PER_TICK, exports.DEFAULT_DIRECTION);
}
function readDriftRebalanceParamsFromStrategy(rebalanceRaw) {
const paramsBuffer = Buffer.from(rebalanceRaw.params);
const params = {};
params['startMidTick'] = new decimal_js_1.default(paramsBuffer.readInt32LE(0));
params['ticksBelowMid'] = new decimal_js_1.default(paramsBuffer.readInt32LE(4));
params['ticksAboveMid'] = new decimal_js_1.default(paramsBuffer.readInt32LE(8));
params['secondsPerTick'] = new decimal_js_1.default(paramsBuffer.readBigUInt64LE(12).toString());
params['direction'] = new decimal_js_1.default(paramsBuffer.readUint8(20));
return params;
}
function readRawDriftRebalanceStateFromStrategy(rebalanceRaw) {
const stateBuffer = Buffer.from(rebalanceRaw.state);
const state = {};
state['step'] = new decimal_js_1.default(stateBuffer.readUInt8(0));
state['lastDriftTimestamp'] = new decimal_js_1.default(stateBuffer.readBigUInt64LE(1).toString());
state['lastMidTick'] = new decimal_js_1.default(stateBuffer.readInt32LE(9));
return state;
}
function readDriftRebalanceStateFromStrategy(dex, tickSpacing, tokenADecimals, tokenBDecimals, rebalanceRaw) {
const stateBuffer = Buffer.from(rebalanceRaw.state);
const paramsBuffer = Buffer.from(rebalanceRaw.params);
const lastMidTick = new decimal_js_1.default(stateBuffer.readInt32LE(9));
const ticksBelowMid = new decimal_js_1.default(paramsBuffer.readInt32LE(4));
const ticksAboveMid = new decimal_js_1.default(paramsBuffer.readInt32LE(8));
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 deserializeDriftRebalanceFromOnchainParams(dex, tickSpacing, tokenADecimals, tokenBDecimals, rebalanceRaw) {
const params = readDriftRebalanceParamsFromStrategy(rebalanceRaw);
return getDriftRebalanceFieldInfos(dex, tickSpacing, tokenADecimals, tokenBDecimals, params['startMidTick'], params['ticksBelowMid'], params['ticksAboveMid'], params['secondsPerTick'], params['direction']);
}
function deserializeDriftRebalanceWithStateOverride(dex, tickSpacing, tokenADecimals, tokenBDecimals, rebalanceRaw) {
const stateFields = readDriftRebalanceStateFromStrategy(dex, tickSpacing, tokenADecimals, tokenBDecimals, rebalanceRaw);
const fields = deserializeDriftRebalanceFromOnchainParams(dex, tickSpacing, tokenADecimals, tokenBDecimals, rebalanceRaw);
return (0, utils_1.upsertManyRebalanceFieldInfos)(fields, stateFields);
}
//# sourceMappingURL=driftRebalance.js.map