@symmetry-hq/liquidity-sdk
Version:
Exchange functionality using symmetry funds liquidity
130 lines (129 loc) • 5.88 kB
JavaScript
"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;