UNPKG

@symmetry-hq/liquidity-sdk

Version:

Exchange functionality using symmetry funds liquidity

104 lines (96 loc) 4.12 kB
import { BN, Program } from "@coral-xyz/anchor"; import { AccountInfo, GetProgramAccountsResponse, PublicKey } from "@solana/web3.js"; import { FundsIDL } from "./fundsIDL"; import { CurveChainData, FundStateChainData, OraclePrice, TokenSettings } from "./types"; import { parsePriceData } from "@pythnetwork/client"; export function asciiToString( coingeckoIdAscii: number[], ): string { let coingeckoId: string = ""; for(let i=0; i<coingeckoIdAscii.length; i++) if(coingeckoIdAscii[i] != 0) coingeckoId += String.fromCharCode(coingeckoIdAscii[i]).toString(); return coingeckoId; } export function decodeTokenList( program: Program<FundsIDL>, tokenListAccountInfo: AccountInfo<Buffer>, ): TokenSettings[] { 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; } export function decodeCurveData( program: Program<FundsIDL>, curveDataAccountInfo: AccountInfo<Buffer>, ): CurveChainData { let state = program.coder.accounts.decode("prismData", curveDataAccountInfo.data); return state; } export function decodeFunds( program: Program<FundsIDL>, fundStateAccountInfos: GetProgramAccountsResponse, ): {pubkey: PublicKey, fund: FundStateChainData}[] { return fundStateAccountInfos.map(account => { return { pubkey: account.pubkey, fund: program.coder.accounts.decode("fundState", account.account.data) }}); } export function decodeOraclePrices( oracleDataAccountInfos: Array<AccountInfo<Buffer>>, tokenListData: TokenSettings[], ): OraclePrice[] { let oraclePrices = []; for(let i=0; i<oracleDataAccountInfos.length; i++){ let avgPrice = 0; let baseConfidence = 0; if(oracleDataAccountInfos[i] == null) {} else if (tokenListData[i].oracleType == "Pyth") { let parsed = parsePriceData(oracleDataAccountInfos[i].data).aggregate; avgPrice = parsed.price * 10 ** 12; baseConfidence = parsed.confidence * 10 ** 12 * tokenListData[i].fixedConfidenceBps / 100; } else { let price = parseInt(new BN( oracleDataAccountInfos[i].data.subarray( tokenListData[i].oracleIndex * 8 + 9, tokenListData[i].oracleIndex * 8 + 17 ), 10, "le" ).toString()); baseConfidence = price * tokenListData[i].oracleConfidencePct / 10000; avgPrice = price - baseConfidence; } let additionalConfidence = avgPrice * tokenListData[i].fixedConfidenceBps / 10000; oraclePrices.push({ sell_price: avgPrice - baseConfidence - additionalConfidence, avg_price: avgPrice, buy_price: avgPrice + baseConfidence + additionalConfidence, }) } return oraclePrices; }