UNPKG

@kamino-finance/kliquidity-sdk

Version:

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

123 lines 5.16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTokensPrices = void 0; const decimal_js_1 = __importDefault(require("decimal.js")); const BATCH_TOKEN_PRICES_LIMIT = 100; const BATCH_TOKEN_PRICES_MAX_URL_LENGTH = 2000; const BATCH_TOKEN_PRICES_PATH = 'batch-token-prices'; const BATCH_TOKEN_PRICES_QUERY_KEY = 'tokens'; const getBatchTokenPricesBaseUrl = (apiBaseUrl) => `${apiBaseUrl.replace(/\/+$/, '')}/${BATCH_TOKEN_PRICES_PATH}`; const getBatchTokenPricesUrl = (apiBaseUrl, tokens) => { const tokensParams = new URLSearchParams(); for (const token of tokens) { tokensParams.append(BATCH_TOKEN_PRICES_QUERY_KEY, token); } return `${getBatchTokenPricesBaseUrl(apiBaseUrl)}?${tokensParams.toString()}`; }; const getTokenQueryParamLength = (token) => { const tokenParam = new URLSearchParams(); tokenParam.append(BATCH_TOKEN_PRICES_QUERY_KEY, token); return tokenParam.toString().length; }; const getTokensPriceBatches = (apiBaseUrl, tokens) => { const baseUrlLength = `${getBatchTokenPricesBaseUrl(apiBaseUrl)}?`.length; const batches = []; let batch = []; let batchUrlLength = baseUrlLength; for (const token of tokens) { const tokenParamLength = getTokenQueryParamLength(token); const separatorLength = batch.length === 0 ? 0 : 1; const nextBatchUrlLength = batchUrlLength + separatorLength + tokenParamLength; if (batch.length < BATCH_TOKEN_PRICES_LIMIT && nextBatchUrlLength <= BATCH_TOKEN_PRICES_MAX_URL_LENGTH) { batch.push(token); batchUrlLength = nextBatchUrlLength; continue; } if (batch.length > 0) { batches.push(batch); } const singleTokenUrl = getBatchTokenPricesUrl(apiBaseUrl, [token]); if (singleTokenUrl.length > BATCH_TOKEN_PRICES_MAX_URL_LENGTH) { throw new Error(`KSwap token price URL length ${singleTokenUrl.length} exceeds limit ${BATCH_TOKEN_PRICES_MAX_URL_LENGTH} for a single token: ${singleTokenUrl}`); } batch = [token]; batchUrlLength = baseUrlLength + tokenParamLength; } if (batch.length > 0) { batches.push(batch); } return batches; }; const getResponseBodyForLog = async (response) => { try { return await response.text(); } catch (error) { return `Failed to read response body: ${error instanceof Error ? error.message : String(error)}`; } }; const getTokensPrices = async (apiBaseUrl, tokens, logger = console) => { if (tokens.length === 0) { return new Map(); } const batches = getTokensPriceBatches(apiBaseUrl, tokens); const results = await Promise.all(batches.map(async (batch) => { const url = getBatchTokenPricesUrl(apiBaseUrl, batch); let response; try { response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', }, }); } catch (error) { logger.error(`Failed to fetch tokens batch price. URL: ${url}.`, error); return { batch, data: null }; } const responseBody = await getResponseBodyForLog(response); if (!response.ok) { logger.error(`Failed to fetch tokens batch price: ${response.status} ${response.statusText}. URL: ${url}. Response body: ${responseBody}`); return { batch, data: null }; } try { const data = JSON.parse(responseBody); if (data.success === false || !data.data) { logger.error(`Unexpected tokens batch price response. URL: ${url}. Response body: ${responseBody}`); return { batch, data: null }; } return { batch, data }; } catch (error) { logger.error(`Failed to parse tokens batch price response. URL: ${url}. Response body: ${responseBody}`, error); return { batch, data: null }; } })); const prices = new Map(); for (const { batch, data } of results) { for (const token of batch) { const tokenData = data?.data[token]; if (tokenData && tokenData.value !== null && tokenData.value !== undefined) { try { const price = new decimal_js_1.default(tokenData.value); prices.set(token, price); } catch (error) { logger.error(`Failed to parse price for token, setting to 0: ${token}:`, error); prices.set(token, new decimal_js_1.default(0)); } } else { logger.warn(`No price data available for token ${token}, setting to 0`); prices.set(token, new decimal_js_1.default(0)); } } } return prices; }; exports.getTokensPrices = getTokensPrices; //# sourceMappingURL=kSwap.js.map