@metamask-previews/perps-controller 8.2.0-preview-9de9aa4 → 8.2.0-preview-153490ebd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -21
- package/dist/PerpsController.cjs +9 -38
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +9 -38
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/constants/eventNames.cjs +0 -10
- package/dist/constants/eventNames.cjs.map +1 -1
- package/dist/constants/eventNames.d.cts +0 -10
- package/dist/constants/eventNames.d.cts.map +1 -1
- package/dist/constants/eventNames.d.mts +0 -10
- package/dist/constants/eventNames.d.mts.map +1 -1
- package/dist/constants/eventNames.mjs +0 -10
- package/dist/constants/eventNames.mjs.map +1 -1
- package/dist/constants/perpsConfig.cjs +1 -10
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +0 -9
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +0 -9
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +0 -9
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/services/MarketDataService.cjs +7 -100
- package/dist/services/MarketDataService.cjs.map +1 -1
- package/dist/services/MarketDataService.d.cts +1 -10
- package/dist/services/MarketDataService.d.cts.map +1 -1
- package/dist/services/MarketDataService.d.mts +1 -10
- package/dist/services/MarketDataService.d.mts.map +1 -1
- package/dist/services/MarketDataService.mjs +7 -100
- package/dist/services/MarketDataService.mjs.map +1 -1
- package/dist/services/TradingService.cjs +0 -4
- package/dist/services/TradingService.cjs.map +1 -1
- package/dist/services/TradingService.d.cts.map +1 -1
- package/dist/services/TradingService.d.mts.map +1 -1
- package/dist/services/TradingService.mjs +0 -4
- package/dist/services/TradingService.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +0 -59
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +0 -59
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/utils/marketDataTransform.cjs +8 -3
- package/dist/utils/marketDataTransform.cjs.map +1 -1
- package/dist/utils/marketDataTransform.d.cts.map +1 -1
- package/dist/utils/marketDataTransform.d.mts.map +1 -1
- package/dist/utils/marketDataTransform.mjs +8 -3
- package/dist/utils/marketDataTransform.mjs.map +1 -1
- package/dist/utils/marketSearch.cjs +2 -28
- package/dist/utils/marketSearch.cjs.map +1 -1
- package/dist/utils/marketSearch.d.cts +3 -4
- package/dist/utils/marketSearch.d.cts.map +1 -1
- package/dist/utils/marketSearch.d.mts +3 -4
- package/dist/utils/marketSearch.d.mts.map +1 -1
- package/dist/utils/marketSearch.mjs +2 -28
- package/dist/utils/marketSearch.mjs.map +1 -1
- package/package.json +4 -5
- package/dist/services/TerminalMarketService.cjs +0 -185
- package/dist/services/TerminalMarketService.cjs.map +0 -1
- package/dist/services/TerminalMarketService.d.cts +0 -36
- package/dist/services/TerminalMarketService.d.cts.map +0 -1
- package/dist/services/TerminalMarketService.d.mts +0 -36
- package/dist/services/TerminalMarketService.d.mts.map +0 -1
- package/dist/services/TerminalMarketService.mjs +0 -181
- package/dist/services/TerminalMarketService.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketDataTransform.mjs","sourceRoot":"","sources":["../../src/utils/marketDataTransform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Market data transformation utilities.\n *\n * Portable: no mobile-specific imports.\n * Formatters are injected via MarketDataFormatters interface.\n */\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n HYPERLIQUID_CONFIG,\n getHyperLiquidAssetName,\n} from '../constants/hyperLiquidConfig';\nimport { PERPS_CONSTANTS } from '../constants/perpsConfig';\nimport type {\n PerpsMarketData,\n MarketType,\n MarketDataFormatters,\n} from '../types';\nimport type {\n AllMidsResponse,\n PerpsUniverse,\n PerpsAssetCtx,\n PredictedFunding,\n} from '../types/hyperliquid-types';\nimport { parseAssetName } from './hyperLiquidAdapter';\n\n/**\n * Calculate open interest in USD\n * Open interest from HyperLiquid is in contracts/units, not USD\n * To get USD value, multiply by current price\n *\n * @param openInterest - Raw open interest value in contracts/units\n * @param currentPrice - Current price of the asset\n * @returns Open interest in USD, or NaN if invalid\n */\nexport function calculateOpenInterestUSD(\n openInterest: string | number | undefined,\n currentPrice: string | number | undefined,\n): number {\n if (openInterest === undefined || currentPrice === undefined) {\n return NaN;\n }\n\n const openInterestNum =\n typeof openInterest === 'string' ? parseFloat(openInterest) : openInterest;\n const priceNum =\n typeof currentPrice === 'string' ? parseFloat(currentPrice) : currentPrice;\n\n if (isNaN(openInterestNum) || isNaN(priceNum)) {\n return NaN;\n }\n\n return openInterestNum * priceNum;\n}\n\n/**\n * HyperLiquid-specific market data structure\n */\nexport type HyperLiquidMarketData = {\n universe: PerpsUniverse[];\n assetCtxs: PerpsAssetCtx[];\n allMids: AllMidsResponse;\n predictedFundings?: PredictedFunding[];\n};\n\n/**\n * Parameters for calculating 24h percentage change\n */\ntype CalculateChange24hPercentParams = {\n hasCurrentPrice: boolean;\n currentPrice: number;\n prevDayPrice: number;\n};\n\n/**\n * Calculate 24h percentage change\n * Shows -100% when current price is missing but previous price exists\n *\n * @param params - The parameters for calculating the 24h change.\n * @returns The 24h percentage change value.\n */\nfunction calculateChange24hPercent(\n params: CalculateChange24hPercentParams,\n): number {\n const { hasCurrentPrice, currentPrice, prevDayPrice } = params;\n\n if (!hasCurrentPrice) {\n return prevDayPrice > 0 ? -100 : 0;\n }\n\n if (prevDayPrice <= 0) {\n return 0;\n }\n\n return ((currentPrice - prevDayPrice) / prevDayPrice) * 100;\n}\n\n/**\n * Funding data extracted from predicted fundings\n */\ntype FundingData = {\n nextFundingTime?: number;\n fundingIntervalHours?: number;\n predictedFundingRate?: number;\n};\n\n/**\n * Parameters for extracting funding data\n */\ntype ExtractFundingDataParams = {\n predictedFundings?: PredictedFunding[];\n symbol: string;\n exchangeName?: string;\n};\n\n/**\n * Extract funding data for a symbol from predicted fundings.\n * Looks for specified exchange first, falls back to first available.\n *\n * @param params - Parameters for extracting funding data\n * @param params.predictedFundings - Array of predicted funding data\n * @param params.symbol - Asset symbol to extract funding for\n * @param params.exchangeName - Exchange to prioritize (defaults to HyperLiquid's 'HlPerp')\n * @returns Funding data including next funding time, interval, and predicted rate\n */\nfunction extractFundingData(params: ExtractFundingDataParams): FundingData {\n const {\n predictedFundings,\n symbol,\n exchangeName = HYPERLIQUID_CONFIG.ExchangeName,\n } = params;\n\n const result: FundingData = {};\n\n if (!predictedFundings) {\n return result;\n }\n\n const fundingData = predictedFundings.find(\n ([assetSymbol]) => assetSymbol === symbol,\n );\n\n if (\n !fundingData?.[1] ||\n !Array.isArray(fundingData[1]) ||\n fundingData[1].length === 0\n ) {\n return result;\n }\n\n // Look for specified exchange (e.g., 'HlPerp' for HyperLiquid)\n const targetExchange = fundingData[1].find(\n (exchange: unknown) =>\n Array.isArray(exchange) && exchange[0] === exchangeName,\n );\n\n if (targetExchange?.[1]) {\n result.nextFundingTime = targetExchange[1].nextFundingTime;\n result.fundingIntervalHours = targetExchange[1].fundingIntervalHours;\n result.predictedFundingRate = parseFloat(targetExchange[1].fundingRate);\n return result;\n }\n\n // Fallback to first exchange if target not found\n const firstExchange = fundingData[1][0];\n if (Array.isArray(firstExchange) && firstExchange[1]) {\n result.nextFundingTime = firstExchange[1].nextFundingTime;\n result.fundingIntervalHours = firstExchange[1].fundingIntervalHours;\n }\n\n return result;\n}\n\n/**\n * Transform raw HyperLiquid market data to UI-friendly format\n *\n * @param hyperLiquidData - Raw data from HyperLiquid API\n * @param formatters - Injectable formatters for platform-agnostic formatting\n * @param assetMarketTypes - Optional mapping of asset symbols to market types\n * @param assetNames - Optional mapping of asset symbols to human-readable names.\n * Defaults to the bundled HYPERLIQUID_ASSET_NAMES; unmapped assets fall back to\n * their ticker symbol.\n * @returns Transformed market data ready for UI consumption\n */\nexport function transformMarketData(\n hyperLiquidData: HyperLiquidMarketData,\n formatters: MarketDataFormatters,\n assetMarketTypes?: Record<string, MarketType>,\n assetNames?: Record<string, string>,\n): PerpsMarketData[] {\n const { universe, assetCtxs, allMids, predictedFundings } = hyperLiquidData;\n\n return universe.map((asset, index) => {\n const symbol = asset.name;\n const currentPrice = parseFloat(allMids[symbol]);\n\n // Find matching asset context for additional data\n // The assetCtxs array is aligned with universe array by index\n const assetCtx = assetCtxs[index];\n\n // Calculate 24h change\n const prevDayPrice = assetCtx ? parseFloat(assetCtx.prevDayPx) : 0;\n\n // Handle missing current price data\n const hasCurrentPrice = !isNaN(currentPrice);\n const effectiveCurrentPrice = hasCurrentPrice ? currentPrice : 0;\n\n // For dollar change: show $0.00 when current price is missing\n const change24h = hasCurrentPrice\n ? effectiveCurrentPrice - prevDayPrice\n : 0;\n\n // For percentage: show -100% when current price is missing but previous price exists\n const change24hPercent = calculateChange24hPercent({\n hasCurrentPrice,\n currentPrice: effectiveCurrentPrice,\n prevDayPrice,\n });\n\n // Format volume (dayNtlVlm is daily notional volume)\n // If assetCtx is missing or dayNtlVlm is not available, use NaN to indicate missing data\n const volume = assetCtx?.dayNtlVlm ? parseFloat(assetCtx.dayNtlVlm) : NaN;\n\n // Calculate open interest in USD\n const openInterest = calculateOpenInterestUSD(\n assetCtx?.openInterest,\n currentPrice,\n );\n\n // Get current funding rate from assetCtx - this is the actual current funding rate\n let fundingRate: number | undefined;\n\n if (assetCtx && hasProperty(assetCtx, 'funding')) {\n fundingRate = parseFloat(assetCtx.funding);\n }\n\n // Extract funding timing and predicted rate\n const fundingData = extractFundingData({\n predictedFundings,\n symbol,\n });\n\n // Use current funding rate from assetCtx, not predicted\n // The predicted rate is for the next funding period\n if (!fundingRate && fundingData.predictedFundingRate !== undefined) {\n fundingRate = fundingData.predictedFundingRate;\n }\n\n // Extract DEX and base symbol for display\n // e.g., \"flx:TSLA\" → { dex: \"flx\", symbol: \"TSLA\" }\n const { dex } = parseAssetName(symbol);\n const marketSource = dex ?? undefined;\n\n // HIP-3 markets have a DEX prefix (e.g., xyz:TSLA, flx:GOLD)\n // Crypto markets (HIP-2) don't have a prefix (e.g., BTC, ETH)\n const isHip3 = Boolean(dex);\n\n // Determine market type from explicit static mapping\n const marketType: MarketType | undefined = assetMarketTypes?.[symbol];\n\n // Mark as \"new\" if it's a HIP-3 market but not explicitly categorized\n const isNewMarket = isHip3 && !marketType;\n\n return {\n symbol,\n name: getHyperLiquidAssetName(symbol, assetNames),\n maxLeverage: `${asset.maxLeverage}x`,\n price: isNaN(currentPrice)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatPerpsFiat(currentPrice, {\n ranges: formatters.priceRangesUniversal,\n }),\n change24h: isNaN(change24h)\n ? PERPS_CONSTANTS.ZeroAmountDetailedDisplay\n : formatChange(change24h, formatters),\n change24hPercent: isNaN(change24hPercent)\n ? '0.00%'\n : formatters.formatPercentage(change24hPercent),\n volume: isNaN(volume)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatVolume(volume),\n openInterest: isNaN(openInterest)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatVolume(openInterest),\n nextFundingTime: fundingData.nextFundingTime,\n fundingIntervalHours: fundingData.fundingIntervalHours,\n fundingRate,\n marketSource,\n marketType,\n isHip3,\n isNewMarket,\n };\n });\n}\n\n/**\n * Format 24h change with sign.\n * Uses more decimal places for smaller amounts to show meaningful precision.\n *\n * @param change - The price change value to format\n * @param formatters - Injectable formatters\n * @returns Formatted change string with sign and dollar symbol\n */\nexport function formatChange(\n change: number,\n formatters: MarketDataFormatters,\n): string {\n if (isNaN(change) || !isFinite(change)) {\n return '$0.00';\n }\n if (change === 0) {\n return '$0.00';\n }\n\n const formatted = formatters.formatPerpsFiat(Math.abs(change), {\n ranges: formatters.priceRangesUniversal,\n });\n\n // Remove $ sign and add it back with proper sign placement\n const valueWithoutDollar = formatted.replace('$', '');\n return change > 0 ? `+$${valueWithoutDollar}` : `-$${valueWithoutDollar}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"marketDataTransform.mjs","sourceRoot":"","sources":["../../src/utils/marketDataTransform.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Market data transformation utilities.\n *\n * Portable: no mobile-specific imports.\n * Formatters are injected via MarketDataFormatters interface.\n */\nimport { hasProperty } from '@metamask/utils';\n\nimport {\n HYPERLIQUID_CONFIG,\n getHyperLiquidAssetName,\n} from '../constants/hyperLiquidConfig';\nimport { PERPS_CONSTANTS } from '../constants/perpsConfig';\nimport type {\n PerpsMarketData,\n MarketType,\n MarketDataFormatters,\n} from '../types';\nimport type {\n AllMidsResponse,\n PerpsUniverse,\n PerpsAssetCtx,\n PredictedFunding,\n} from '../types/hyperliquid-types';\nimport { parseAssetName } from './hyperLiquidAdapter';\n\n/**\n * Calculate open interest in USD\n * Open interest from HyperLiquid is in contracts/units, not USD\n * To get USD value, multiply by current price\n *\n * @param openInterest - Raw open interest value in contracts/units\n * @param currentPrice - Current price of the asset\n * @returns Open interest in USD, or NaN if invalid\n */\nexport function calculateOpenInterestUSD(\n openInterest: string | number | undefined,\n currentPrice: string | number | undefined,\n): number {\n if (openInterest === undefined || currentPrice === undefined) {\n return NaN;\n }\n\n const openInterestNum =\n typeof openInterest === 'string' ? parseFloat(openInterest) : openInterest;\n const priceNum =\n typeof currentPrice === 'string' ? parseFloat(currentPrice) : currentPrice;\n\n if (isNaN(openInterestNum) || isNaN(priceNum)) {\n return NaN;\n }\n\n return openInterestNum * priceNum;\n}\n\n/**\n * HyperLiquid-specific market data structure\n */\nexport type HyperLiquidMarketData = {\n universe: PerpsUniverse[];\n assetCtxs: PerpsAssetCtx[];\n allMids: AllMidsResponse;\n predictedFundings?: PredictedFunding[];\n};\n\n/**\n * Parameters for calculating 24h percentage change\n */\ntype CalculateChange24hPercentParams = {\n hasCurrentPrice: boolean;\n currentPrice: number;\n prevDayPrice: number;\n};\n\n/**\n * Calculate 24h percentage change\n * Shows -100% when current price is missing but previous price exists\n *\n * @param params - The parameters for calculating the 24h change.\n * @returns The 24h percentage change value.\n */\nfunction calculateChange24hPercent(\n params: CalculateChange24hPercentParams,\n): number {\n const { hasCurrentPrice, currentPrice, prevDayPrice } = params;\n\n if (!hasCurrentPrice) {\n return prevDayPrice > 0 ? -100 : 0;\n }\n\n if (prevDayPrice <= 0) {\n return 0;\n }\n\n return ((currentPrice - prevDayPrice) / prevDayPrice) * 100;\n}\n\n/**\n * Funding data extracted from predicted fundings\n */\ntype FundingData = {\n nextFundingTime?: number;\n fundingIntervalHours?: number;\n predictedFundingRate?: number;\n};\n\n/**\n * Parameters for extracting funding data\n */\ntype ExtractFundingDataParams = {\n predictedFundings?: PredictedFunding[];\n symbol: string;\n exchangeName?: string;\n};\n\n/**\n * Extract funding data for a symbol from predicted fundings.\n * Looks for specified exchange first, falls back to first available.\n *\n * @param params - Parameters for extracting funding data\n * @param params.predictedFundings - Array of predicted funding data\n * @param params.symbol - Asset symbol to extract funding for\n * @param params.exchangeName - Exchange to prioritize (defaults to HyperLiquid's 'HlPerp')\n * @returns Funding data including next funding time, interval, and predicted rate\n */\nfunction extractFundingData(params: ExtractFundingDataParams): FundingData {\n const {\n predictedFundings,\n symbol,\n exchangeName = HYPERLIQUID_CONFIG.ExchangeName,\n } = params;\n\n const result: FundingData = {};\n\n if (!predictedFundings) {\n return result;\n }\n\n const fundingData = predictedFundings.find(\n ([assetSymbol]) => assetSymbol === symbol,\n );\n\n if (\n !fundingData?.[1] ||\n !Array.isArray(fundingData[1]) ||\n fundingData[1].length === 0\n ) {\n return result;\n }\n\n // Look for specified exchange (e.g., 'HlPerp' for HyperLiquid)\n const targetExchange = fundingData[1].find(\n (exchange: unknown) =>\n Array.isArray(exchange) && exchange[0] === exchangeName,\n );\n\n if (targetExchange?.[1]) {\n result.nextFundingTime = targetExchange[1].nextFundingTime;\n result.fundingIntervalHours = targetExchange[1].fundingIntervalHours;\n result.predictedFundingRate = parseFloat(targetExchange[1].fundingRate);\n return result;\n }\n\n // Fallback to first exchange if target not found\n const firstExchange = fundingData[1][0];\n if (Array.isArray(firstExchange) && firstExchange[1]) {\n result.nextFundingTime = firstExchange[1].nextFundingTime;\n result.fundingIntervalHours = firstExchange[1].fundingIntervalHours;\n }\n\n return result;\n}\n\n/**\n * Transform raw HyperLiquid market data to UI-friendly format\n *\n * @param hyperLiquidData - Raw data from HyperLiquid API\n * @param formatters - Injectable formatters for platform-agnostic formatting\n * @param assetMarketTypes - Optional mapping of asset symbols to market types\n * @param assetNames - Optional mapping of asset symbols to human-readable names.\n * Defaults to the bundled HYPERLIQUID_ASSET_NAMES; unmapped assets fall back to\n * their ticker symbol.\n * @returns Transformed market data ready for UI consumption\n */\nexport function transformMarketData(\n hyperLiquidData: HyperLiquidMarketData,\n formatters: MarketDataFormatters,\n assetMarketTypes?: Record<string, MarketType>,\n assetNames?: Record<string, string>,\n): PerpsMarketData[] {\n const { universe, assetCtxs, allMids, predictedFundings } = hyperLiquidData;\n\n return universe.map((asset, index) => {\n const symbol = asset.name;\n const currentPrice = parseFloat(allMids[symbol]);\n\n // Find matching asset context for additional data\n // The assetCtxs array is aligned with universe array by index\n const assetCtx = assetCtxs[index];\n\n // Calculate 24h change\n const prevDayPrice = assetCtx ? parseFloat(assetCtx.prevDayPx) : 0;\n\n // Handle missing current price data\n const hasCurrentPrice = !isNaN(currentPrice);\n const effectiveCurrentPrice = hasCurrentPrice ? currentPrice : 0;\n\n // For dollar change: show $0.00 when current price is missing\n const change24h = hasCurrentPrice\n ? effectiveCurrentPrice - prevDayPrice\n : 0;\n\n // For percentage: show -100% when current price is missing but previous price exists\n const change24hPercent = calculateChange24hPercent({\n hasCurrentPrice,\n currentPrice: effectiveCurrentPrice,\n prevDayPrice,\n });\n\n // Format volume (dayNtlVlm is daily notional volume)\n // If assetCtx is missing or dayNtlVlm is not available, use NaN to indicate missing data\n const volume = assetCtx?.dayNtlVlm ? parseFloat(assetCtx.dayNtlVlm) : NaN;\n\n // Calculate open interest in USD\n const openInterest = calculateOpenInterestUSD(\n assetCtx?.openInterest,\n currentPrice,\n );\n\n // Get current funding rate from assetCtx - this is the actual current funding rate\n let fundingRate: number | undefined;\n\n if (assetCtx && hasProperty(assetCtx, 'funding')) {\n fundingRate = parseFloat(assetCtx.funding);\n }\n\n // Extract funding timing and predicted rate\n const fundingData = extractFundingData({\n predictedFundings,\n symbol,\n });\n\n // Use current funding rate from assetCtx, not predicted\n // The predicted rate is for the next funding period\n if (!fundingRate && fundingData.predictedFundingRate !== undefined) {\n fundingRate = fundingData.predictedFundingRate;\n }\n\n // Extract DEX and base symbol for display\n // e.g., \"flx:TSLA\" → { dex: \"flx\", symbol: \"TSLA\" }\n const { dex } = parseAssetName(symbol);\n const marketSource = dex ?? undefined;\n\n // HIP-3 markets have a DEX prefix (e.g., xyz:TSLA, flx:GOLD)\n // Crypto markets (HIP-2) don't have a prefix (e.g., BTC, ETH)\n const isHip3 = Boolean(dex);\n\n // Determine market type from explicit mapping only\n // Only explicitly mapped HIP-3 markets get a marketType (e.g., 'xyz:GOLD' → 'commodity')\n // Unmapped HIP-3 markets (e.g., 'hyna:BTC') have no marketType - they go to \"New\" tab\n // Main DEX crypto also has no marketType\n const explicitMarketType = assetMarketTypes?.[symbol];\n const marketType: MarketType | undefined = explicitMarketType;\n\n // Mark as \"new\" if it's a HIP-3 market but not explicitly categorized\n // New markets are always HIP-3 (non-crypto) that haven't been assigned a category yet\n const isNewMarket = isHip3 && !explicitMarketType;\n\n return {\n symbol,\n name: getHyperLiquidAssetName(symbol, assetNames),\n maxLeverage: `${asset.maxLeverage}x`,\n price: isNaN(currentPrice)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatPerpsFiat(currentPrice, {\n ranges: formatters.priceRangesUniversal,\n }),\n change24h: isNaN(change24h)\n ? PERPS_CONSTANTS.ZeroAmountDetailedDisplay\n : formatChange(change24h, formatters),\n change24hPercent: isNaN(change24hPercent)\n ? '0.00%'\n : formatters.formatPercentage(change24hPercent),\n volume: isNaN(volume)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatVolume(volume),\n openInterest: isNaN(openInterest)\n ? PERPS_CONSTANTS.FallbackPriceDisplay\n : formatters.formatVolume(openInterest),\n nextFundingTime: fundingData.nextFundingTime,\n fundingIntervalHours: fundingData.fundingIntervalHours,\n fundingRate,\n marketSource,\n marketType,\n isHip3,\n isNewMarket,\n };\n });\n}\n\n/**\n * Format 24h change with sign.\n * Uses more decimal places for smaller amounts to show meaningful precision.\n *\n * @param change - The price change value to format\n * @param formatters - Injectable formatters\n * @returns Formatted change string with sign and dollar symbol\n */\nexport function formatChange(\n change: number,\n formatters: MarketDataFormatters,\n): string {\n if (isNaN(change) || !isFinite(change)) {\n return '$0.00';\n }\n if (change === 0) {\n return '$0.00';\n }\n\n const formatted = formatters.formatPerpsFiat(Math.abs(change), {\n ranges: formatters.priceRangesUniversal,\n });\n\n // Remove $ sign and add it back with proper sign placement\n const valueWithoutDollar = formatted.replace('$', '');\n return change > 0 ? `+$${valueWithoutDollar}` : `-$${valueWithoutDollar}`;\n}\n"]}
|
|
@@ -33,36 +33,11 @@ function fieldRank(value, query) {
|
|
|
33
33
|
}
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
37
|
-
* Rank an array of keyword strings against a normalized query.
|
|
38
|
-
* Returns the best (lowest) rank found across all keywords, or null.
|
|
39
|
-
*
|
|
40
|
-
* @param keywords - Array of keyword strings; may be undefined.
|
|
41
|
-
* @param query - Already trimmed, lower-cased, non-empty query.
|
|
42
|
-
* @returns The best match tier across all keywords, or null when none match.
|
|
43
|
-
*/
|
|
44
|
-
function keywordsRank(keywords, query) {
|
|
45
|
-
if (!keywords || keywords.length === 0) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
let best = null;
|
|
49
|
-
for (const keyword of keywords) {
|
|
50
|
-
const rank = fieldRank(keyword, query);
|
|
51
|
-
if (rank === MarketMatchRank.Exact) {
|
|
52
|
-
return rank;
|
|
53
|
-
}
|
|
54
|
-
if (rank !== null && (best === null || rank < best)) {
|
|
55
|
-
best = rank;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return best;
|
|
59
|
-
}
|
|
60
36
|
/**
|
|
61
37
|
* Compute the best (lowest) relevance rank for a market against a search query,
|
|
62
|
-
* considering its ticker symbol
|
|
63
|
-
* from Terminal API metadata.
|
|
38
|
+
* considering both its ticker symbol and human-readable name.
|
|
64
39
|
*
|
|
65
|
-
* @param market - Market to score (uses `symbol
|
|
40
|
+
* @param market - Market to score (uses `symbol` and `name`).
|
|
66
41
|
* @param searchQuery - User search text (trimmed/cased internally).
|
|
67
42
|
* @returns The match rank, or null when the market does not match (or the query
|
|
68
43
|
* is empty/whitespace).
|
|
@@ -75,7 +50,6 @@ function getMarketMatchRank(market, searchQuery) {
|
|
|
75
50
|
const ranks = [
|
|
76
51
|
fieldRank(market.symbol, query),
|
|
77
52
|
fieldRank(market.name, query),
|
|
78
|
-
keywordsRank(market.keywords, query),
|
|
79
53
|
].filter((rank) => rank !== null);
|
|
80
54
|
return ranks.length > 0 ? Math.min(...ranks) : null;
|
|
81
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketSearch.cjs","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":";;;AAkBA;;GAEG;AACH,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,+DAAa,CAAA;AACf,CAAC,EAJW,eAAe,+BAAf,eAAe,QAI1B;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAChB,KAAyB,EACzB,KAAa;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC;IAC/B,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,eAAe,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC,SAAS,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"marketSearch.cjs","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":";;;AAkBA;;GAEG;AACH,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,+DAAa,CAAA;AACf,CAAC,EAJW,eAAe,+BAAf,eAAe,QAI1B;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAChB,KAAyB,EACzB,KAAa;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC;IAC/B,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,eAAe,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC,SAAS,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAChC,MAAgD,EAChD,WAAmB;IAEnB,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG;QACZ,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAC/B,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;KAC9B,CAAC,MAAM,CAAC,CAAC,IAAI,EAA2B,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAE3D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAdD,gDAcC;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAChC,OAA0B,EAC1B,WAAmB;IAEnB,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE/C,MAAM,OAAO,GAAyD,EAAE,CAAC;IACzE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,8DAA8D;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC;AArBD,gDAqBC","sourcesContent":["/**\n * Market search ranking (TAT-2413).\n *\n * Provisional, standalone helper layered on the same match semantics as\n * `filterMarketsByQuery` (case-insensitive substring on a market's ticker symbol\n * and human-readable name). It adds the one thing `filterMarketsByQuery` does\n * not: relevance ranking — exact matches first, then prefix, then substring;\n * ties keep their input order (stable). No fuzzy/phonetic matching (out of scope\n * for v1).\n *\n * Kept in its own file so it can be promoted or relocated later without touching\n * the shared `marketUtils`. A market matches here (rank !== null) iff\n * `filterMarketsByQuery` would include it, so the two stay behaviorally aligned.\n *\n * Portable: no platform-specific imports.\n */\nimport type { PerpsMarketData } from '../types';\n\n/**\n * Relevance tier for a market/query match. Lower values sort first.\n */\nexport enum MarketMatchRank {\n Exact = 0,\n Prefix = 1,\n Substring = 2,\n}\n\n/**\n * Rank a single field value against a normalized query.\n *\n * @param value - Field value (e.g. symbol or name); may be undefined.\n * @param query - Already trimmed, lower-cased, non-empty query.\n * @returns The match tier, or null when the field does not match.\n */\nfunction fieldRank(\n value: string | undefined,\n query: string,\n): MarketMatchRank | null {\n if (!value) {\n return null;\n }\n const normalized = value.toLowerCase();\n if (normalized === query) {\n return MarketMatchRank.Exact;\n }\n if (normalized.startsWith(query)) {\n return MarketMatchRank.Prefix;\n }\n if (normalized.includes(query)) {\n return MarketMatchRank.Substring;\n }\n return null;\n}\n\n/**\n * Compute the best (lowest) relevance rank for a market against a search query,\n * considering both its ticker symbol and human-readable name.\n *\n * @param market - Market to score (uses `symbol` and `name`).\n * @param searchQuery - User search text (trimmed/cased internally).\n * @returns The match rank, or null when the market does not match (or the query\n * is empty/whitespace).\n */\nexport function getMarketMatchRank(\n market: Pick<PerpsMarketData, 'symbol' | 'name'>,\n searchQuery: string,\n): MarketMatchRank | null {\n if (!searchQuery?.trim()) {\n return null;\n }\n const query = searchQuery.toLowerCase().trim();\n const ranks = [\n fieldRank(market.symbol, query),\n fieldRank(market.name, query),\n ].filter((rank): rank is MarketMatchRank => rank !== null);\n\n return ranks.length > 0 ? Math.min(...ranks) : null;\n}\n\n/**\n * Filter and rank markets by a search query, matching the human-readable name or\n * ticker symbol. Exact matches sort first, then prefix, then substring; markets\n * sharing a rank keep their input order (stable). An empty/whitespace query\n * returns the markets unchanged (no filtering), matching `filterMarketsByQuery`.\n *\n * @param markets - Markets to search.\n * @param searchQuery - User search text.\n * @returns Matching markets ordered by relevance.\n */\nexport function rankMarketsByQuery(\n markets: PerpsMarketData[],\n searchQuery: string,\n): PerpsMarketData[] {\n if (!searchQuery?.trim()) {\n return markets;\n }\n const query = searchQuery.toLowerCase().trim();\n\n const matches: { market: PerpsMarketData; rank: MarketMatchRank }[] = [];\n markets.forEach((market) => {\n const rank = getMarketMatchRank(market, query);\n if (rank !== null) {\n matches.push({ market, rank });\n }\n });\n\n // Stable sort by rank only; Array.prototype.sort is stable in modern engines,\n // so equal-rank markets retain their original relative order.\n matches.sort((a, b) => a.rank - b.rank);\n return matches.map((match) => match.market);\n}\n"]}
|
|
@@ -25,15 +25,14 @@ export declare enum MarketMatchRank {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Compute the best (lowest) relevance rank for a market against a search query,
|
|
28
|
-
* considering its ticker symbol
|
|
29
|
-
* from Terminal API metadata.
|
|
28
|
+
* considering both its ticker symbol and human-readable name.
|
|
30
29
|
*
|
|
31
|
-
* @param market - Market to score (uses `symbol
|
|
30
|
+
* @param market - Market to score (uses `symbol` and `name`).
|
|
32
31
|
* @param searchQuery - User search text (trimmed/cased internally).
|
|
33
32
|
* @returns The match rank, or null when the market does not match (or the query
|
|
34
33
|
* is empty/whitespace).
|
|
35
34
|
*/
|
|
36
|
-
export declare function getMarketMatchRank(market: Pick<PerpsMarketData, 'symbol' | 'name'
|
|
35
|
+
export declare function getMarketMatchRank(market: Pick<PerpsMarketData, 'symbol' | 'name'>, searchQuery: string): MarketMatchRank | null;
|
|
37
36
|
/**
|
|
38
37
|
* Filter and rank markets by a search query, matching the human-readable name or
|
|
39
38
|
* ticker symbol. Exact matches sort first, then prefix, then substring; markets
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketSearch.d.cts","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,2BAAiB;AAEhD;;GAEG;AACH,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,SAAS,IAAI;CACd;
|
|
1
|
+
{"version":3,"file":"marketSearch.d.cts","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,2BAAiB;AAEhD;;GAEG;AACH,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,SAAS,IAAI;CACd;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,MAAM,CAAC,EAChD,WAAW,EAAE,MAAM,GAClB,eAAe,GAAG,IAAI,CAWxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EAAE,EAC1B,WAAW,EAAE,MAAM,GAClB,eAAe,EAAE,CAkBnB"}
|
|
@@ -25,15 +25,14 @@ export declare enum MarketMatchRank {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Compute the best (lowest) relevance rank for a market against a search query,
|
|
28
|
-
* considering its ticker symbol
|
|
29
|
-
* from Terminal API metadata.
|
|
28
|
+
* considering both its ticker symbol and human-readable name.
|
|
30
29
|
*
|
|
31
|
-
* @param market - Market to score (uses `symbol
|
|
30
|
+
* @param market - Market to score (uses `symbol` and `name`).
|
|
32
31
|
* @param searchQuery - User search text (trimmed/cased internally).
|
|
33
32
|
* @returns The match rank, or null when the market does not match (or the query
|
|
34
33
|
* is empty/whitespace).
|
|
35
34
|
*/
|
|
36
|
-
export declare function getMarketMatchRank(market: Pick<PerpsMarketData, 'symbol' | 'name'
|
|
35
|
+
export declare function getMarketMatchRank(market: Pick<PerpsMarketData, 'symbol' | 'name'>, searchQuery: string): MarketMatchRank | null;
|
|
37
36
|
/**
|
|
38
37
|
* Filter and rank markets by a search query, matching the human-readable name or
|
|
39
38
|
* ticker symbol. Exact matches sort first, then prefix, then substring; markets
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketSearch.d.mts","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,2BAAiB;AAEhD;;GAEG;AACH,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,SAAS,IAAI;CACd;
|
|
1
|
+
{"version":3,"file":"marketSearch.d.mts","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,2BAAiB;AAEhD;;GAEG;AACH,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,SAAS,IAAI;CACd;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,MAAM,CAAC,EAChD,WAAW,EAAE,MAAM,GAClB,eAAe,GAAG,IAAI,CAWxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EAAE,EAC1B,WAAW,EAAE,MAAM,GAClB,eAAe,EAAE,CAkBnB"}
|
|
@@ -30,36 +30,11 @@ function fieldRank(value, query) {
|
|
|
30
30
|
}
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Rank an array of keyword strings against a normalized query.
|
|
35
|
-
* Returns the best (lowest) rank found across all keywords, or null.
|
|
36
|
-
*
|
|
37
|
-
* @param keywords - Array of keyword strings; may be undefined.
|
|
38
|
-
* @param query - Already trimmed, lower-cased, non-empty query.
|
|
39
|
-
* @returns The best match tier across all keywords, or null when none match.
|
|
40
|
-
*/
|
|
41
|
-
function keywordsRank(keywords, query) {
|
|
42
|
-
if (!keywords || keywords.length === 0) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
let best = null;
|
|
46
|
-
for (const keyword of keywords) {
|
|
47
|
-
const rank = fieldRank(keyword, query);
|
|
48
|
-
if (rank === MarketMatchRank.Exact) {
|
|
49
|
-
return rank;
|
|
50
|
-
}
|
|
51
|
-
if (rank !== null && (best === null || rank < best)) {
|
|
52
|
-
best = rank;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return best;
|
|
56
|
-
}
|
|
57
33
|
/**
|
|
58
34
|
* Compute the best (lowest) relevance rank for a market against a search query,
|
|
59
|
-
* considering its ticker symbol
|
|
60
|
-
* from Terminal API metadata.
|
|
35
|
+
* considering both its ticker symbol and human-readable name.
|
|
61
36
|
*
|
|
62
|
-
* @param market - Market to score (uses `symbol
|
|
37
|
+
* @param market - Market to score (uses `symbol` and `name`).
|
|
63
38
|
* @param searchQuery - User search text (trimmed/cased internally).
|
|
64
39
|
* @returns The match rank, or null when the market does not match (or the query
|
|
65
40
|
* is empty/whitespace).
|
|
@@ -72,7 +47,6 @@ export function getMarketMatchRank(market, searchQuery) {
|
|
|
72
47
|
const ranks = [
|
|
73
48
|
fieldRank(market.symbol, query),
|
|
74
49
|
fieldRank(market.name, query),
|
|
75
|
-
keywordsRank(market.keywords, query),
|
|
76
50
|
].filter((rank) => rank !== null);
|
|
77
51
|
return ranks.length > 0 ? Math.min(...ranks) : null;
|
|
78
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketSearch.mjs","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,+DAAa,CAAA;AACf,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAChB,KAAyB,EACzB,KAAa;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC;IAC/B,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,eAAe,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC,SAAS,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"marketSearch.mjs","sourceRoot":"","sources":["../../src/utils/marketSearch.ts"],"names":[],"mappings":"AAkBA;;GAEG;AACH,MAAM,CAAN,IAAY,eAIX;AAJD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,+DAAa,CAAA;AACf,CAAC,EAJW,eAAe,KAAf,eAAe,QAI1B;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAChB,KAAyB,EACzB,KAAa;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC;IAC/B,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,eAAe,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,eAAe,CAAC,SAAS,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAgD,EAChD,WAAmB;IAEnB,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG;QACZ,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;QAC/B,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;KAC9B,CAAC,MAAM,CAAC,CAAC,IAAI,EAA2B,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAE3D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAA0B,EAC1B,WAAmB;IAEnB,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAE/C,MAAM,OAAO,GAAyD,EAAE,CAAC;IACzE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACzB,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC/C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,8DAA8D;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC","sourcesContent":["/**\n * Market search ranking (TAT-2413).\n *\n * Provisional, standalone helper layered on the same match semantics as\n * `filterMarketsByQuery` (case-insensitive substring on a market's ticker symbol\n * and human-readable name). It adds the one thing `filterMarketsByQuery` does\n * not: relevance ranking — exact matches first, then prefix, then substring;\n * ties keep their input order (stable). No fuzzy/phonetic matching (out of scope\n * for v1).\n *\n * Kept in its own file so it can be promoted or relocated later without touching\n * the shared `marketUtils`. A market matches here (rank !== null) iff\n * `filterMarketsByQuery` would include it, so the two stay behaviorally aligned.\n *\n * Portable: no platform-specific imports.\n */\nimport type { PerpsMarketData } from '../types';\n\n/**\n * Relevance tier for a market/query match. Lower values sort first.\n */\nexport enum MarketMatchRank {\n Exact = 0,\n Prefix = 1,\n Substring = 2,\n}\n\n/**\n * Rank a single field value against a normalized query.\n *\n * @param value - Field value (e.g. symbol or name); may be undefined.\n * @param query - Already trimmed, lower-cased, non-empty query.\n * @returns The match tier, or null when the field does not match.\n */\nfunction fieldRank(\n value: string | undefined,\n query: string,\n): MarketMatchRank | null {\n if (!value) {\n return null;\n }\n const normalized = value.toLowerCase();\n if (normalized === query) {\n return MarketMatchRank.Exact;\n }\n if (normalized.startsWith(query)) {\n return MarketMatchRank.Prefix;\n }\n if (normalized.includes(query)) {\n return MarketMatchRank.Substring;\n }\n return null;\n}\n\n/**\n * Compute the best (lowest) relevance rank for a market against a search query,\n * considering both its ticker symbol and human-readable name.\n *\n * @param market - Market to score (uses `symbol` and `name`).\n * @param searchQuery - User search text (trimmed/cased internally).\n * @returns The match rank, or null when the market does not match (or the query\n * is empty/whitespace).\n */\nexport function getMarketMatchRank(\n market: Pick<PerpsMarketData, 'symbol' | 'name'>,\n searchQuery: string,\n): MarketMatchRank | null {\n if (!searchQuery?.trim()) {\n return null;\n }\n const query = searchQuery.toLowerCase().trim();\n const ranks = [\n fieldRank(market.symbol, query),\n fieldRank(market.name, query),\n ].filter((rank): rank is MarketMatchRank => rank !== null);\n\n return ranks.length > 0 ? Math.min(...ranks) : null;\n}\n\n/**\n * Filter and rank markets by a search query, matching the human-readable name or\n * ticker symbol. Exact matches sort first, then prefix, then substring; markets\n * sharing a rank keep their input order (stable). An empty/whitespace query\n * returns the markets unchanged (no filtering), matching `filterMarketsByQuery`.\n *\n * @param markets - Markets to search.\n * @param searchQuery - User search text.\n * @returns Matching markets ordered by relevance.\n */\nexport function rankMarketsByQuery(\n markets: PerpsMarketData[],\n searchQuery: string,\n): PerpsMarketData[] {\n if (!searchQuery?.trim()) {\n return markets;\n }\n const query = searchQuery.toLowerCase().trim();\n\n const matches: { market: PerpsMarketData; rank: MarketMatchRank }[] = [];\n markets.forEach((market) => {\n const rank = getMarketMatchRank(market, query);\n if (rank !== null) {\n matches.push({ market, rank });\n }\n });\n\n // Stable sort by rank only; Array.prototype.sort is stable in modern engines,\n // so equal-rank markets retain their original relative order.\n matches.sort((a, b) => a.rank - b.rank);\n return matches.map((match) => match.market);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/perps-controller",
|
|
3
|
-
"version": "8.2.0-preview-
|
|
3
|
+
"version": "8.2.0-preview-153490ebd",
|
|
4
4
|
"description": "Controller for perpetual trading functionality in MetaMask",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ethereum",
|
|
@@ -98,9 +98,8 @@
|
|
|
98
98
|
"dependencies": {
|
|
99
99
|
"@metamask/abi-utils": "^2.0.3",
|
|
100
100
|
"@metamask/base-controller": "^9.1.0",
|
|
101
|
-
"@metamask/controller-utils": "^12.
|
|
101
|
+
"@metamask/controller-utils": "^12.2.0",
|
|
102
102
|
"@metamask/messenger": "^1.2.0",
|
|
103
|
-
"@metamask/superstruct": "^3.1.0",
|
|
104
103
|
"@metamask/utils": "^11.11.0",
|
|
105
104
|
"@nktkas/hyperliquid": "^0.32.2",
|
|
106
105
|
"bignumber.js": "^9.1.2",
|
|
@@ -113,10 +112,10 @@
|
|
|
113
112
|
"@metamask/geolocation-controller": "^0.1.3",
|
|
114
113
|
"@metamask/keyring-controller": "^27.1.0",
|
|
115
114
|
"@metamask/keyring-internal-api": "^11.0.1",
|
|
116
|
-
"@metamask/network-controller": "^
|
|
115
|
+
"@metamask/network-controller": "^32.0.0",
|
|
117
116
|
"@metamask/profile-sync-controller": "^28.2.0",
|
|
118
117
|
"@metamask/remote-feature-flag-controller": "^4.2.2",
|
|
119
|
-
"@metamask/transaction-controller": "^68.1.
|
|
118
|
+
"@metamask/transaction-controller": "^68.1.0",
|
|
120
119
|
"@ts-bridge/cli": "^0.6.4",
|
|
121
120
|
"@types/jest": "^29.5.14",
|
|
122
121
|
"@types/uuid": "^8.3.0",
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _TerminalMarketService_instances, _TerminalMarketService_deps, _TerminalMarketService_cache, _TerminalMarketService_validateItems, _TerminalMarketService_mapToMarketInfo, _TerminalMarketService_extractMetadata;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.TerminalMarketService = void 0;
|
|
16
|
-
const superstruct_1 = require("@metamask/superstruct");
|
|
17
|
-
const perpsConfig_1 = require("../constants/perpsConfig.cjs");
|
|
18
|
-
const types_1 = require("../types/index.cjs");
|
|
19
|
-
const errorUtils_1 = require("../utils/errorUtils.cjs");
|
|
20
|
-
const VALID_MARKET_TYPES = new Set(Object.values(types_1.MarketCategory));
|
|
21
|
-
/**
|
|
22
|
-
* Runtime validation schema for a single market item returned by
|
|
23
|
-
* `GET {terminalApiUrl}`.
|
|
24
|
-
*
|
|
25
|
-
* Uses `type()` (loose object matching) so that extra fields the API sends
|
|
26
|
-
* (e.g. `price`, `iconUrl`, `trend`) are silently accepted.
|
|
27
|
-
* Each item is individually validated; items that fail validation are
|
|
28
|
-
* filtered out and logged rather than rejecting the entire response.
|
|
29
|
-
*/
|
|
30
|
-
const TerminalPerpetualItemStruct = (0, superstruct_1.type)({
|
|
31
|
-
symbol: (0, superstruct_1.string)(),
|
|
32
|
-
name: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.string)())),
|
|
33
|
-
szDecimals: (0, superstruct_1.optional)((0, superstruct_1.number)()),
|
|
34
|
-
maxLeverage: (0, superstruct_1.optional)((0, superstruct_1.number)()),
|
|
35
|
-
marginTableId: (0, superstruct_1.optional)((0, superstruct_1.number)()),
|
|
36
|
-
onlyIsolated: (0, superstruct_1.optional)((0, superstruct_1.boolean)()),
|
|
37
|
-
isDelisted: (0, superstruct_1.optional)((0, superstruct_1.boolean)()),
|
|
38
|
-
minimumOrderSize: (0, superstruct_1.optional)((0, superstruct_1.number)()),
|
|
39
|
-
keywords: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.array)((0, superstruct_1.string)()))),
|
|
40
|
-
tags: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.array)((0, superstruct_1.string)()))),
|
|
41
|
-
categories: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.array)((0, superstruct_1.string)()))),
|
|
42
|
-
marketType: (0, superstruct_1.optional)((0, superstruct_1.nullable)((0, superstruct_1.string)())),
|
|
43
|
-
});
|
|
44
|
-
/**
|
|
45
|
-
* TerminalMarketService
|
|
46
|
-
*
|
|
47
|
-
* Fetches structured market metadata from the MetaMask Terminal API.
|
|
48
|
-
* Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid
|
|
49
|
-
* redundant network calls across polling cycles.
|
|
50
|
-
*
|
|
51
|
-
* Instance-based service with constructor injection of platform dependencies.
|
|
52
|
-
*/
|
|
53
|
-
class TerminalMarketService {
|
|
54
|
-
constructor(deps) {
|
|
55
|
-
_TerminalMarketService_instances.add(this);
|
|
56
|
-
_TerminalMarketService_deps.set(this, void 0);
|
|
57
|
-
_TerminalMarketService_cache.set(this, null);
|
|
58
|
-
__classPrivateFieldSet(this, _TerminalMarketService_deps, deps, "f");
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Fetch markets from the Terminal API.
|
|
62
|
-
* Returns cached data when available and within TTL.
|
|
63
|
-
*
|
|
64
|
-
* @returns Object with mapped MarketInfo array and per-symbol metadata.
|
|
65
|
-
*/
|
|
66
|
-
async fetchMarkets() {
|
|
67
|
-
if (__classPrivateFieldGet(this, _TerminalMarketService_cache, "f") &&
|
|
68
|
-
Date.now() - __classPrivateFieldGet(this, _TerminalMarketService_cache, "f").timestamp < perpsConfig_1.TERMINAL_API_CONFIG.CacheTtlMs) {
|
|
69
|
-
return {
|
|
70
|
-
markets: __classPrivateFieldGet(this, _TerminalMarketService_cache, "f").markets,
|
|
71
|
-
metadata: __classPrivateFieldGet(this, _TerminalMarketService_cache, "f").metadata,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
if (!__classPrivateFieldGet(this, _TerminalMarketService_deps, "f").terminalApiUrl) {
|
|
75
|
-
throw new Error('Terminal API URL not configured (terminalApiUrl is required)');
|
|
76
|
-
}
|
|
77
|
-
const url = __classPrivateFieldGet(this, _TerminalMarketService_deps, "f").terminalApiUrl;
|
|
78
|
-
const response = await fetch(url, {
|
|
79
|
-
method: 'GET',
|
|
80
|
-
headers: { 'Content-Type': 'application/json' },
|
|
81
|
-
});
|
|
82
|
-
if (!response.ok) {
|
|
83
|
-
throw new Error(`Terminal API returned ${String(response.status)}: ${response.statusText}`);
|
|
84
|
-
}
|
|
85
|
-
const body = await response.json();
|
|
86
|
-
if (!Array.isArray(body)) {
|
|
87
|
-
throw new Error(`Terminal API returned non-array body: ${typeof body}`);
|
|
88
|
-
}
|
|
89
|
-
const items = __classPrivateFieldGet(this, _TerminalMarketService_instances, "m", _TerminalMarketService_validateItems).call(this, body);
|
|
90
|
-
const markets = __classPrivateFieldGet(this, _TerminalMarketService_instances, "m", _TerminalMarketService_mapToMarketInfo).call(this, items);
|
|
91
|
-
const metadata = __classPrivateFieldGet(this, _TerminalMarketService_instances, "m", _TerminalMarketService_extractMetadata).call(this, items);
|
|
92
|
-
__classPrivateFieldSet(this, _TerminalMarketService_cache, { markets, metadata, timestamp: Date.now() }, "f");
|
|
93
|
-
return { markets, metadata };
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Invalidate the internal cache so the next fetch hits the network.
|
|
97
|
-
*/
|
|
98
|
-
clearCache() {
|
|
99
|
-
__classPrivateFieldSet(this, _TerminalMarketService_cache, null, "f");
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Log a Terminal API error to Sentry without surfacing it to the user.
|
|
103
|
-
*
|
|
104
|
-
* @param error - The caught error.
|
|
105
|
-
* @param method - The calling method name for context.
|
|
106
|
-
*/
|
|
107
|
-
logError(error, method) {
|
|
108
|
-
__classPrivateFieldGet(this, _TerminalMarketService_deps, "f").logger.error((0, errorUtils_1.ensureError)(error, `TerminalMarketService.${method}`), {
|
|
109
|
-
tags: { feature: perpsConfig_1.PERPS_CONSTANTS.FeatureName, source: 'terminal-api' },
|
|
110
|
-
context: {
|
|
111
|
-
name: `TerminalMarketService.${method}`,
|
|
112
|
-
data: { url: __classPrivateFieldGet(this, _TerminalMarketService_deps, "f").terminalApiUrl },
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
exports.TerminalMarketService = TerminalMarketService;
|
|
118
|
-
_TerminalMarketService_deps = new WeakMap(), _TerminalMarketService_cache = new WeakMap(), _TerminalMarketService_instances = new WeakSet(), _TerminalMarketService_validateItems = function _TerminalMarketService_validateItems(raw) {
|
|
119
|
-
const valid = [];
|
|
120
|
-
for (const item of raw) {
|
|
121
|
-
if ((0, superstruct_1.is)(item, TerminalPerpetualItemStruct)) {
|
|
122
|
-
valid.push(item);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
__classPrivateFieldGet(this, _TerminalMarketService_deps, "f").logger.error((0, errorUtils_1.ensureError)(new Error('Terminal API item failed schema validation'), 'TerminalMarketService.validateItems'), {
|
|
126
|
-
tags: {
|
|
127
|
-
feature: perpsConfig_1.PERPS_CONSTANTS.FeatureName,
|
|
128
|
-
source: 'terminal-api',
|
|
129
|
-
},
|
|
130
|
-
context: {
|
|
131
|
-
name: 'TerminalMarketService.validateItems',
|
|
132
|
-
data: {
|
|
133
|
-
symbol: typeof item === 'object' &&
|
|
134
|
-
item !== null &&
|
|
135
|
-
Object.prototype.hasOwnProperty.call(item, 'symbol')
|
|
136
|
-
? item.symbol
|
|
137
|
-
: undefined,
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return valid;
|
|
144
|
-
}, _TerminalMarketService_mapToMarketInfo = function _TerminalMarketService_mapToMarketInfo(items) {
|
|
145
|
-
return items
|
|
146
|
-
.filter((item) => typeof item.symbol === 'string' && item.symbol.length > 0)
|
|
147
|
-
.map((item) => ({
|
|
148
|
-
name: item.symbol,
|
|
149
|
-
szDecimals: item.szDecimals ?? 0,
|
|
150
|
-
maxLeverage: item.maxLeverage ?? 1,
|
|
151
|
-
marginTableId: item.marginTableId ?? 0,
|
|
152
|
-
...(item.onlyIsolated === true && { onlyIsolated: true }),
|
|
153
|
-
...(item.isDelisted === true && { isDelisted: true }),
|
|
154
|
-
...(item.minimumOrderSize !== undefined && {
|
|
155
|
-
minimumOrderSize: item.minimumOrderSize,
|
|
156
|
-
}),
|
|
157
|
-
}));
|
|
158
|
-
}, _TerminalMarketService_extractMetadata = function _TerminalMarketService_extractMetadata(items) {
|
|
159
|
-
const map = new Map();
|
|
160
|
-
for (const item of items) {
|
|
161
|
-
if (typeof item.symbol !== 'string' || item.symbol.length === 0) {
|
|
162
|
-
continue;
|
|
163
|
-
}
|
|
164
|
-
const entry = {
|
|
165
|
-
name: item.name ?? item.symbol,
|
|
166
|
-
};
|
|
167
|
-
if (Array.isArray(item.keywords) && item.keywords.length > 0) {
|
|
168
|
-
entry.keywords = item.keywords;
|
|
169
|
-
}
|
|
170
|
-
if (Array.isArray(item.tags) && item.tags.length > 0) {
|
|
171
|
-
entry.tags = item.tags;
|
|
172
|
-
}
|
|
173
|
-
if (Array.isArray(item.categories) && item.categories.length > 0) {
|
|
174
|
-
entry.categories = item.categories;
|
|
175
|
-
}
|
|
176
|
-
if (typeof item.marketType === 'string' &&
|
|
177
|
-
VALID_MARKET_TYPES.has(item.marketType)) {
|
|
178
|
-
entry.marketType =
|
|
179
|
-
item.marketType;
|
|
180
|
-
}
|
|
181
|
-
map.set(item.symbol, entry);
|
|
182
|
-
}
|
|
183
|
-
return map;
|
|
184
|
-
};
|
|
185
|
-
//# sourceMappingURL=TerminalMarketService.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalMarketService.cjs","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,uDAS+B;AAE/B,8DAAgF;AAMhF,8CAA0C;AAC1C,wDAAkD;AAElD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,MAAM,CAAC,sBAAc,CAAC,CAAC,CAAC;AAE1E;;;;;;;;GAQG;AACH,MAAM,2BAA2B,GAAG,IAAA,kBAAI,EAAC;IACvC,MAAM,EAAE,IAAA,oBAAM,GAAE;IAChB,IAAI,EAAE,IAAA,sBAAQ,EAAC,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC,CAAC;IAClC,UAAU,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC;IAC9B,WAAW,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC;IAC/B,aAAa,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC;IACjC,YAAY,EAAE,IAAA,sBAAQ,EAAC,IAAA,qBAAO,GAAE,CAAC;IACjC,UAAU,EAAE,IAAA,sBAAQ,EAAC,IAAA,qBAAO,GAAE,CAAC;IAC/B,gBAAgB,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC;IACpC,QAAQ,EAAE,IAAA,sBAAQ,EAAC,IAAA,sBAAQ,EAAC,IAAA,mBAAK,EAAC,IAAA,oBAAM,GAAE,CAAC,CAAC,CAAC;IAC7C,IAAI,EAAE,IAAA,sBAAQ,EAAC,IAAA,sBAAQ,EAAC,IAAA,mBAAK,EAAC,IAAA,oBAAM,GAAE,CAAC,CAAC,CAAC;IACzC,UAAU,EAAE,IAAA,sBAAQ,EAAC,IAAA,sBAAQ,EAAC,IAAA,mBAAK,EAAC,IAAA,oBAAM,GAAE,CAAC,CAAC,CAAC;IAC/C,UAAU,EAAE,IAAA,sBAAQ,EAAC,IAAA,sBAAQ,EAAC,IAAA,oBAAM,GAAE,CAAC,CAAC;CACzC,CAAC,CAAC;AAUH;;;;;;;;GAQG;AACH,MAAa,qBAAqB;IAKhC,YAAY,IAA+B;;QAJlC,8CAAiC;QAE1C,uCAA4B,IAAI,EAAC;QAG/B,uBAAA,IAAI,+BAAS,IAAI,MAAA,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY;QAIhB,IACE,uBAAA,IAAI,oCAAO;YACX,IAAI,CAAC,GAAG,EAAE,GAAG,uBAAA,IAAI,oCAAO,CAAC,SAAS,GAAG,iCAAmB,CAAC,UAAU,EACnE,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,uBAAA,IAAI,oCAAO,CAAC,OAAO;gBAC5B,QAAQ,EAAE,uBAAA,IAAI,oCAAO,CAAC,QAAQ;aAC/B,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,uBAAA,IAAI,mCAAM,CAAC,cAAc,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;QACJ,CAAC;QAED,MAAM,GAAG,GAAG,uBAAA,IAAI,mCAAM,CAAC,cAAc,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,yBAAyB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,UAAU,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE5C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,yCAAyC,OAAO,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,KAAK,GAAG,uBAAA,IAAI,8EAAe,MAAnB,IAAI,EAAgB,IAAI,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,uBAAA,IAAI,gFAAiB,MAArB,IAAI,EAAkB,KAAK,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,uBAAA,IAAI,gFAAiB,MAArB,IAAI,EAAkB,KAAK,CAAC,CAAC;QAE9C,uBAAA,IAAI,gCAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAA,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,uBAAA,IAAI,gCAAU,IAAI,MAAA,CAAC;IACrB,CAAC;IA+GD;;;;;OAKG;IACH,QAAQ,CAAC,KAAc,EAAE,MAAc;QACrC,uBAAA,IAAI,mCAAM,CAAC,MAAM,CAAC,KAAK,CACrB,IAAA,wBAAW,EAAC,KAAK,EAAE,yBAAyB,MAAM,EAAE,CAAC,EACrD;YACE,IAAI,EAAE,EAAE,OAAO,EAAE,6BAAe,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE;YACtE,OAAO,EAAE;gBACP,IAAI,EAAE,yBAAyB,MAAM,EAAE;gBACvC,IAAI,EAAE,EAAE,GAAG,EAAE,uBAAA,IAAI,mCAAM,CAAC,cAAc,EAAE;aACzC;SACF,CACF,CAAC;IACJ,CAAC;CACF;AAnMD,sDAmMC;kOAvHgB,GAAc;IAC3B,MAAM,KAAK,GAA4B,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,IAAA,gBAAE,EAAC,IAAI,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,uBAAA,IAAI,mCAAM,CAAC,MAAM,CAAC,KAAK,CACrB,IAAA,wBAAW,EACT,IAAI,KAAK,CAAC,4CAA4C,CAAC,EACvD,qCAAqC,CACtC,EACD;gBACE,IAAI,EAAE;oBACJ,OAAO,EAAE,6BAAe,CAAC,WAAW;oBACpC,MAAM,EAAE,cAAc;iBACvB;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,qCAAqC;oBAC3C,IAAI,EAAE;wBACJ,MAAM,EACJ,OAAO,IAAI,KAAK,QAAQ;4BACxB,IAAI,KAAK,IAAI;4BACb,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;4BAClD,CAAC,CAAE,IAAgC,CAAC,MAAM;4BAC1C,CAAC,CAAC,SAAS;qBAChB;iBACF;aACF,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,2FAQgB,KAA8B;IAC7C,OAAO,KAAK;SACT,MAAM,CACL,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CACpE;SACA,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACd,IAAI,EAAE,IAAI,CAAC,MAAM;QACjB,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;QAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,CAAC;QAClC,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC,YAAY,KAAK,IAAI,IAAI,EAAE,YAAY,EAAE,IAAa,EAAE,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,EAAE,UAAU,EAAE,IAAa,EAAE,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,gBAAgB,KAAK,SAAS,IAAI;YACzC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;SACxC,CAAC;KACH,CAAC,CAAC,CAAC;AACR,CAAC,2FASC,KAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiC,CAAC;IAErD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChE,SAAS;QACX,CAAC;QAED,MAAM,KAAK,GAA0B;YACnC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;SAC/B,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7D,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACjC,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACrC,CAAC;QACD,IACE,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;YACnC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EACvC,CAAC;YACD,KAAK,CAAC,UAAU;gBACd,IAAI,CAAC,UAAiD,CAAC;QAC3D,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import type { Infer } from '@metamask/superstruct';\nimport {\n array,\n boolean,\n is,\n nullable,\n number,\n optional,\n string,\n type,\n} from '@metamask/superstruct';\n\nimport { PERPS_CONSTANTS, TERMINAL_API_CONFIG } from '../constants/perpsConfig';\nimport type {\n MarketInfo,\n PerpsPlatformDependencies,\n TerminalAssetMetadata,\n} from '../types';\nimport { MarketCategory } from '../types';\nimport { ensureError } from '../utils/errorUtils';\n\nconst VALID_MARKET_TYPES = new Set<string>(Object.values(MarketCategory));\n\n/**\n * Runtime validation schema for a single market item returned by\n * `GET {terminalApiUrl}`.\n *\n * Uses `type()` (loose object matching) so that extra fields the API sends\n * (e.g. `price`, `iconUrl`, `trend`) are silently accepted.\n * Each item is individually validated; items that fail validation are\n * filtered out and logged rather than rejecting the entire response.\n */\nconst TerminalPerpetualItemStruct = type({\n symbol: string(),\n name: optional(nullable(string())),\n szDecimals: optional(number()),\n maxLeverage: optional(number()),\n marginTableId: optional(number()),\n onlyIsolated: optional(boolean()),\n isDelisted: optional(boolean()),\n minimumOrderSize: optional(number()),\n keywords: optional(nullable(array(string()))),\n tags: optional(nullable(array(string()))),\n categories: optional(nullable(array(string()))),\n marketType: optional(nullable(string())),\n});\n\ntype TerminalPerpetualItem = Infer<typeof TerminalPerpetualItemStruct>;\n\ntype CacheEntry = {\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n timestamp: number;\n};\n\n/**\n * TerminalMarketService\n *\n * Fetches structured market metadata from the MetaMask Terminal API.\n * Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid\n * redundant network calls across polling cycles.\n *\n * Instance-based service with constructor injection of platform dependencies.\n */\nexport class TerminalMarketService {\n readonly #deps: PerpsPlatformDependencies;\n\n #cache: CacheEntry | null = null;\n\n constructor(deps: PerpsPlatformDependencies) {\n this.#deps = deps;\n }\n\n /**\n * Fetch markets from the Terminal API.\n * Returns cached data when available and within TTL.\n *\n * @returns Object with mapped MarketInfo array and per-symbol metadata.\n */\n async fetchMarkets(): Promise<{\n markets: MarketInfo[];\n metadata: Map<string, TerminalAssetMetadata>;\n }> {\n if (\n this.#cache &&\n Date.now() - this.#cache.timestamp < TERMINAL_API_CONFIG.CacheTtlMs\n ) {\n return {\n markets: this.#cache.markets,\n metadata: this.#cache.metadata,\n };\n }\n\n if (!this.#deps.terminalApiUrl) {\n throw new Error(\n 'Terminal API URL not configured (terminalApiUrl is required)',\n );\n }\n\n const url = this.#deps.terminalApiUrl;\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json' },\n });\n\n if (!response.ok) {\n throw new Error(\n `Terminal API returned ${String(response.status)}: ${response.statusText}`,\n );\n }\n\n const body: unknown = await response.json();\n\n if (!Array.isArray(body)) {\n throw new Error(`Terminal API returned non-array body: ${typeof body}`);\n }\n\n const items = this.#validateItems(body);\n const markets = this.#mapToMarketInfo(items);\n const metadata = this.#extractMetadata(items);\n\n this.#cache = { markets, metadata, timestamp: Date.now() };\n return { markets, metadata };\n }\n\n /**\n * Invalidate the internal cache so the next fetch hits the network.\n */\n clearCache(): void {\n this.#cache = null;\n }\n\n /**\n * Validate raw API response items against the expected schema.\n * Items that fail validation are filtered out and logged rather than\n * rejecting the entire response.\n *\n * @param raw - The raw array from the API response body.\n * @returns Array of validated items.\n */\n #validateItems(raw: unknown[]): TerminalPerpetualItem[] {\n const valid: TerminalPerpetualItem[] = [];\n for (const item of raw) {\n if (is(item, TerminalPerpetualItemStruct)) {\n valid.push(item);\n } else {\n this.#deps.logger.error(\n ensureError(\n new Error('Terminal API item failed schema validation'),\n 'TerminalMarketService.validateItems',\n ),\n {\n tags: {\n feature: PERPS_CONSTANTS.FeatureName,\n source: 'terminal-api',\n },\n context: {\n name: 'TerminalMarketService.validateItems',\n data: {\n symbol:\n typeof item === 'object' &&\n item !== null &&\n Object.prototype.hasOwnProperty.call(item, 'symbol')\n ? (item as Record<string, unknown>).symbol\n : undefined,\n },\n },\n },\n );\n }\n }\n return valid;\n }\n\n /**\n * Map Terminal API items to the protocol-agnostic MarketInfo shape.\n *\n * @param items - Raw items from the API response.\n * @returns Array of MarketInfo objects.\n */\n #mapToMarketInfo(items: TerminalPerpetualItem[]): MarketInfo[] {\n return items\n .filter(\n (item) => typeof item.symbol === 'string' && item.symbol.length > 0,\n )\n .map((item) => ({\n name: item.symbol,\n szDecimals: item.szDecimals ?? 0,\n maxLeverage: item.maxLeverage ?? 1,\n marginTableId: item.marginTableId ?? 0,\n ...(item.onlyIsolated === true && { onlyIsolated: true as const }),\n ...(item.isDelisted === true && { isDelisted: true as const }),\n ...(item.minimumOrderSize !== undefined && {\n minimumOrderSize: item.minimumOrderSize,\n }),\n }));\n }\n\n /**\n * Extract per-symbol metadata for downstream merge into PerpsMarketData.\n *\n * @param items - Raw items from the API response.\n * @returns Map keyed by symbol with enrichment metadata.\n */\n #extractMetadata(\n items: TerminalPerpetualItem[],\n ): Map<string, TerminalAssetMetadata> {\n const map = new Map<string, TerminalAssetMetadata>();\n\n for (const item of items) {\n if (typeof item.symbol !== 'string' || item.symbol.length === 0) {\n continue;\n }\n\n const entry: TerminalAssetMetadata = {\n name: item.name ?? item.symbol,\n };\n\n if (Array.isArray(item.keywords) && item.keywords.length > 0) {\n entry.keywords = item.keywords;\n }\n if (Array.isArray(item.tags) && item.tags.length > 0) {\n entry.tags = item.tags;\n }\n if (Array.isArray(item.categories) && item.categories.length > 0) {\n entry.categories = item.categories;\n }\n if (\n typeof item.marketType === 'string' &&\n VALID_MARKET_TYPES.has(item.marketType)\n ) {\n entry.marketType =\n item.marketType as TerminalAssetMetadata['marketType'];\n }\n\n map.set(item.symbol, entry);\n }\n\n return map;\n }\n\n /**\n * Log a Terminal API error to Sentry without surfacing it to the user.\n *\n * @param error - The caught error.\n * @param method - The calling method name for context.\n */\n logError(error: unknown, method: string): void {\n this.#deps.logger.error(\n ensureError(error, `TerminalMarketService.${method}`),\n {\n tags: { feature: PERPS_CONSTANTS.FeatureName, source: 'terminal-api' },\n context: {\n name: `TerminalMarketService.${method}`,\n data: { url: this.#deps.terminalApiUrl },\n },\n },\n );\n }\n}\n"]}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { MarketInfo, PerpsPlatformDependencies, TerminalAssetMetadata } from "../types/index.cjs";
|
|
2
|
-
/**
|
|
3
|
-
* TerminalMarketService
|
|
4
|
-
*
|
|
5
|
-
* Fetches structured market metadata from the MetaMask Terminal API.
|
|
6
|
-
* Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid
|
|
7
|
-
* redundant network calls across polling cycles.
|
|
8
|
-
*
|
|
9
|
-
* Instance-based service with constructor injection of platform dependencies.
|
|
10
|
-
*/
|
|
11
|
-
export declare class TerminalMarketService {
|
|
12
|
-
#private;
|
|
13
|
-
constructor(deps: PerpsPlatformDependencies);
|
|
14
|
-
/**
|
|
15
|
-
* Fetch markets from the Terminal API.
|
|
16
|
-
* Returns cached data when available and within TTL.
|
|
17
|
-
*
|
|
18
|
-
* @returns Object with mapped MarketInfo array and per-symbol metadata.
|
|
19
|
-
*/
|
|
20
|
-
fetchMarkets(): Promise<{
|
|
21
|
-
markets: MarketInfo[];
|
|
22
|
-
metadata: Map<string, TerminalAssetMetadata>;
|
|
23
|
-
}>;
|
|
24
|
-
/**
|
|
25
|
-
* Invalidate the internal cache so the next fetch hits the network.
|
|
26
|
-
*/
|
|
27
|
-
clearCache(): void;
|
|
28
|
-
/**
|
|
29
|
-
* Log a Terminal API error to Sentry without surfacing it to the user.
|
|
30
|
-
*
|
|
31
|
-
* @param error - The caught error.
|
|
32
|
-
* @param method - The calling method name for context.
|
|
33
|
-
*/
|
|
34
|
-
logError(error: unknown, method: string): void;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=TerminalMarketService.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalMarketService.d.cts","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,UAAU,EACV,yBAAyB,EACzB,qBAAqB,EACtB,2BAAiB;AAsClB;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;;gBAKpB,IAAI,EAAE,yBAAyB;IAI3C;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC;QAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;KAC9C,CAAC;IA2CF;;OAEG;IACH,UAAU,IAAI,IAAI;IAiHlB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAY/C"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { MarketInfo, PerpsPlatformDependencies, TerminalAssetMetadata } from "../types/index.mjs";
|
|
2
|
-
/**
|
|
3
|
-
* TerminalMarketService
|
|
4
|
-
*
|
|
5
|
-
* Fetches structured market metadata from the MetaMask Terminal API.
|
|
6
|
-
* Caches responses for {@link TERMINAL_API_CONFIG.CacheTtlMs} to avoid
|
|
7
|
-
* redundant network calls across polling cycles.
|
|
8
|
-
*
|
|
9
|
-
* Instance-based service with constructor injection of platform dependencies.
|
|
10
|
-
*/
|
|
11
|
-
export declare class TerminalMarketService {
|
|
12
|
-
#private;
|
|
13
|
-
constructor(deps: PerpsPlatformDependencies);
|
|
14
|
-
/**
|
|
15
|
-
* Fetch markets from the Terminal API.
|
|
16
|
-
* Returns cached data when available and within TTL.
|
|
17
|
-
*
|
|
18
|
-
* @returns Object with mapped MarketInfo array and per-symbol metadata.
|
|
19
|
-
*/
|
|
20
|
-
fetchMarkets(): Promise<{
|
|
21
|
-
markets: MarketInfo[];
|
|
22
|
-
metadata: Map<string, TerminalAssetMetadata>;
|
|
23
|
-
}>;
|
|
24
|
-
/**
|
|
25
|
-
* Invalidate the internal cache so the next fetch hits the network.
|
|
26
|
-
*/
|
|
27
|
-
clearCache(): void;
|
|
28
|
-
/**
|
|
29
|
-
* Log a Terminal API error to Sentry without surfacing it to the user.
|
|
30
|
-
*
|
|
31
|
-
* @param error - The caught error.
|
|
32
|
-
* @param method - The calling method name for context.
|
|
33
|
-
*/
|
|
34
|
-
logError(error: unknown, method: string): void;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=TerminalMarketService.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TerminalMarketService.d.mts","sourceRoot":"","sources":["../../src/services/TerminalMarketService.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,UAAU,EACV,yBAAyB,EACzB,qBAAqB,EACtB,2BAAiB;AAsClB;;;;;;;;GAQG;AACH,qBAAa,qBAAqB;;gBAKpB,IAAI,EAAE,yBAAyB;IAI3C;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC;QAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;QACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;KAC9C,CAAC;IA2CF;;OAEG;IACH,UAAU,IAAI,IAAI;IAiHlB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAY/C"}
|