@parifi/synthetix-sdk-ts
Version:
A Typescript SDK for interactions with the Synthetix protocol
1 lines • 9.77 kB
Source Map (JSON)
{"version":3,"sources":["../../src/utils/market.ts","../../src/constants/common.ts"],"sourcesContent":["import { encodeAbiParameters, Hex, parseUnits } from 'viem';\nimport { SynthetixSdk } from '..';\nimport { CUSTOM_DECIMALS, DISABLED_MARKETS } from '../constants';\nimport { MarketIdOrName } from '../interface/commonTypes';\nimport { MarketData, SpotMarketData } from '../perps/interface';\nimport { Call3Value } from '../interface/contractTypes';\n\nexport abstract class Market<T extends MarketData | SpotMarketData> {\n sdk: SynthetixSdk;\n marketsById: Map<number, T>;\n marketsByName: Map<string, T>;\n\n // Mapping of Market Symbol to T.\n // @note Ideally prefer using market symbol over market name\n marketsBySymbol: Map<string, T>;\n disabledMarkets: number[] = [];\n\n constructor(synthetixSdk: SynthetixSdk) {\n this.sdk = synthetixSdk;\n // Initialize empty market data\n this.marketsById = new Map<number, T>();\n this.marketsByName = new Map<string, T>();\n this.marketsBySymbol = new Map<string, T>();\n\n // Set disabled markets\n if (synthetixSdk.rpcConfig.chainId in DISABLED_MARKETS) {\n this.disabledMarkets = DISABLED_MARKETS[synthetixSdk.rpcConfig.chainId];\n }\n }\n /**\n * Look up the market_id and market_name for a market. If only one is provided,\n * the other is resolved. If both are provided, they are checked for consistency.\n * @param marketIdOrName Id or name of the market to resolve\n */\n public async resolveMarket(\n marketIdOrName: MarketIdOrName,\n ): Promise<{ resolvedMarketId: number; resolvedMarketName: string }> {\n // Do not resolve markets if flag is not set or if market name is passed as\n // an argument\n if (!this.sdk.resolveMarketNames && typeof marketIdOrName === 'number') {\n console.log('Resolve markets set to false. Returning market id without validating...');\n return { resolvedMarketName: 'Unresolved Market', resolvedMarketId: Number(marketIdOrName) };\n }\n\n const market = await this.getMarket(marketIdOrName);\n if (!market?.marketName || market?.marketId === undefined)\n throw new Error(`Market not found for ${marketIdOrName}`);\n\n return { resolvedMarketName: market.marketName, resolvedMarketId: market.marketId };\n }\n\n /**\n * Format the size of a synth for an order. This is used for synths whose base asset\n * does not use 18 decimals. For example, USDC uses 6 decimals, so we need to handle size\n * differently from other assets.\n * @param size The size as an ether value (e.g. 100).\n * @param marketId The id of the market.\n * @returns The formatted size in wei. (e.g. 100 = 100000000000000000000)\n */\n public async formatSize(size: number, marketId: MarketIdOrName) {\n // TODO: think in a better solution maybe get the collateral and query the decimals from the contract\n\n return parseUnits(size.toString(), CUSTOM_DECIMALS[this.sdk.rpcConfig.chainId][marketId] || 18);\n }\n\n async prepareOracleCallsWithPriceId(priceFeedIds: string[]): Promise<Call3Value[]> {\n if (!priceFeedIds.length) {\n return [];\n }\n const stalenessTolerance = 30n; // 30 seconds\n const updateData = await this.sdk.pyth.getPriceFeedsUpdateData(priceFeedIds as Hex[]);\n\n const signedRequiredData = encodeAbiParameters(\n [\n { type: 'uint8', name: 'updateType' },\n { type: 'uint64', name: 'stalenessTolerance' },\n { type: 'bytes32[]', name: 'priceIds' },\n { type: 'bytes[]', name: 'updateData' },\n ],\n [1, stalenessTolerance, priceFeedIds as Hex[], updateData],\n );\n\n const pythWrapper = await this.sdk.contracts.getPythErc7412WrapperInstance();\n const dataVerificationTx = this.sdk.utils.generateDataVerificationTx(pythWrapper.address, signedRequiredData);\n\n // set `requireSuccess` to false in this case, since sometimes\n // the wrapper will return an error if the price has already been updated\n\n // @note A better approach would be to fetch the priceUpdateFee for tx dynamically\n // from the Pyth contract instead of using arbitrary values for pyth price update fees\n return [{ ...dataVerificationTx, value: 0n, requireSuccess: false }];\n }\n\n /**\n * Prepare a call to the external node with oracle updates for the specified market names.\n * The result can be passed as the first argument to a multicall function to improve performance\n * of ERC-7412 calls. If no market names are provided, all markets are fetched. This is useful for\n * read functions since the user does not pay gas for those oracle calls, and reduces RPC calls and\n * runtime.\n * @param {number[]} marketIds An array of market ids to fetch prices for. If not provided, all markets are fetched\n * @returns {Promise<Call3Value[]>} objects representing the target contract, call data, value, requireSuccess flag and other necessary details for executing the function in the blockchain.\n */\n public async prepareOracleCall(marketIds: number[] = []): Promise<Call3Value[]> {\n let priceFeedIds: string[] = [];\n\n if (marketIds.length != 0) {\n const marketSymbols: string[] = [];\n marketIds.forEach((marketId) => {\n const marketSymbol = this.marketsById.get(marketId)?.symbol;\n if (!marketSymbol) return;\n marketSymbols.push(marketSymbol);\n });\n\n marketSymbols.forEach((marketSymbol) => {\n const feedId = this.sdk.pyth.priceFeedIds.get(marketSymbol);\n if (!feedId) return;\n priceFeedIds.push(feedId);\n });\n } else {\n priceFeedIds = Array.from(this.sdk.pyth.priceFeedIds.values());\n }\n\n return this.prepareOracleCallsWithPriceId(priceFeedIds);\n }\n\n public async getMarket(marketIdOrName: MarketIdOrName): Promise<T> {\n throw new Error('Method not implemented. ' + marketIdOrName);\n }\n}\n","import { Hex, zeroAddress } from 'viem';\nimport { MarketIdOrName } from '../interface/commonTypes';\nimport { SUPPORTED_CHAINS } from './chains';\n\nexport const ZERO_ADDRESS: Hex = zeroAddress;\n\nexport const SIG_ORACLE_DATA_REQUIRED = '0xcf2cabdf';\nexport const SIG_FEE_REQUIRED = '0x0e7186fb';\nexport const SIG_ERRORS = '0x0b42fd17';\n\n// for markets metadata it is requesting too much oracle updates\nexport const MAX_ERC7412_RETRIES = 80; // Limit the max failures to prevent infinite loops\n\n// List of market ids disabled by chainId\nexport const DISABLED_MARKETS: { [key: number]: number[] } = {\n 84532: [3, 6300],\n 8453: [6300],\n};\n\nexport const publicRpcEndpoints: { [key: number]: string } = {\n 8453: 'https://base.llamarpc.com',\n 84532: 'https://sepolia.base.org',\n 42161: 'https://arbitrum.llamarpc.com',\n 421614: 'https://sepolia-rollup.arbitrum.io/rpc',\n};\n\n// Logger constants\nexport type LOGGER_MESSAGE_TYPE = 'json' | 'pretty' | 'hidden';\n\n// 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error, 6: fatal\nexport const DEFAULT_LOGGER_LEVEL = 4; // https://tslog.js.org/#/?id=highlights to see more levels\nexport const CUSTOM_DECIMALS: Record<number, Record<MarketIdOrName, number>> = {\n [SUPPORTED_CHAINS.ARBITUM_SEPOLIA]: {\n 2: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.ARBITRUM]: {\n 2: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.BASE_SEPOLIA]: {\n 1: 6,\n USDC: 6,\n },\n [SUPPORTED_CHAINS.BASE]: {\n 1: 6,\n USDC: 6,\n },\n};\n"],"mappings":";AAAA,SAAS,qBAA0B,kBAAkB;;;ACArD,SAAc,mBAAmB;AAc1B,IAAM,mBAAgD;AAAA,EAC3D,OAAO,CAAC,GAAG,IAAI;AAAA,EACf,MAAM,CAAC,IAAI;AACb;AAcO,IAAM,kBAAkE;AAAA,EAC7E,6BAAiC,GAAG;AAAA,IAClC,GAAG;AAAA,IACH,MAAM;AAAA,EACR;AAAA,EACA,qBAA0B,GAAG;AAAA,IAC3B,GAAG;AAAA,IACH,MAAM;AAAA,EACR;AAAA,EACA,yBAA8B,GAAG;AAAA,IAC/B,GAAG;AAAA,IACH,MAAM;AAAA,EACR;AAAA,EACA,gBAAsB,GAAG;AAAA,IACvB,GAAG;AAAA,IACH,MAAM;AAAA,EACR;AACF;;;ADzCO,IAAe,SAAf,MAA6D;AAAA,EAUlE,YAAY,cAA4B;AAFxC,2BAA4B,CAAC;AAG3B,SAAK,MAAM;AAEX,SAAK,cAAc,oBAAI,IAAe;AACtC,SAAK,gBAAgB,oBAAI,IAAe;AACxC,SAAK,kBAAkB,oBAAI,IAAe;AAG1C,QAAI,aAAa,UAAU,WAAW,kBAAkB;AACtD,WAAK,kBAAkB,iBAAiB,aAAa,UAAU,OAAO;AAAA,IACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,cACX,gBACmE;AAGnE,QAAI,CAAC,KAAK,IAAI,sBAAsB,OAAO,mBAAmB,UAAU;AACtE,cAAQ,IAAI,yEAAyE;AACrF,aAAO,EAAE,oBAAoB,qBAAqB,kBAAkB,OAAO,cAAc,EAAE;AAAA,IAC7F;AAEA,UAAM,SAAS,MAAM,KAAK,UAAU,cAAc;AAClD,QAAI,CAAC,QAAQ,cAAc,QAAQ,aAAa;AAC9C,YAAM,IAAI,MAAM,wBAAwB,cAAc,EAAE;AAE1D,WAAO,EAAE,oBAAoB,OAAO,YAAY,kBAAkB,OAAO,SAAS;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,WAAW,MAAc,UAA0B;AAG9D,WAAO,WAAW,KAAK,SAAS,GAAG,gBAAgB,KAAK,IAAI,UAAU,OAAO,EAAE,QAAQ,KAAK,EAAE;AAAA,EAChG;AAAA,EAEA,MAAM,8BAA8B,cAA+C;AACjF,QAAI,CAAC,aAAa,QAAQ;AACxB,aAAO,CAAC;AAAA,IACV;AACA,UAAM,qBAAqB;AAC3B,UAAM,aAAa,MAAM,KAAK,IAAI,KAAK,wBAAwB,YAAqB;AAEpF,UAAM,qBAAqB;AAAA,MACzB;AAAA,QACE,EAAE,MAAM,SAAS,MAAM,aAAa;AAAA,QACpC,EAAE,MAAM,UAAU,MAAM,qBAAqB;AAAA,QAC7C,EAAE,MAAM,aAAa,MAAM,WAAW;AAAA,QACtC,EAAE,MAAM,WAAW,MAAM,aAAa;AAAA,MACxC;AAAA,MACA,CAAC,GAAG,oBAAoB,cAAuB,UAAU;AAAA,IAC3D;AAEA,UAAM,cAAc,MAAM,KAAK,IAAI,UAAU,8BAA8B;AAC3E,UAAM,qBAAqB,KAAK,IAAI,MAAM,2BAA2B,YAAY,SAAS,kBAAkB;AAO5G,WAAO,CAAC,EAAE,GAAG,oBAAoB,OAAO,IAAI,gBAAgB,MAAM,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,kBAAkB,YAAsB,CAAC,GAA0B;AAC9E,QAAI,eAAyB,CAAC;AAE9B,QAAI,UAAU,UAAU,GAAG;AACzB,YAAM,gBAA0B,CAAC;AACjC,gBAAU,QAAQ,CAAC,aAAa;AAC9B,cAAM,eAAe,KAAK,YAAY,IAAI,QAAQ,GAAG;AACrD,YAAI,CAAC,aAAc;AACnB,sBAAc,KAAK,YAAY;AAAA,MACjC,CAAC;AAED,oBAAc,QAAQ,CAAC,iBAAiB;AACtC,cAAM,SAAS,KAAK,IAAI,KAAK,aAAa,IAAI,YAAY;AAC1D,YAAI,CAAC,OAAQ;AACb,qBAAa,KAAK,MAAM;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AACL,qBAAe,MAAM,KAAK,KAAK,IAAI,KAAK,aAAa,OAAO,CAAC;AAAA,IAC/D;AAEA,WAAO,KAAK,8BAA8B,YAAY;AAAA,EACxD;AAAA,EAEA,MAAa,UAAU,gBAA4C;AACjE,UAAM,IAAI,MAAM,6BAA6B,cAAc;AAAA,EAC7D;AACF;","names":[]}