import { parsePriceData } from "@pythnetwork/client"; import { utils } from "@coral-xyz/anchor"; import { Connection, PublicKey } from "@solana/web3.js"; import { BONK_DEV_MINT_PK, BONK_MINT_PK, BTC_DEV_MINT_PK, DUAL_MINT_PK, ETH_DEV_MINT_PK, JITOSOL_MINT_PK, MNGO_MINT_PK, MSOL_MINT_PK, NO_ORACLE_PRICE, NUM_SPL_ATOMS_PER_TOKEN, PYTH_TO_MINT, RAY_DEV_MINT_PK, RAY_MINT_PK, USDC_ATOMS_PER_TOKEN, USDC_DEV_MINT_PK, USDC_MINT_PK, TBTC_MINT_PK, WETH_PORTAL_MINT_PK, WSOL_PK, } from "./constants"; export async function fetchPythPrices( connection: Connection, pythPriceAddresses: PublicKey[] ): Promise<{ [pk: string]: number }> { try { const priceInfos = await utils.rpc.getMultipleAccounts( connection, pythPriceAddresses, "confirmed" ); const prices = priceInfos.reduce((acc, info, i) => { const price = info ? parsePriceData(info.account.data).price : undefined; const result = price ? roundToFixed(price) : NO_ORACLE_PRICE; return { ...acc, [PYTH_TO_MINT[pythPriceAddresses[i].toBase58()]]: result, }; }, {}); return prices; } catch (error) { // Silently fail and return no prices. return pythPriceAddresses.reduce((acc, token) => { return { ...acc, [PYTH_TO_MINT[token.toBase58()]]: NO_ORACLE_PRICE }; }, {}); } } const roundToFixed = (value: number, digits = 2) => { return Math.round(value * 10 ** digits) / 10 ** digits; }; /** * Convert a 64 bit number to two big endian bytes. That is the format used in * seeds for DIP program accounts. */ export function toBeBytes(x: number): Uint8Array { const y = Math.floor(x / 2 ** 32); return Uint8Array.from( [y, y << 8, y << 16, y << 24, x, x << 8, x << 16, x << 24].map( (z) => z >>> 24 ) ); } export function mintToTokenName(mint: PublicKey) { const pkToAsset = { [TBTC_MINT_PK.toBase58()]: "BTC", [BTC_DEV_MINT_PK.toBase58()]: "BTC", [WETH_PORTAL_MINT_PK.toBase58()]: "ETH", [ETH_DEV_MINT_PK.toBase58()]: "ETH", [WSOL_PK.toBase58()]: "SOL", [USDC_MINT_PK.toBase58()]: "USDC", [USDC_DEV_MINT_PK.toBase58()]: "USDC", [MNGO_MINT_PK.toBase58()]: "MNGO", [BONK_MINT_PK.toBase58()]: "BONK", [BONK_DEV_MINT_PK.toBase58()]: "BONK", [RAY_MINT_PK.toBase58()]: "RAY", [RAY_DEV_MINT_PK.toBase58()]: "RAY", [DUAL_MINT_PK.toBase58()]: "DUAL", [MSOL_MINT_PK.toBase58()]: "MSOL", [JITOSOL_MINT_PK.toBase58()]: "JITOSOL", LSO: "LSO", }; return pkToAsset[mint.toBase58()]; } export const calculateStrikeAtomsPerBaseToken = (data: { isUpside: boolean; baseMint: PublicKey; strike: number; }) => { return data.isUpside ? data.strike * USDC_ATOMS_PER_TOKEN : Number( ( (1 / data.strike) * NUM_SPL_ATOMS_PER_TOKEN[data.baseMint.toBase58()] ).toPrecision(6) ); };