UNPKG

@symmetry-hq/liquidity-sdk

Version:

Exchange functionality using symmetry funds liquidity

130 lines (129 loc) 5.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.mulDiv = exports.calculateOutputValueForSellingAsset = exports.calculateOutputAmountForBuyingAsset = exports.findTokenId = exports.decodeCurveData = exports.decodeTokenList = exports.asciiToString = exports.FundError = void 0; class FundError extends Error { constructor(message, txId = "") { super(message); this.txId = txId; } } exports.FundError = FundError; function asciiToString(coingeckoIdAscii) { let coingeckoId = ""; for (let i = 0; i < coingeckoIdAscii.length; i++) if (coingeckoIdAscii[i] != 0) coingeckoId += String.fromCharCode(coingeckoIdAscii[i]).toString(); return coingeckoId; } exports.asciiToString = asciiToString; function decodeTokenList(program, tokenListAccountInfo) { let state = program.coder.accounts.decode("tokenList", tokenListAccountInfo.data); let numTokens = state.numTokens.toNumber(); let tokens = []; for (let i = 0; i < numTokens; i++) { let tokenSettings = state.list[i]; tokens.push({ id: i, symbol: "", name: "", tokenMint: tokenSettings.tokenMint.toBase58(), decimals: tokenSettings.decimals, coingeckoId: asciiToString(tokenSettings.coingeckoId), pdaTokenAccount: tokenSettings.pdaTokenAccount.toBase58(), oracleType: tokenSettings.oracleType == 0 ? "Pyth" : "Switchboard", oracleAccount: tokenSettings.oracleAccount.toBase58(), oracleIndex: tokenSettings.oracleIndex, oracleConfidencePct: tokenSettings.oracleConfidencePct, fixedConfidenceBps: tokenSettings.fixedConfidenceBps, tokenSwapFeeBeforeTwBps: tokenSettings.tokenSwapFeeBeforeTwBps, tokenSwapFeeAfterTwBps: tokenSettings.tokenSwapFeeAfterTwBps, isLive: tokenSettings.isLive == 0 ? false : true, lpOn: tokenSettings.lpOn == 0 ? false : true, useCurveData: tokenSettings.useCurveData == 0 ? false : true, additionalData: tokenSettings.additionalData, }); } return tokens; } exports.decodeTokenList = decodeTokenList; function decodeCurveData(program, curveDataAccountInfo) { let state = program.coder.accounts.decode("prismData", curveDataAccountInfo.data); return state; } exports.decodeCurveData = decodeCurveData; function findTokenId(tokenListData, tokenMint) { for (let i = 0; i < tokenListData.length; i++) if (tokenListData[i].tokenMint == tokenMint.toBase58()) return tokenListData[i].id; return undefined; } exports.findTokenId = findTokenId; let NUM_OF_POINTS_IN_CURVE_DATA = 10; function calculateOutputAmountForBuyingAsset(currentAmount, targetAmount, pyth, amountValue, curveData, decimals) { let curveStartAmount = 0; if (currentAmount < targetAmount) curveStartAmount = targetAmount; else curveStartAmount = currentAmount; let amountValueLeft = amountValue; let currentOutputAmount = 0; let expo = 10 ** decimals; let pythPrice = pyth; let currentPrice = pythPrice; let amountFromTargetWeight = 0; for (let step = 0; step < NUM_OF_POINTS_IN_CURVE_DATA; step++) { let priceInInterval = Math.floor((curveData.price[step].toNumber() * 9 + pythPrice) / 10); if (priceInInterval > currentPrice) { currentPrice = priceInInterval; } amountFromTargetWeight += curveData.amount[step].toNumber(); if (amountFromTargetWeight <= curveStartAmount - currentAmount) continue; let amountInInterval = Math.min(amountFromTargetWeight - (curveStartAmount - currentAmount), curveData.amount[step].toNumber()); let valueInInterval = mulDiv(amountInInterval, currentPrice, expo); if (valueInInterval > amountValueLeft) { return mulDiv(amountValueLeft, expo, currentPrice) + currentOutputAmount; } currentOutputAmount += amountInInterval; amountValueLeft -= valueInInterval; } currentOutputAmount += mulDiv(amountValueLeft, expo, currentPrice); return currentOutputAmount; } exports.calculateOutputAmountForBuyingAsset = calculateOutputAmountForBuyingAsset; function calculateOutputValueForSellingAsset(currentAmount, targetAmount, pyth, amount, curveData, decimals) { let curveStartAmount = 0; if (currentAmount > targetAmount) curveStartAmount = targetAmount; else curveStartAmount = currentAmount; let currentOutputValue = 0; let amountLeft = amount; let expo = 10 ** decimals; let pythPrice = pyth; let currentPrice = pythPrice; let amountFromTargetWeight = 0; for (let step = 0; step < NUM_OF_POINTS_IN_CURVE_DATA; step++) { let priceInInterval = Math.floor((curveData.price[step].toNumber() * 9 + pythPrice) / 10); if (priceInInterval < currentPrice) { currentPrice = priceInInterval; } amountFromTargetWeight += curveData.amount[step].toNumber(); if (amountFromTargetWeight <= currentAmount - curveStartAmount) continue; let amountInInterval = Math.min(amountFromTargetWeight - (currentAmount - curveStartAmount), curveData.amount[step].toNumber()); let valueInInterval = mulDiv(amountInInterval, currentPrice, expo); if (amountInInterval > amountLeft) { return mulDiv(amountLeft, currentPrice, expo) + currentOutputValue; } currentOutputValue += valueInInterval; amountLeft -= amountInInterval; } currentOutputValue += mulDiv(amountLeft, currentPrice, expo); return currentOutputValue; } exports.calculateOutputValueForSellingAsset = calculateOutputValueForSellingAsset; function mulDiv(a, b, c) { return Math.floor(a * b / c); } exports.mulDiv = mulDiv;