UNPKG

@kamino-finance/kliquidity-sdk

Version:

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

160 lines 8.51 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSOLMint = exports.DECIMALS_SOL = exports.SOL_MINTS = exports.WSOL_MINT = exports.SOL_MINT = void 0; exports.getAssociatedTokenAddressAndAccount = getAssociatedTokenAddressAndAccount; exports.getAssociatedTokenAddress = getAssociatedTokenAddress; exports.createAssociatedTokenAccountInstruction = createAssociatedTokenAccountInstruction; exports.createComputeUnitLimitIx = createComputeUnitLimitIx; exports.getStrategyPriceRangeOrca = getStrategyPriceRangeOrca; exports.getStrategyPriceRangeRaydium = getStrategyPriceRangeRaydium; exports.getStrategyPriceRangeMeteora = getStrategyPriceRangeMeteora; exports.getMeteoraPriceLowerUpper = getMeteoraPriceLowerUpper; exports.getPriceLowerUpper = getPriceLowerUpper; exports.getTokenNameFromCollateralInfo = getTokenNameFromCollateralInfo; exports.getMintDecimals = getMintDecimals; exports.solToWSol = solToWSol; exports.getTokenAccountBalance = getTokenAccountBalance; exports.getTokenAccountBalanceLamports = getTokenAccountBalanceLamports; const kit_1 = require("@solana/kit"); const decimal_js_1 = __importDefault(require("decimal.js")); const meteora_1 = require("./meteora"); const token_1 = require("@solana-program/token"); const token_2022_1 = require("@solana-program/token-2022"); const system_1 = require("@solana-program/system"); const compute_budget_1 = require("@solana-program/compute-budget"); const whirlpools_core_1 = require("@orca-so/whirlpools-core"); exports.SOL_MINT = (0, kit_1.address)('So11111111111111111111111111111111111111111'); exports.WSOL_MINT = (0, kit_1.address)('So11111111111111111111111111111111111111112'); exports.SOL_MINTS = [exports.SOL_MINT, exports.WSOL_MINT]; exports.DECIMALS_SOL = 9; async function getAssociatedTokenAddressAndAccount(connection, mint, owner, programId = token_1.TOKEN_PROGRAM_ADDRESS) { const ata = await getAssociatedTokenAddress(mint, owner, programId); const account = await (0, token_2022_1.fetchMaybeToken)(connection, ata); return [ata, account.exists ? account : null]; } async function getAssociatedTokenAddress(mint, owner, programId = token_1.TOKEN_PROGRAM_ADDRESS, associatedTokenProgramId = token_2022_1.ASSOCIATED_TOKEN_PROGRAM_ADDRESS) { const [ata] = await (0, token_2022_1.findAssociatedTokenPda)({ mint, owner, tokenProgram: programId, }, { programAddress: associatedTokenProgramId }); return ata; } function createAssociatedTokenAccountInstruction(payer, associatedTokenAddress, owner, mint, programId = token_1.TOKEN_PROGRAM_ADDRESS, associatedTokenProgramId = token_2022_1.ASSOCIATED_TOKEN_PROGRAM_ADDRESS) { return (0, token_2022_1.getCreateAssociatedTokenInstruction)({ mint, owner, ata: associatedTokenAddress, payer: payer, tokenProgram: programId, systemProgram: system_1.SYSTEM_PROGRAM_ADDRESS, }, { programAddress: associatedTokenProgramId }); } function createComputeUnitLimitIx(units = 400000) { return (0, compute_budget_1.getSetComputeUnitLimitInstruction)({ units }); } function getStrategyPriceRangeOrca(tickLowerIndex, tickUpperIndex, strategy, poolPrice) { const { priceLower, priceUpper } = getPriceLowerUpper(tickLowerIndex, tickUpperIndex, Number(strategy.tokenAMintDecimals.toString()), Number(strategy.tokenBMintDecimals.toString())); const strategyOutOfRange = poolPrice.lt(priceLower) || poolPrice.gt(priceUpper); return { priceLower, poolPrice, priceUpper, strategyOutOfRange }; } function getStrategyPriceRangeRaydium(tickLowerIndex, tickUpperIndex, tickCurrent, tokenADecimals, tokenBDecimals) { const { priceLower, priceUpper } = getPriceLowerUpper(tickLowerIndex, tickUpperIndex, tokenADecimals, tokenBDecimals); const poolPrice = new decimal_js_1.default((0, whirlpools_core_1.tickIndexToPrice)(tickCurrent, tokenADecimals, tokenBDecimals)); const strategyOutOfRange = poolPrice.lt(priceLower) || poolPrice.gt(priceUpper); return { priceLower: new decimal_js_1.default(priceLower), poolPrice, priceUpper: new decimal_js_1.default(priceUpper), strategyOutOfRange }; } function getStrategyPriceRangeMeteora(priceLower, priceUpper, activeBinId, binStep, decimalsA, decimalsB) { const poolPrice = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(activeBinId, binStep, decimalsA, decimalsB); const strategyOutOfRange = poolPrice.lt(priceLower) || poolPrice.gt(priceUpper); return { priceLower, poolPrice, priceUpper, strategyOutOfRange }; } function getMeteoraPriceLowerUpper(tickLowerIndex, tickUpperIndex, tokenAMintDecimals, tokenBMintDecimals, binStep) { const priceLower = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(tickLowerIndex, binStep, tokenAMintDecimals, tokenBMintDecimals); const priceUpper = (0, meteora_1.getPriceOfBinByBinIdWithDecimals)(tickUpperIndex, binStep, tokenAMintDecimals, tokenBMintDecimals); return { priceLower, priceUpper }; } function getPriceLowerUpper(tickLowerIndex, tickUpperIndex, tokenAMintDecimals, tokenBMintDecimals) { const priceLower = (0, whirlpools_core_1.tickIndexToPrice)(tickLowerIndex, Number(tokenAMintDecimals.toString()), Number(tokenBMintDecimals.toString())); const priceUpper = (0, whirlpools_core_1.tickIndexToPrice)(tickUpperIndex, Number(tokenAMintDecimals.toString()), Number(tokenBMintDecimals.toString())); return { priceLower, priceUpper }; } // Collateral names come back as Uint8Array on-chain, but can degrade into plain arrays // or keyed objects after JSON serialization through caches or APIs. function normalizeFixedBytes(value) { if (value == null) { return []; } if (typeof value === 'string') { return Array.from(value, (char) => char.charCodeAt(0)); } if (value instanceof Uint8Array) { return Array.from(value); } if (value instanceof ArrayBuffer) { return Array.from(new Uint8Array(value)); } if (ArrayBuffer.isView(value)) { return Array.from(new Uint8Array(value.buffer, value.byteOffset, value.byteLength)); } if (Array.isArray(value)) { return value.map((item) => Number(item)).filter((item) => Number.isFinite(item)); } if (typeof value === 'object') { const record = value; if (Array.isArray(record.data)) { return record.data.map((item) => Number(item)).filter((item) => Number.isFinite(item)); } return Object.entries(record) .filter(([key]) => /^\d+$/.test(key)) .sort((a, b) => Number(a[0]) - Number(b[0])) .map(([, item]) => Number(item)) .filter((item) => Number.isFinite(item)); } return []; } // Decode the fixed-width on-chain token name and stay resilient to JSON-round-tripped byte shapes. function getTokenNameFromCollateralInfo(collateralInfo) { const name = typeof collateralInfo.name === 'string' ? collateralInfo.name : String.fromCharCode(...normalizeFixedBytes(collateralInfo.name)); return name.replace(/\0/g, ''); } const isSOLMint = (mint) => { return exports.SOL_MINTS.filter((m) => m === mint).length > 0; }; exports.isSOLMint = isSOLMint; async function getMintDecimals(rpc, mint) { if ((0, exports.isSOLMint)(mint)) { return exports.DECIMALS_SOL; } const acc = await (0, token_2022_1.fetchMaybeMint)(rpc, mint); if (!acc.exists) { throw new Error(`Mint ${mint} not found`); } return acc.data.decimals; } function solToWSol(mint) { if (mint === exports.SOL_MINT) { return exports.WSOL_MINT; } return mint; } async function getTokenAccountBalance(rpc, tokenAccount) { const tokenAccountBalance = await rpc.getTokenAccountBalance(tokenAccount).send(); if (!tokenAccountBalance.value) { throw new Error(`Could not get token account balance for ${tokenAccount.toString()}.`); } return new decimal_js_1.default(tokenAccountBalance.value.uiAmountString); } async function getTokenAccountBalanceLamports(rpc, tokenAccount) { const tokenAccountBalance = await rpc.getTokenAccountBalance(tokenAccount).send(); if (!tokenAccountBalance.value) { throw new Error(`Could not get token account balance for ${tokenAccount.toString()}.`); } return Number(tokenAccountBalance.value.amount); } //# sourceMappingURL=tokenUtils.js.map