@metamask-previews/perps-controller 0.0.0-preview-ae46ab603 → 0.0.0-preview-e4aa1532
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 +11 -1
- package/dist/PerpsController.cjs +2224 -66
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +933 -79
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +933 -79
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +2221 -64
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/__mocks__/hyperliquidMock.cjs +68 -0
- package/dist/__mocks__/hyperliquidMock.cjs.map +1 -0
- package/dist/__mocks__/hyperliquidMock.d.cts +15 -0
- package/dist/__mocks__/hyperliquidMock.d.cts.map +1 -0
- package/dist/__mocks__/hyperliquidMock.d.mts +15 -0
- package/dist/__mocks__/hyperliquidMock.d.mts.map +1 -0
- package/dist/__mocks__/hyperliquidMock.mjs +65 -0
- package/dist/__mocks__/hyperliquidMock.mjs.map +1 -0
- package/dist/__mocks__/providerMocks.cjs +144 -0
- package/dist/__mocks__/providerMocks.cjs.map +1 -0
- package/dist/__mocks__/providerMocks.d.cts +44 -0
- package/dist/__mocks__/providerMocks.d.cts.map +1 -0
- package/dist/__mocks__/providerMocks.d.mts +44 -0
- package/dist/__mocks__/providerMocks.d.mts.map +1 -0
- package/dist/__mocks__/providerMocks.mjs +136 -0
- package/dist/__mocks__/providerMocks.mjs.map +1 -0
- package/dist/__mocks__/serviceMocks.cjs +187 -0
- package/dist/__mocks__/serviceMocks.cjs.map +1 -0
- package/dist/__mocks__/serviceMocks.d.cts +58 -0
- package/dist/__mocks__/serviceMocks.d.cts.map +1 -0
- package/dist/__mocks__/serviceMocks.d.mts +58 -0
- package/dist/__mocks__/serviceMocks.d.mts.map +1 -0
- package/dist/__mocks__/serviceMocks.mjs +180 -0
- package/dist/__mocks__/serviceMocks.mjs.map +1 -0
- package/dist/aggregation/SubscriptionMultiplexer.cjs +459 -0
- package/dist/aggregation/SubscriptionMultiplexer.cjs.map +1 -0
- package/dist/aggregation/SubscriptionMultiplexer.d.cts +222 -0
- package/dist/aggregation/SubscriptionMultiplexer.d.cts.map +1 -0
- package/dist/aggregation/SubscriptionMultiplexer.d.mts +222 -0
- package/dist/aggregation/SubscriptionMultiplexer.d.mts.map +1 -0
- package/dist/aggregation/SubscriptionMultiplexer.mjs +455 -0
- package/dist/aggregation/SubscriptionMultiplexer.mjs.map +1 -0
- package/dist/aggregation/index.cjs +9 -0
- package/dist/aggregation/index.cjs.map +1 -0
- package/dist/aggregation/index.d.cts +6 -0
- package/dist/aggregation/index.d.cts.map +1 -0
- package/dist/aggregation/index.d.mts +6 -0
- package/dist/aggregation/index.d.mts.map +1 -0
- package/dist/aggregation/index.mjs +5 -0
- package/dist/aggregation/index.mjs.map +1 -0
- package/dist/constants/eventNames.cjs +117 -0
- package/dist/constants/eventNames.cjs.map +1 -0
- package/dist/constants/eventNames.d.cts +106 -0
- package/dist/constants/eventNames.d.cts.map +1 -0
- package/dist/constants/eventNames.d.mts +106 -0
- package/dist/constants/eventNames.d.mts.map +1 -0
- package/dist/constants/eventNames.mjs +114 -0
- package/dist/constants/eventNames.mjs.map +1 -0
- package/dist/constants/hyperLiquidConfig.cjs +366 -0
- package/dist/constants/hyperLiquidConfig.cjs.map +1 -0
- package/dist/constants/hyperLiquidConfig.d.cts +276 -0
- package/dist/constants/hyperLiquidConfig.d.cts.map +1 -0
- package/dist/constants/hyperLiquidConfig.d.mts +276 -0
- package/dist/constants/hyperLiquidConfig.d.mts.map +1 -0
- package/dist/constants/hyperLiquidConfig.mjs +357 -0
- package/dist/constants/hyperLiquidConfig.mjs.map +1 -0
- package/dist/constants/index.cjs +23 -0
- package/dist/constants/index.cjs.map +1 -0
- package/dist/constants/index.d.cts +7 -0
- package/dist/constants/index.d.cts.map +1 -0
- package/dist/constants/index.d.mts +7 -0
- package/dist/constants/index.d.mts.map +1 -0
- package/dist/constants/index.mjs +7 -0
- package/dist/constants/index.mjs.map +1 -0
- package/dist/constants/orderTypes.cjs +31 -0
- package/dist/constants/orderTypes.cjs.map +1 -0
- package/dist/constants/orderTypes.d.cts +19 -0
- package/dist/constants/orderTypes.d.cts.map +1 -0
- package/dist/constants/orderTypes.d.mts +19 -0
- package/dist/constants/orderTypes.d.mts.map +1 -0
- package/dist/constants/orderTypes.mjs +27 -0
- package/dist/constants/orderTypes.mjs.map +1 -0
- package/dist/constants/performanceMetrics.cjs +61 -0
- package/dist/constants/performanceMetrics.cjs.map +1 -0
- package/dist/constants/performanceMetrics.d.cts +44 -0
- package/dist/constants/performanceMetrics.d.cts.map +1 -0
- package/dist/constants/performanceMetrics.d.mts +44 -0
- package/dist/constants/performanceMetrics.d.mts.map +1 -0
- package/dist/constants/performanceMetrics.mjs +58 -0
- package/dist/constants/performanceMetrics.mjs.map +1 -0
- package/dist/constants/perpsConfig.cjs +461 -0
- package/dist/constants/perpsConfig.cjs.map +1 -0
- package/dist/constants/perpsConfig.d.cts +343 -0
- package/dist/constants/perpsConfig.d.cts.map +1 -0
- package/dist/constants/perpsConfig.d.mts +343 -0
- package/dist/constants/perpsConfig.d.mts.map +1 -0
- package/dist/constants/perpsConfig.mjs +458 -0
- package/dist/constants/perpsConfig.mjs.map +1 -0
- package/dist/constants/perpsErrorCodes.cjs +79 -0
- package/dist/constants/perpsErrorCodes.cjs.map +1 -0
- package/dist/constants/perpsErrorCodes.d.cts +64 -0
- package/dist/constants/perpsErrorCodes.d.cts.map +1 -0
- package/dist/constants/perpsErrorCodes.d.mts +64 -0
- package/dist/constants/perpsErrorCodes.d.mts.map +1 -0
- package/dist/constants/perpsErrorCodes.mjs +76 -0
- package/dist/constants/perpsErrorCodes.mjs.map +1 -0
- package/dist/index.cjs +32 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +9 -1
- package/dist/index.mjs.map +1 -1
- package/dist/platform-services/HyperLiquidClientService.cjs +857 -0
- package/dist/platform-services/HyperLiquidClientService.cjs.map +1 -0
- package/dist/platform-services/HyperLiquidClientService.d.cts +263 -0
- package/dist/platform-services/HyperLiquidClientService.d.cts.map +1 -0
- package/dist/platform-services/HyperLiquidClientService.d.mts +263 -0
- package/dist/platform-services/HyperLiquidClientService.d.mts.map +1 -0
- package/dist/platform-services/HyperLiquidClientService.mjs +853 -0
- package/dist/platform-services/HyperLiquidClientService.mjs.map +1 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.cjs +2170 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.cjs.map +1 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.d.cts +424 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.d.cts.map +1 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.d.mts +424 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.d.mts.map +1 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.mjs +2166 -0
- package/dist/platform-services/HyperLiquidSubscriptionService.mjs.map +1 -0
- package/dist/platform-services/HyperLiquidWalletService.cjs +140 -0
- package/dist/platform-services/HyperLiquidWalletService.cjs.map +1 -0
- package/dist/platform-services/HyperLiquidWalletService.d.cts +78 -0
- package/dist/platform-services/HyperLiquidWalletService.d.cts.map +1 -0
- package/dist/platform-services/HyperLiquidWalletService.d.mts +78 -0
- package/dist/platform-services/HyperLiquidWalletService.d.mts.map +1 -0
- package/dist/platform-services/HyperLiquidWalletService.mjs +136 -0
- package/dist/platform-services/HyperLiquidWalletService.mjs.map +1 -0
- package/dist/providers/AggregatedPerpsProvider.cjs +777 -0
- package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -0
- package/dist/providers/AggregatedPerpsProvider.d.cts +466 -0
- package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -0
- package/dist/providers/AggregatedPerpsProvider.d.mts +466 -0
- package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -0
- package/dist/providers/AggregatedPerpsProvider.mjs +773 -0
- package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -0
- package/dist/providers/HyperLiquidProvider.cjs +5172 -0
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -0
- package/dist/providers/HyperLiquidProvider.d.cts +881 -0
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -0
- package/dist/providers/HyperLiquidProvider.d.mts +881 -0
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -0
- package/dist/providers/HyperLiquidProvider.mjs +5168 -0
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -0
- package/dist/providers/index.cjs +11 -0
- package/dist/providers/index.cjs.map +1 -0
- package/dist/providers/index.d.cts +6 -0
- package/dist/providers/index.d.cts.map +1 -0
- package/dist/providers/index.d.mts +6 -0
- package/dist/providers/index.d.mts.map +1 -0
- package/dist/providers/index.mjs +6 -0
- package/dist/providers/index.mjs.map +1 -0
- package/dist/routing/ProviderRouter.cjs +148 -0
- package/dist/routing/ProviderRouter.cjs.map +1 -0
- package/dist/routing/ProviderRouter.d.cts +124 -0
- package/dist/routing/ProviderRouter.d.cts.map +1 -0
- package/dist/routing/ProviderRouter.d.mts +124 -0
- package/dist/routing/ProviderRouter.d.mts.map +1 -0
- package/dist/routing/ProviderRouter.mjs +144 -0
- package/dist/routing/ProviderRouter.mjs.map +1 -0
- package/dist/routing/index.cjs +9 -0
- package/dist/routing/index.cjs.map +1 -0
- package/dist/routing/index.d.cts +6 -0
- package/dist/routing/index.d.cts.map +1 -0
- package/dist/routing/index.d.mts +6 -0
- package/dist/routing/index.d.mts.map +1 -0
- package/dist/routing/index.mjs +5 -0
- package/dist/routing/index.mjs.map +1 -0
- package/dist/selectors.cjs +161 -0
- package/dist/selectors.cjs.map +1 -0
- package/dist/selectors.d.cts +345 -0
- package/dist/selectors.d.cts.map +1 -0
- package/dist/selectors.d.mts +345 -0
- package/dist/selectors.d.mts.map +1 -0
- package/dist/selectors.mjs +153 -0
- package/dist/selectors.mjs.map +1 -0
- package/dist/services/AccountService.cjs +313 -0
- package/dist/services/AccountService.cjs.map +1 -0
- package/dist/services/AccountService.d.cts +53 -0
- package/dist/services/AccountService.d.cts.map +1 -0
- package/dist/services/AccountService.d.mts +53 -0
- package/dist/services/AccountService.d.mts.map +1 -0
- package/dist/services/AccountService.mjs +309 -0
- package/dist/services/AccountService.mjs.map +1 -0
- package/dist/services/DataLakeService.cjs +219 -0
- package/dist/services/DataLakeService.cjs.map +1 -0
- package/dist/services/DataLakeService.d.cts +49 -0
- package/dist/services/DataLakeService.d.cts.map +1 -0
- package/dist/services/DataLakeService.d.mts +49 -0
- package/dist/services/DataLakeService.d.mts.map +1 -0
- package/dist/services/DataLakeService.mjs +215 -0
- package/dist/services/DataLakeService.mjs.map +1 -0
- package/dist/services/DepositService.cjs +96 -0
- package/dist/services/DepositService.cjs.map +1 -0
- package/dist/services/DepositService.d.cts +37 -0
- package/dist/services/DepositService.d.cts.map +1 -0
- package/dist/services/DepositService.d.mts +37 -0
- package/dist/services/DepositService.d.mts.map +1 -0
- package/dist/services/DepositService.mjs +92 -0
- package/dist/services/DepositService.mjs.map +1 -0
- package/dist/services/EligibilityService.cjs +156 -0
- package/dist/services/EligibilityService.cjs.map +1 -0
- package/dist/services/EligibilityService.d.cts +48 -0
- package/dist/services/EligibilityService.d.cts.map +1 -0
- package/dist/services/EligibilityService.d.mts +48 -0
- package/dist/services/EligibilityService.d.mts.map +1 -0
- package/dist/services/EligibilityService.mjs +152 -0
- package/dist/services/EligibilityService.mjs.map +1 -0
- package/dist/services/FeatureFlagConfigurationService.cjs +258 -0
- package/dist/services/FeatureFlagConfigurationService.cjs.map +1 -0
- package/dist/services/FeatureFlagConfigurationService.d.cts +100 -0
- package/dist/services/FeatureFlagConfigurationService.d.cts.map +1 -0
- package/dist/services/FeatureFlagConfigurationService.d.mts +100 -0
- package/dist/services/FeatureFlagConfigurationService.d.mts.map +1 -0
- package/dist/services/FeatureFlagConfigurationService.mjs +254 -0
- package/dist/services/FeatureFlagConfigurationService.mjs.map +1 -0
- package/dist/services/MarketDataService.cjs +875 -0
- package/dist/services/MarketDataService.cjs.map +1 -0
- package/dist/services/MarketDataService.d.cts +289 -0
- package/dist/services/MarketDataService.d.cts.map +1 -0
- package/dist/services/MarketDataService.d.mts +289 -0
- package/dist/services/MarketDataService.d.mts.map +1 -0
- package/dist/services/MarketDataService.mjs +871 -0
- package/dist/services/MarketDataService.mjs.map +1 -0
- package/dist/services/RewardsIntegrationService.cjs +94 -0
- package/dist/services/RewardsIntegrationService.cjs.map +1 -0
- package/dist/services/RewardsIntegrationService.d.cts +30 -0
- package/dist/services/RewardsIntegrationService.d.cts.map +1 -0
- package/dist/services/RewardsIntegrationService.d.mts +30 -0
- package/dist/services/RewardsIntegrationService.d.mts.map +1 -0
- package/dist/services/RewardsIntegrationService.mjs +90 -0
- package/dist/services/RewardsIntegrationService.mjs.map +1 -0
- package/dist/services/ServiceContext.cjs +3 -0
- package/dist/services/ServiceContext.cjs.map +1 -0
- package/dist/services/ServiceContext.d.cts +110 -0
- package/dist/services/ServiceContext.d.cts.map +1 -0
- package/dist/services/ServiceContext.d.mts +110 -0
- package/dist/services/ServiceContext.d.mts.map +1 -0
- package/dist/services/ServiceContext.mjs +2 -0
- package/dist/services/ServiceContext.mjs.map +1 -0
- package/dist/services/TradingService.cjs +1481 -0
- package/dist/services/TradingService.cjs.map +1 -0
- package/dist/services/TradingService.d.cts +308 -0
- package/dist/services/TradingService.d.cts.map +1 -0
- package/dist/services/TradingService.d.mts +308 -0
- package/dist/services/TradingService.d.mts.map +1 -0
- package/dist/services/TradingService.mjs +1477 -0
- package/dist/services/TradingService.mjs.map +1 -0
- package/dist/services/index.cjs +26 -0
- package/dist/services/index.cjs.map +1 -0
- package/dist/services/index.d.cts +11 -0
- package/dist/services/index.d.cts.map +1 -0
- package/dist/services/index.d.mts +11 -0
- package/dist/services/index.d.mts.map +1 -0
- package/dist/services/index.mjs +10 -0
- package/dist/services/index.mjs.map +1 -0
- package/dist/services/utils.cjs +16 -0
- package/dist/services/utils.cjs.map +1 -0
- package/dist/services/utils.d.cts +8 -0
- package/dist/services/utils.d.cts.map +1 -0
- package/dist/services/utils.d.mts +8 -0
- package/dist/services/utils.d.mts.map +1 -0
- package/dist/services/utils.mjs +12 -0
- package/dist/services/utils.mjs.map +1 -0
- package/dist/types/chart.cjs +42 -0
- package/dist/types/chart.cjs.map +1 -0
- package/dist/types/chart.d.cts +62 -0
- package/dist/types/chart.d.cts.map +1 -0
- package/dist/types/chart.d.mts +62 -0
- package/dist/types/chart.d.mts.map +1 -0
- package/dist/types/chart.mjs +39 -0
- package/dist/types/chart.mjs.map +1 -0
- package/dist/types/hyperliquid-types.cjs +3 -0
- package/dist/types/hyperliquid-types.cjs.map +1 -0
- package/dist/types/hyperliquid-types.d.cts +52 -0
- package/dist/types/hyperliquid-types.d.cts.map +1 -0
- package/dist/types/hyperliquid-types.d.mts +52 -0
- package/dist/types/hyperliquid-types.d.mts.map +1 -0
- package/dist/types/hyperliquid-types.mjs +2 -0
- package/dist/types/hyperliquid-types.mjs.map +1 -0
- package/dist/types/index.cjs +96 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +1153 -0
- package/dist/types/index.d.cts.map +1 -0
- package/dist/types/index.d.mts +1153 -0
- package/dist/types/index.d.mts.map +1 -0
- package/dist/types/index.mjs +79 -0
- package/dist/types/index.mjs.map +1 -0
- package/dist/types/transactionTypes.cjs +28 -0
- package/dist/types/transactionTypes.cjs.map +1 -0
- package/dist/types/transactionTypes.d.cts +64 -0
- package/dist/types/transactionTypes.d.cts.map +1 -0
- package/dist/types/transactionTypes.d.mts +64 -0
- package/dist/types/transactionTypes.d.mts.map +1 -0
- package/dist/types/transactionTypes.mjs +23 -0
- package/dist/types/transactionTypes.mjs.map +1 -0
- package/dist/utils/accountUtils.cjs +65 -0
- package/dist/utils/accountUtils.cjs.map +1 -0
- package/dist/utils/accountUtils.d.cts +26 -0
- package/dist/utils/accountUtils.d.cts.map +1 -0
- package/dist/utils/accountUtils.d.mts +26 -0
- package/dist/utils/accountUtils.d.mts.map +1 -0
- package/dist/utils/accountUtils.mjs +61 -0
- package/dist/utils/accountUtils.mjs.map +1 -0
- package/dist/utils/amountConversion.cjs +61 -0
- package/dist/utils/amountConversion.cjs.map +1 -0
- package/dist/utils/amountConversion.d.cts +16 -0
- package/dist/utils/amountConversion.d.cts.map +1 -0
- package/dist/utils/amountConversion.d.mts +16 -0
- package/dist/utils/amountConversion.d.mts.map +1 -0
- package/dist/utils/amountConversion.mjs +54 -0
- package/dist/utils/amountConversion.mjs.map +1 -0
- package/dist/utils/chartUtils.cjs +98 -0
- package/dist/utils/chartUtils.cjs.map +1 -0
- package/dist/utils/chartUtils.d.cts +14 -0
- package/dist/utils/chartUtils.d.cts.map +1 -0
- package/dist/utils/chartUtils.d.mts +14 -0
- package/dist/utils/chartUtils.d.mts.map +1 -0
- package/dist/utils/chartUtils.mjs +94 -0
- package/dist/utils/chartUtils.mjs.map +1 -0
- package/dist/utils/errorUtils.cjs +22 -0
- package/dist/utils/errorUtils.cjs.map +1 -0
- package/dist/utils/errorUtils.d.cts +13 -0
- package/dist/utils/errorUtils.d.cts.map +1 -0
- package/dist/utils/errorUtils.d.mts +13 -0
- package/dist/utils/errorUtils.d.mts.map +1 -0
- package/dist/utils/errorUtils.mjs +18 -0
- package/dist/utils/errorUtils.mjs.map +1 -0
- package/dist/utils/formatUtils.cjs +987 -0
- package/dist/utils/formatUtils.cjs.map +1 -0
- package/dist/utils/formatUtils.d.cts +387 -0
- package/dist/utils/formatUtils.d.cts.map +1 -0
- package/dist/utils/formatUtils.d.mts +387 -0
- package/dist/utils/formatUtils.d.mts.map +1 -0
- package/dist/utils/formatUtils.mjs +966 -0
- package/dist/utils/formatUtils.mjs.map +1 -0
- package/dist/utils/hyperLiquidAdapter.cjs +454 -0
- package/dist/utils/hyperLiquidAdapter.cjs.map +1 -0
- package/dist/utils/hyperLiquidAdapter.d.cts +158 -0
- package/dist/utils/hyperLiquidAdapter.d.cts.map +1 -0
- package/dist/utils/hyperLiquidAdapter.d.mts +158 -0
- package/dist/utils/hyperLiquidAdapter.d.mts.map +1 -0
- package/dist/utils/hyperLiquidAdapter.mjs +439 -0
- package/dist/utils/hyperLiquidAdapter.mjs.map +1 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.cjs +89 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.cjs.map +1 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.d.cts +58 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.d.cts.map +1 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.d.mts +58 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.d.mts.map +1 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.mjs +84 -0
- package/dist/utils/hyperLiquidOrderBookProcessor.mjs.map +1 -0
- package/dist/utils/hyperLiquidValidation.cjs +426 -0
- package/dist/utils/hyperLiquidValidation.cjs.map +1 -0
- package/dist/utils/hyperLiquidValidation.d.cts +143 -0
- package/dist/utils/hyperLiquidValidation.d.cts.map +1 -0
- package/dist/utils/hyperLiquidValidation.d.mts +143 -0
- package/dist/utils/hyperLiquidValidation.d.mts.map +1 -0
- package/dist/utils/hyperLiquidValidation.mjs +413 -0
- package/dist/utils/hyperLiquidValidation.mjs.map +1 -0
- package/dist/utils/idUtils.cjs +50 -0
- package/dist/utils/idUtils.cjs.map +1 -0
- package/dist/utils/idUtils.d.cts +38 -0
- package/dist/utils/idUtils.d.cts.map +1 -0
- package/dist/utils/idUtils.d.mts +38 -0
- package/dist/utils/idUtils.d.mts.map +1 -0
- package/dist/utils/idUtils.mjs +42 -0
- package/dist/utils/idUtils.mjs.map +1 -0
- package/dist/utils/marginUtils.cjs +137 -0
- package/dist/utils/marginUtils.cjs.map +1 -0
- package/dist/utils/marginUtils.d.cts +64 -0
- package/dist/utils/marginUtils.d.cts.map +1 -0
- package/dist/utils/marginUtils.d.mts +64 -0
- package/dist/utils/marginUtils.d.mts.map +1 -0
- package/dist/utils/marginUtils.mjs +131 -0
- package/dist/utils/marginUtils.mjs.map +1 -0
- package/dist/utils/marketDataTransform.cjs +227 -0
- package/dist/utils/marketDataTransform.cjs.map +1 -0
- package/dist/utils/marketDataTransform.d.cts +45 -0
- package/dist/utils/marketDataTransform.d.cts.map +1 -0
- package/dist/utils/marketDataTransform.d.mts +45 -0
- package/dist/utils/marketDataTransform.d.mts.map +1 -0
- package/dist/utils/marketDataTransform.mjs +220 -0
- package/dist/utils/marketDataTransform.mjs.map +1 -0
- package/dist/utils/marketUtils.cjs +420 -0
- package/dist/utils/marketUtils.cjs.map +1 -0
- package/dist/utils/marketUtils.d.cts +227 -0
- package/dist/utils/marketUtils.d.cts.map +1 -0
- package/dist/utils/marketUtils.d.mts +227 -0
- package/dist/utils/marketUtils.d.mts.map +1 -0
- package/dist/utils/marketUtils.mjs +404 -0
- package/dist/utils/marketUtils.mjs.map +1 -0
- package/dist/utils/orderBookGrouping.cjs +151 -0
- package/dist/utils/orderBookGrouping.cjs.map +1 -0
- package/dist/utils/orderBookGrouping.d.cts +76 -0
- package/dist/utils/orderBookGrouping.d.cts.map +1 -0
- package/dist/utils/orderBookGrouping.d.mts +76 -0
- package/dist/utils/orderBookGrouping.d.mts.map +1 -0
- package/dist/utils/orderBookGrouping.mjs +143 -0
- package/dist/utils/orderBookGrouping.mjs.map +1 -0
- package/dist/utils/orderCalculations.cjs +283 -0
- package/dist/utils/orderCalculations.cjs.map +1 -0
- package/dist/utils/orderCalculations.d.cts +107 -0
- package/dist/utils/orderCalculations.d.cts.map +1 -0
- package/dist/utils/orderCalculations.d.mts +107 -0
- package/dist/utils/orderCalculations.d.mts.map +1 -0
- package/dist/utils/orderCalculations.mjs +274 -0
- package/dist/utils/orderCalculations.mjs.map +1 -0
- package/dist/utils/orderUtils.cjs +159 -0
- package/dist/utils/orderUtils.cjs.map +1 -0
- package/dist/utils/orderUtils.d.cts +66 -0
- package/dist/utils/orderUtils.d.cts.map +1 -0
- package/dist/utils/orderUtils.d.mts +66 -0
- package/dist/utils/orderUtils.d.mts.map +1 -0
- package/dist/utils/orderUtils.mjs +151 -0
- package/dist/utils/orderUtils.mjs.map +1 -0
- package/dist/utils/pnlCalculations.cjs +107 -0
- package/dist/utils/pnlCalculations.cjs.map +1 -0
- package/dist/utils/pnlCalculations.d.cts +79 -0
- package/dist/utils/pnlCalculations.d.cts.map +1 -0
- package/dist/utils/pnlCalculations.d.mts +79 -0
- package/dist/utils/pnlCalculations.d.mts.map +1 -0
- package/dist/utils/pnlCalculations.mjs +97 -0
- package/dist/utils/pnlCalculations.mjs.map +1 -0
- package/dist/utils/positionCalculations.cjs +176 -0
- package/dist/utils/positionCalculations.cjs.map +1 -0
- package/dist/utils/positionCalculations.d.cts +85 -0
- package/dist/utils/positionCalculations.d.cts.map +1 -0
- package/dist/utils/positionCalculations.d.mts +85 -0
- package/dist/utils/positionCalculations.d.mts.map +1 -0
- package/dist/utils/positionCalculations.mjs +165 -0
- package/dist/utils/positionCalculations.mjs.map +1 -0
- package/dist/utils/sortMarkets.cjs +88 -0
- package/dist/utils/sortMarkets.cjs.map +1 -0
- package/dist/utils/sortMarkets.d.cts +21 -0
- package/dist/utils/sortMarkets.d.cts.map +1 -0
- package/dist/utils/sortMarkets.d.mts +21 -0
- package/dist/utils/sortMarkets.d.mts.map +1 -0
- package/dist/utils/sortMarkets.mjs +84 -0
- package/dist/utils/sortMarkets.mjs.map +1 -0
- package/dist/utils/standaloneInfoClient.cjs +34 -0
- package/dist/utils/standaloneInfoClient.cjs.map +1 -0
- package/dist/utils/standaloneInfoClient.d.cts +31 -0
- package/dist/utils/standaloneInfoClient.d.cts.map +1 -0
- package/dist/utils/standaloneInfoClient.d.mts +31 -0
- package/dist/utils/standaloneInfoClient.d.mts.map +1 -0
- package/dist/utils/standaloneInfoClient.mjs +30 -0
- package/dist/utils/standaloneInfoClient.mjs.map +1 -0
- package/dist/utils/stringParseUtils.cjs +49 -0
- package/dist/utils/stringParseUtils.cjs.map +1 -0
- package/dist/utils/stringParseUtils.d.cts +35 -0
- package/dist/utils/stringParseUtils.d.cts.map +1 -0
- package/dist/utils/stringParseUtils.d.mts +35 -0
- package/dist/utils/stringParseUtils.d.mts.map +1 -0
- package/dist/utils/stringParseUtils.mjs +44 -0
- package/dist/utils/stringParseUtils.mjs.map +1 -0
- package/dist/utils/time.cjs +37 -0
- package/dist/utils/time.cjs.map +1 -0
- package/dist/utils/time.d.cts +17 -0
- package/dist/utils/time.d.cts.map +1 -0
- package/dist/utils/time.d.mts +17 -0
- package/dist/utils/time.d.mts.map +1 -0
- package/dist/utils/time.mjs +33 -0
- package/dist/utils/time.mjs.map +1 -0
- package/dist/utils/tpslValidation.cjs +505 -0
- package/dist/utils/tpslValidation.cjs.map +1 -0
- package/dist/utils/tpslValidation.d.cts +182 -0
- package/dist/utils/tpslValidation.d.cts.map +1 -0
- package/dist/utils/tpslValidation.d.mts +182 -0
- package/dist/utils/tpslValidation.d.mts.map +1 -0
- package/dist/utils/tpslValidation.mjs +482 -0
- package/dist/utils/tpslValidation.mjs.map +1 -0
- package/dist/utils/transactionUtils.cjs +36 -0
- package/dist/utils/transactionUtils.cjs.map +1 -0
- package/dist/utils/transactionUtils.d.cts +17 -0
- package/dist/utils/transactionUtils.d.cts.map +1 -0
- package/dist/utils/transactionUtils.d.mts +17 -0
- package/dist/utils/transactionUtils.d.mts.map +1 -0
- package/dist/utils/transactionUtils.mjs +32 -0
- package/dist/utils/transactionUtils.mjs.map +1 -0
- package/dist/utils/wait.cjs +12 -0
- package/dist/utils/wait.cjs.map +1 -0
- package/dist/utils/wait.d.cts +8 -0
- package/dist/utils/wait.d.cts.map +1 -0
- package/dist/utils/wait.d.mts +8 -0
- package/dist/utils/wait.d.mts.map +1 -0
- package/dist/utils/wait.mjs +8 -0
- package/dist/utils/wait.mjs.map +1 -0
- package/package.json +19 -4
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAssetIconUrls = exports.getAssetIconUrl = exports.filterMarketsByQuery = exports.getMarketBadgeType = exports.calculate24hHighLow = exports.calculateFundingCountdown = exports.getPerpsDexFromSymbol = exports.getPerpsDisplaySymbol = exports.shouldIncludeMarket = exports.matchesMarketPattern = exports.compileMarketPattern = exports.validateMarketPattern = exports.escapeRegex = void 0;
|
|
4
|
+
const hyperLiquidConfig_1 = require("../constants/hyperLiquidConfig.cjs");
|
|
5
|
+
/**
|
|
6
|
+
* Maximum length for market filter patterns (prevents DoS attacks)
|
|
7
|
+
*/
|
|
8
|
+
const MAX_MARKET_PATTERN_LENGTH = 100;
|
|
9
|
+
/**
|
|
10
|
+
* Escape special regex characters in a string
|
|
11
|
+
*
|
|
12
|
+
* @param str - String to escape
|
|
13
|
+
* @returns Escaped string safe for regex
|
|
14
|
+
*/
|
|
15
|
+
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
16
|
+
exports.escapeRegex = escapeRegex;
|
|
17
|
+
/**
|
|
18
|
+
* Validate market filter pattern for safety
|
|
19
|
+
* Prevents regex DoS attacks from malicious patterns
|
|
20
|
+
*
|
|
21
|
+
* @param pattern - Pattern to validate
|
|
22
|
+
* @returns true if pattern is safe
|
|
23
|
+
* @throws Error if pattern is unsafe
|
|
24
|
+
*
|
|
25
|
+
* @example Valid patterns
|
|
26
|
+
* validateMarketPattern("BTC") // → true
|
|
27
|
+
* validateMarketPattern("xyz:TSLA") // → true
|
|
28
|
+
* validateMarketPattern("xyz:*") // → true
|
|
29
|
+
*
|
|
30
|
+
* @example Invalid patterns
|
|
31
|
+
* validateMarketPattern("") // → throws Error
|
|
32
|
+
* validateMarketPattern("xyz:.*") // → throws Error (regex chars)
|
|
33
|
+
* validateMarketPattern("BTC#SCAM") // → throws Error (invalid char)
|
|
34
|
+
*/
|
|
35
|
+
const validateMarketPattern = (pattern) => {
|
|
36
|
+
// Reject empty patterns
|
|
37
|
+
if (!pattern || pattern.trim().length === 0) {
|
|
38
|
+
throw new Error('Market pattern cannot be empty');
|
|
39
|
+
}
|
|
40
|
+
// Trim whitespace and normalize the pattern
|
|
41
|
+
const normalizedPattern = pattern.trim();
|
|
42
|
+
// Reject patterns that are too long (potential DoS)
|
|
43
|
+
if (normalizedPattern.length > MAX_MARKET_PATTERN_LENGTH) {
|
|
44
|
+
throw new Error(`Market pattern exceeds maximum length (${MAX_MARKET_PATTERN_LENGTH} chars): ${normalizedPattern}`);
|
|
45
|
+
}
|
|
46
|
+
// Reject patterns with suspicious regex control characters
|
|
47
|
+
// Allow only colon and asterisk for our pattern syntax
|
|
48
|
+
const dangerousChars = /[\\()[\]{}^$+?.|]/u;
|
|
49
|
+
if (dangerousChars.test(normalizedPattern)) {
|
|
50
|
+
throw new Error(`Market pattern contains invalid regex characters: ${normalizedPattern}`);
|
|
51
|
+
}
|
|
52
|
+
// Allow only: alphanumeric, colon, hyphen, underscore, asterisk
|
|
53
|
+
const validPattern = /^[a-zA-Z0-9:_\-*]+$/u;
|
|
54
|
+
if (!validPattern.test(normalizedPattern)) {
|
|
55
|
+
throw new Error(`Market pattern contains invalid characters: ${normalizedPattern}`);
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
59
|
+
exports.validateMarketPattern = validateMarketPattern;
|
|
60
|
+
/**
|
|
61
|
+
* Compile market filter pattern into optimized matcher
|
|
62
|
+
* Supports wildcards ("xyz:*"), DEX shorthand ("xyz"), and exact matches ("xyz:TSLA")
|
|
63
|
+
*
|
|
64
|
+
* Note: Main DEX markets (no prefix) don't need filtering - they're always included.
|
|
65
|
+
* Patterns without colons are treated as HIP-3 DEX shorthand.
|
|
66
|
+
*
|
|
67
|
+
* @param pattern - Pattern string (e.g., "xyz:*", "xyz:TSLA", "xyz")
|
|
68
|
+
* @returns Compiled matcher (RegExp for wildcards/shorthand, string for exact match)
|
|
69
|
+
*
|
|
70
|
+
* @example Wildcard - matches all markets from a DEX
|
|
71
|
+
* compileMarketPattern("xyz:*") // → /^xyz:/
|
|
72
|
+
*
|
|
73
|
+
* @example DEX shorthand - equivalent to wildcard
|
|
74
|
+
* compileMarketPattern("xyz") // → /^xyz:/ (matches all xyz markets)
|
|
75
|
+
*
|
|
76
|
+
* @example Exact match - matches specific market
|
|
77
|
+
* compileMarketPattern("xyz:TSLA") // → "xyz:TSLA"
|
|
78
|
+
*/
|
|
79
|
+
const compileMarketPattern = (pattern) => {
|
|
80
|
+
// Trim and validate pattern before compilation to prevent regex DoS
|
|
81
|
+
const normalizedPattern = pattern.trim();
|
|
82
|
+
(0, exports.validateMarketPattern)(normalizedPattern);
|
|
83
|
+
if (normalizedPattern.endsWith(':*')) {
|
|
84
|
+
// Wildcard: "xyz:*" → regex /^xyz:/
|
|
85
|
+
const prefix = normalizedPattern.slice(0, -2);
|
|
86
|
+
return new RegExp(`^${(0, exports.escapeRegex)(prefix)}:`, 'u');
|
|
87
|
+
}
|
|
88
|
+
if (!normalizedPattern.includes(':')) {
|
|
89
|
+
// DEX shorthand: "xyz" → regex /^xyz:/
|
|
90
|
+
return new RegExp(`^${(0, exports.escapeRegex)(normalizedPattern)}:`, 'u');
|
|
91
|
+
}
|
|
92
|
+
// Exact match: just use string (fastest)
|
|
93
|
+
return normalizedPattern;
|
|
94
|
+
};
|
|
95
|
+
exports.compileMarketPattern = compileMarketPattern;
|
|
96
|
+
/**
|
|
97
|
+
* Check if a symbol matches a compiled pattern matcher
|
|
98
|
+
*
|
|
99
|
+
* @param symbol - Market symbol (e.g., "BTC", "xyz:TSLA")
|
|
100
|
+
* @param matcher - Compiled matcher (string or RegExp)
|
|
101
|
+
* @returns true if symbol matches the pattern
|
|
102
|
+
*/
|
|
103
|
+
const matchesMarketPattern = (symbol, matcher) => {
|
|
104
|
+
if (typeof matcher === 'string') {
|
|
105
|
+
// Exact match - fastest
|
|
106
|
+
return symbol === matcher;
|
|
107
|
+
}
|
|
108
|
+
// RegExp match - still very fast
|
|
109
|
+
return matcher.test(symbol);
|
|
110
|
+
};
|
|
111
|
+
exports.matchesMarketPattern = matchesMarketPattern;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a market should be included based on HIP-3 master switch and whitelist/blacklist patterns
|
|
114
|
+
* Main DEX markets (null dex) are ALWAYS included (no filtering)
|
|
115
|
+
*
|
|
116
|
+
* Logic: Check master switch → apply whitelist (if non-empty) → apply blacklist
|
|
117
|
+
*
|
|
118
|
+
* @param symbol - Market symbol (e.g., "BTC", "xyz:TSLA")
|
|
119
|
+
* @param dex - DEX identifier (null for main DEX, "xyz" for HIP-3 DEX)
|
|
120
|
+
* @param hip3Enabled - Master switch for HIP-3 markets (false = block all HIP-3)
|
|
121
|
+
* @param compiledEnabledPatterns - Pre-compiled whitelist patterns (empty = allow all)
|
|
122
|
+
* @param compiledBlockedPatterns - Pre-compiled blacklist patterns (empty = block none)
|
|
123
|
+
* @returns true if market should be shown to users
|
|
124
|
+
*
|
|
125
|
+
* @example Main DEX market (always included)
|
|
126
|
+
* shouldIncludeMarket("BTC", null, true, [...], [...]) // → true
|
|
127
|
+
*
|
|
128
|
+
* @example HIP-3 when master switch is OFF
|
|
129
|
+
* shouldIncludeMarket("xyz:TSLA", "xyz", false, [...], [...]) // → false (HIP-3 disabled)
|
|
130
|
+
*
|
|
131
|
+
* @example HIP-3 with empty whitelist (discovery mode)
|
|
132
|
+
* shouldIncludeMarket("xyz:TSLA", "xyz", true, [], []) // → true (allow all)
|
|
133
|
+
*
|
|
134
|
+
* @example HIP-3 with whitelist
|
|
135
|
+
* shouldIncludeMarket("xyz:TSLA", "xyz", true,
|
|
136
|
+
* [{pattern: "xyz:*", matcher: /^xyz:/}], []) // → true (matches whitelist)
|
|
137
|
+
*
|
|
138
|
+
* @example HIP-3 with blacklist
|
|
139
|
+
* shouldIncludeMarket("xyz:SCAM", "xyz", true, [],
|
|
140
|
+
* [{pattern: "xyz:SCAM", matcher: "xyz:SCAM"}]) // → false (blocked)
|
|
141
|
+
*/
|
|
142
|
+
const shouldIncludeMarket = (symbol, dex, hip3Enabled, compiledEnabledPatterns, compiledBlockedPatterns) => {
|
|
143
|
+
// ALWAYS include main DEX markets (no filtering)
|
|
144
|
+
if (dex === null) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
// Enforce HIP-3 master switch: if disabled, block ALL HIP-3 markets
|
|
148
|
+
if (!hip3Enabled) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
// Step 1: Apply whitelist only if non-empty
|
|
152
|
+
if (compiledEnabledPatterns.length > 0) {
|
|
153
|
+
const whitelisted = compiledEnabledPatterns.some(({ matcher }) => (0, exports.matchesMarketPattern)(symbol, matcher));
|
|
154
|
+
if (!whitelisted) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Step 2: Apply blacklist ONLY if non-empty (early return optimization)
|
|
159
|
+
if (compiledBlockedPatterns.length === 0) {
|
|
160
|
+
return true; // No blacklist to check - accept immediately
|
|
161
|
+
}
|
|
162
|
+
// Only reach here if blacklist has values
|
|
163
|
+
const blacklisted = compiledBlockedPatterns.some(({ matcher }) => (0, exports.matchesMarketPattern)(symbol, matcher));
|
|
164
|
+
return !blacklisted;
|
|
165
|
+
};
|
|
166
|
+
exports.shouldIncludeMarket = shouldIncludeMarket;
|
|
167
|
+
/**
|
|
168
|
+
* Extract the display symbol from a full symbol string
|
|
169
|
+
* Strips DEX prefix for HIP-3 markets (e.g., "xyz:XYZ100" -> "XYZ100")
|
|
170
|
+
* Returns the symbol unchanged if no DEX prefix is present
|
|
171
|
+
*
|
|
172
|
+
* @param symbol - Full symbol (e.g., "BTC" or "xyz:XYZ100")
|
|
173
|
+
* @returns Display symbol without DEX prefix (e.g., "BTC" or "XYZ100")
|
|
174
|
+
*/
|
|
175
|
+
const getPerpsDisplaySymbol = (symbol) => {
|
|
176
|
+
if (!symbol || typeof symbol !== 'string') {
|
|
177
|
+
return symbol;
|
|
178
|
+
}
|
|
179
|
+
// Check for DEX prefix pattern (dex:symbol)
|
|
180
|
+
const colonIndex = symbol.indexOf(':');
|
|
181
|
+
if (colonIndex > 0 && colonIndex < symbol.length - 1) {
|
|
182
|
+
// Return everything after the colon
|
|
183
|
+
return symbol.substring(colonIndex + 1);
|
|
184
|
+
}
|
|
185
|
+
// No DEX prefix found, return original symbol
|
|
186
|
+
return symbol;
|
|
187
|
+
};
|
|
188
|
+
exports.getPerpsDisplaySymbol = getPerpsDisplaySymbol;
|
|
189
|
+
/**
|
|
190
|
+
* Extract the DEX identifier from a full symbol string
|
|
191
|
+
* Returns the DEX prefix for HIP-3 markets (e.g., "xyz:XYZ100" -> "xyz")
|
|
192
|
+
* Returns null if no DEX prefix is present (main DEX market)
|
|
193
|
+
*
|
|
194
|
+
* @param symbol - Full symbol (e.g., "BTC" or "xyz:XYZ100")
|
|
195
|
+
* @returns DEX identifier or null if main DEX (e.g., "xyz" or null)
|
|
196
|
+
*/
|
|
197
|
+
const getPerpsDexFromSymbol = (symbol) => {
|
|
198
|
+
if (!symbol || typeof symbol !== 'string') {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
// Check for DEX prefix pattern (dex:symbol)
|
|
202
|
+
const colonIndex = symbol.indexOf(':');
|
|
203
|
+
if (colonIndex > 0 && colonIndex < symbol.length - 1) {
|
|
204
|
+
// Return the DEX prefix (everything before the colon)
|
|
205
|
+
return symbol.substring(0, colonIndex);
|
|
206
|
+
}
|
|
207
|
+
// No DEX prefix found, this is a main DEX market
|
|
208
|
+
return null;
|
|
209
|
+
};
|
|
210
|
+
exports.getPerpsDexFromSymbol = getPerpsDexFromSymbol;
|
|
211
|
+
/**
|
|
212
|
+
* Calculate the time until the next funding period.
|
|
213
|
+
* Supports market-specific funding times when provided.
|
|
214
|
+
* Falls back to default HyperLiquid 1-hour periods (funding paid every hour).
|
|
215
|
+
*
|
|
216
|
+
* @param params - Optional funding countdown parameters
|
|
217
|
+
* @returns Formatted countdown string in HH:MM:SS format
|
|
218
|
+
*/
|
|
219
|
+
const calculateFundingCountdown = (params) => {
|
|
220
|
+
const now = new Date();
|
|
221
|
+
const nowMs = now.getTime();
|
|
222
|
+
// If we have a specific next funding time, check if it's reasonable for HyperLiquid's hourly funding
|
|
223
|
+
if (params?.nextFundingTime && params.nextFundingTime > nowMs) {
|
|
224
|
+
const msUntilFunding = params.nextFundingTime - nowMs;
|
|
225
|
+
const hoursUntilFunding = msUntilFunding / (1000 * 60 * 60);
|
|
226
|
+
// If API shows >1.1 hours, it's likely incorrect for HyperLiquid's hourly funding
|
|
227
|
+
// Use fallback calculation instead to show time until next hour
|
|
228
|
+
if (hoursUntilFunding <= 1.1) {
|
|
229
|
+
const totalSeconds = Math.floor(msUntilFunding / 1000);
|
|
230
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
231
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
232
|
+
const seconds = totalSeconds % 60;
|
|
233
|
+
// Format as HH:MM:SS
|
|
234
|
+
const formattedHours = String(hours).padStart(2, '0');
|
|
235
|
+
const formattedMinutes = String(minutes).padStart(2, '0');
|
|
236
|
+
const formattedSeconds = String(seconds).padStart(2, '0');
|
|
237
|
+
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
|
|
238
|
+
}
|
|
239
|
+
// If >1.1 hours, fall through to use hourly calculation instead
|
|
240
|
+
}
|
|
241
|
+
// Fall back to default calculation for HyperLiquid (1-hour periods)
|
|
242
|
+
// HyperLiquid pays funding every hour, so next funding is at the next hour
|
|
243
|
+
const utcMinutes = now.getUTCMinutes();
|
|
244
|
+
const utcSeconds = now.getUTCSeconds();
|
|
245
|
+
// Calculate time remaining until next hour (next funding time)
|
|
246
|
+
const minutesUntilNextHour = 59 - utcMinutes;
|
|
247
|
+
const secondsUntilNextHour = 60 - utcSeconds;
|
|
248
|
+
// Handle edge case where seconds equals 60
|
|
249
|
+
const finalSeconds = secondsUntilNextHour === 60 ? 0 : secondsUntilNextHour;
|
|
250
|
+
const finalMinutes = secondsUntilNextHour === 60
|
|
251
|
+
? minutesUntilNextHour + 1
|
|
252
|
+
: minutesUntilNextHour;
|
|
253
|
+
// For HyperLiquid 1-hour funding, hours should always be 0
|
|
254
|
+
// (countdown should never exceed 59:59 since funding happens every hour)
|
|
255
|
+
const finalHours = finalMinutes === 60 ? 1 : 0;
|
|
256
|
+
const adjustedMinutes = finalMinutes === 60 ? 0 : finalMinutes;
|
|
257
|
+
// Format as HH:MM:SS
|
|
258
|
+
const formattedHours = String(finalHours).padStart(2, '0');
|
|
259
|
+
const formattedMinutes = String(adjustedMinutes).padStart(2, '0');
|
|
260
|
+
const formattedSeconds = String(finalSeconds).padStart(2, '0');
|
|
261
|
+
return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
|
|
262
|
+
};
|
|
263
|
+
exports.calculateFundingCountdown = calculateFundingCountdown;
|
|
264
|
+
/**
|
|
265
|
+
* Calculate 24h high and low from candlestick data.
|
|
266
|
+
*
|
|
267
|
+
* @param candleData - Candlestick data containing price candles
|
|
268
|
+
* @returns Object with high and low prices for the last 24 hours
|
|
269
|
+
*/
|
|
270
|
+
const calculate24hHighLow = (candleData) => {
|
|
271
|
+
if (!candleData?.candles || candleData.candles.length === 0) {
|
|
272
|
+
return { high: 0, low: 0 };
|
|
273
|
+
}
|
|
274
|
+
// Get candles from last 24 hours
|
|
275
|
+
const now = Date.now();
|
|
276
|
+
const twentyFourHoursAgo = now - 24 * 60 * 60 * 1000;
|
|
277
|
+
let last24hCandles = candleData.candles.filter((candle) => candle.time >= twentyFourHoursAgo);
|
|
278
|
+
if (last24hCandles.length === 0) {
|
|
279
|
+
// If no 24h data, use all available candles
|
|
280
|
+
last24hCandles = [...candleData.candles];
|
|
281
|
+
}
|
|
282
|
+
const highs = last24hCandles.map((candle) => parseFloat(candle.high));
|
|
283
|
+
const lows = last24hCandles.map((candle) => parseFloat(candle.low));
|
|
284
|
+
return {
|
|
285
|
+
high: Math.max(...highs),
|
|
286
|
+
low: Math.min(...lows),
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
exports.calculate24hHighLow = calculate24hHighLow;
|
|
290
|
+
/**
|
|
291
|
+
* Determine badge type for a market based on its metadata
|
|
292
|
+
* Prioritizes explicit marketType over generic experimental badge
|
|
293
|
+
*
|
|
294
|
+
* @param market - Market data object (only needs marketType and marketSource fields)
|
|
295
|
+
* @returns Badge type to display, or undefined for no badge (main DEX)
|
|
296
|
+
*
|
|
297
|
+
* @example Main DEX
|
|
298
|
+
* getMarketBadgeType({ symbol: 'BTC', marketSource: null }) // → undefined
|
|
299
|
+
*
|
|
300
|
+
* @example Mapped HIP-3 DEX
|
|
301
|
+
* getMarketBadgeType({ symbol: 'xyz:XYZ100', marketSource: 'xyz', marketType: 'equity' }) // → 'equity'
|
|
302
|
+
*
|
|
303
|
+
* @example Unmapped HIP-3 DEX
|
|
304
|
+
* getMarketBadgeType({ symbol: 'abc:ABC100', marketSource: 'abc' }) // → 'experimental'
|
|
305
|
+
*/
|
|
306
|
+
const getMarketBadgeType = (market) =>
|
|
307
|
+
// Prioritize explicit marketType (e.g., 'equity' for xyz DEX)
|
|
308
|
+
// Fall back to 'experimental' for unmapped HIP-3 DEXs
|
|
309
|
+
// Main DEX markets without marketType show no badge
|
|
310
|
+
market.marketType ?? (market.marketSource ? 'experimental' : undefined);
|
|
311
|
+
exports.getMarketBadgeType = getMarketBadgeType;
|
|
312
|
+
/**
|
|
313
|
+
* Filter markets by search query
|
|
314
|
+
* Searches through both symbol and name fields (case-insensitive)
|
|
315
|
+
*
|
|
316
|
+
* @param markets - Array of markets to filter
|
|
317
|
+
* @param searchQuery - Search query string
|
|
318
|
+
* @returns Filtered array of markets matching the query
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], 'btc') // → [{ symbol: 'BTC', name: 'Bitcoin' }]
|
|
322
|
+
* filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], 'coin') // → [{ symbol: 'BTC', name: 'Bitcoin' }]
|
|
323
|
+
* filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], '') // → [{ symbol: 'BTC', name: 'Bitcoin' }]
|
|
324
|
+
*/
|
|
325
|
+
const filterMarketsByQuery = (markets, searchQuery) => {
|
|
326
|
+
// Return all markets if query is empty
|
|
327
|
+
if (!searchQuery?.trim()) {
|
|
328
|
+
return markets;
|
|
329
|
+
}
|
|
330
|
+
const lowerQuery = searchQuery.toLowerCase().trim();
|
|
331
|
+
return markets.filter((market) => market.symbol?.toLowerCase().includes(lowerQuery) ||
|
|
332
|
+
market.name?.toLowerCase().includes(lowerQuery));
|
|
333
|
+
};
|
|
334
|
+
exports.filterMarketsByQuery = filterMarketsByQuery;
|
|
335
|
+
/**
|
|
336
|
+
* Generate the appropriate icon URL for an asset symbol
|
|
337
|
+
* Handles both regular assets and HIP-3 assets (dex:symbol format)
|
|
338
|
+
*
|
|
339
|
+
* @param symbol - Asset symbol (e.g., "BTC" or "xyz:TSLA")
|
|
340
|
+
* @param kPrefixAssets - Optional set of assets that have a 'k' prefix to remove
|
|
341
|
+
* @returns Icon URL for the asset
|
|
342
|
+
*
|
|
343
|
+
* @example Regular asset
|
|
344
|
+
* getAssetIconUrl('BTC') // → 'https://app.hyperliquid.xyz/coins/BTC.svg'
|
|
345
|
+
*
|
|
346
|
+
* @example HIP-3 asset
|
|
347
|
+
* getAssetIconUrl('xyz:TSLA') // → 'https://raw.githubusercontent.com/.../hip3%3Axyz_TSLA.svg'
|
|
348
|
+
*
|
|
349
|
+
* @example With k-prefix handling
|
|
350
|
+
* getAssetIconUrl('kBONK', new Set(['KBONK'])) // → 'https://app.hyperliquid.xyz/coins/BONK.svg'
|
|
351
|
+
*/
|
|
352
|
+
const getAssetIconUrl = (symbol, kPrefixAssets) => {
|
|
353
|
+
if (!symbol) {
|
|
354
|
+
return '';
|
|
355
|
+
}
|
|
356
|
+
// Check for HIP-3 asset (contains colon) BEFORE uppercasing
|
|
357
|
+
if (symbol.includes(':')) {
|
|
358
|
+
const [dex, assetSymbol] = symbol.split(':');
|
|
359
|
+
return `${hyperLiquidConfig_1.HYPERLIQUID_ASSET_ICONS_BASE_URL}${dex.toLowerCase()}:${assetSymbol.toUpperCase()}.svg`;
|
|
360
|
+
}
|
|
361
|
+
// For regular assets, uppercase the entire symbol
|
|
362
|
+
let processedSymbol = symbol.toUpperCase();
|
|
363
|
+
// Remove 'k' prefix only for specific assets if provided
|
|
364
|
+
if (kPrefixAssets?.has(processedSymbol)) {
|
|
365
|
+
processedSymbol = processedSymbol.substring(1);
|
|
366
|
+
}
|
|
367
|
+
// Regular asset
|
|
368
|
+
return `${hyperLiquidConfig_1.HYPERLIQUID_ASSET_ICONS_BASE_URL}${processedSymbol}.svg`;
|
|
369
|
+
};
|
|
370
|
+
exports.getAssetIconUrl = getAssetIconUrl;
|
|
371
|
+
/**
|
|
372
|
+
* Generate icon URLs for an asset symbol with fallback support
|
|
373
|
+
*
|
|
374
|
+
* Resolution order:
|
|
375
|
+
* 1. Primary: MetaMask contract-metadata repo (manually curated)
|
|
376
|
+
* 2. Fallback: HyperLiquid CDN (always available)
|
|
377
|
+
*
|
|
378
|
+
* @param symbol - Asset symbol (e.g., "BTC" or "xyz:TSLA")
|
|
379
|
+
* @param kPrefixAssets - Optional set of assets that have a 'k' prefix to remove
|
|
380
|
+
* @returns Object with primary and fallback URLs, or null if no symbol
|
|
381
|
+
*
|
|
382
|
+
* @example Regular asset
|
|
383
|
+
* getAssetIconUrls('BTC')
|
|
384
|
+
* // → { primary: 'https://raw.githubusercontent.com/.../BTC.svg',
|
|
385
|
+
* // fallback: 'https://app.hyperliquid.xyz/coins/BTC.svg' }
|
|
386
|
+
*
|
|
387
|
+
* @example HIP-3 asset
|
|
388
|
+
* getAssetIconUrls('xyz:TSLA')
|
|
389
|
+
* // → { primary: 'https://raw.githubusercontent.com/.../hip3:xyz_TSLA.svg',
|
|
390
|
+
* // fallback: 'https://app.hyperliquid.xyz/coins/xyz:TSLA.svg' }
|
|
391
|
+
*/
|
|
392
|
+
const getAssetIconUrls = (symbol, kPrefixAssets) => {
|
|
393
|
+
if (!symbol) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
// Check for HIP-3 asset (contains colon) BEFORE uppercasing
|
|
397
|
+
if (symbol.includes(':')) {
|
|
398
|
+
const [dex, assetSymbol] = symbol.split(':');
|
|
399
|
+
// HyperLiquid uses dex:SYMBOL format
|
|
400
|
+
const hyperliquidFormat = `${dex.toLowerCase()}:${assetSymbol.toUpperCase()}`;
|
|
401
|
+
// MetaMask contract-metadata uses hip3:dex_SYMBOL format
|
|
402
|
+
const metamaskFormat = `hip3:${dex.toLowerCase()}_${assetSymbol.toUpperCase()}`;
|
|
403
|
+
return {
|
|
404
|
+
primary: `${hyperLiquidConfig_1.METAMASK_PERPS_ICONS_BASE_URL}${metamaskFormat}.svg`,
|
|
405
|
+
fallback: `${hyperLiquidConfig_1.HYPERLIQUID_ASSET_ICONS_BASE_URL}${hyperliquidFormat}.svg`,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
// For regular assets, uppercase the entire symbol
|
|
409
|
+
let processedSymbol = symbol.toUpperCase();
|
|
410
|
+
// Remove 'k' prefix only for specific assets if provided
|
|
411
|
+
if (kPrefixAssets?.has(processedSymbol)) {
|
|
412
|
+
processedSymbol = processedSymbol.substring(1);
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
primary: `${hyperLiquidConfig_1.METAMASK_PERPS_ICONS_BASE_URL}${processedSymbol}.svg`,
|
|
416
|
+
fallback: `${hyperLiquidConfig_1.HYPERLIQUID_ASSET_ICONS_BASE_URL}${processedSymbol}.svg`,
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
exports.getAssetIconUrls = getAssetIconUrls;
|
|
420
|
+
//# sourceMappingURL=marketUtils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marketUtils.cjs","sourceRoot":"","sources":["../../src/utils/marketUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n HYPERLIQUID_ASSET_ICONS_BASE_URL,\n METAMASK_PERPS_ICONS_BASE_URL,\n} from '../constants/hyperLiquidConfig';\nimport type {\n BadgeType,\n CandleData,\n CandleStick,\n PerpsMarketData,\n} from '../types';\n\n/**\n * Maximum length for market filter patterns (prevents DoS attacks)\n */\nconst MAX_MARKET_PATTERN_LENGTH = 100;\n\n/**\n * Pattern matcher type - either string (exact match) or RegExp (wildcard)\n */\nexport type MarketPatternMatcher = RegExp | string;\n\n/**\n * Pre-compiled pattern with original pattern string and matcher\n */\nexport type CompiledMarketPattern = {\n pattern: string;\n matcher: MarketPatternMatcher;\n};\n\n/**\n * Escape special regex characters in a string\n *\n * @param str - String to escape\n * @returns Escaped string safe for regex\n */\nexport const escapeRegex = (str: string): string =>\n str.replace(/[.*+?^${}()|[\\]\\\\]/gu, '\\\\$&');\n\n/**\n * Validate market filter pattern for safety\n * Prevents regex DoS attacks from malicious patterns\n *\n * @param pattern - Pattern to validate\n * @returns true if pattern is safe\n * @throws Error if pattern is unsafe\n *\n * @example Valid patterns\n * validateMarketPattern(\"BTC\") // → true\n * validateMarketPattern(\"xyz:TSLA\") // → true\n * validateMarketPattern(\"xyz:*\") // → true\n *\n * @example Invalid patterns\n * validateMarketPattern(\"\") // → throws Error\n * validateMarketPattern(\"xyz:.*\") // → throws Error (regex chars)\n * validateMarketPattern(\"BTC#SCAM\") // → throws Error (invalid char)\n */\nexport const validateMarketPattern = (pattern: string): boolean => {\n // Reject empty patterns\n if (!pattern || pattern.trim().length === 0) {\n throw new Error('Market pattern cannot be empty');\n }\n\n // Trim whitespace and normalize the pattern\n const normalizedPattern = pattern.trim();\n\n // Reject patterns that are too long (potential DoS)\n if (normalizedPattern.length > MAX_MARKET_PATTERN_LENGTH) {\n throw new Error(\n `Market pattern exceeds maximum length (${MAX_MARKET_PATTERN_LENGTH} chars): ${normalizedPattern}`,\n );\n }\n\n // Reject patterns with suspicious regex control characters\n // Allow only colon and asterisk for our pattern syntax\n const dangerousChars = /[\\\\()[\\]{}^$+?.|]/u;\n if (dangerousChars.test(normalizedPattern)) {\n throw new Error(\n `Market pattern contains invalid regex characters: ${normalizedPattern}`,\n );\n }\n\n // Allow only: alphanumeric, colon, hyphen, underscore, asterisk\n const validPattern = /^[a-zA-Z0-9:_\\-*]+$/u;\n if (!validPattern.test(normalizedPattern)) {\n throw new Error(\n `Market pattern contains invalid characters: ${normalizedPattern}`,\n );\n }\n\n return true;\n};\n\n/**\n * Compile market filter pattern into optimized matcher\n * Supports wildcards (\"xyz:*\"), DEX shorthand (\"xyz\"), and exact matches (\"xyz:TSLA\")\n *\n * Note: Main DEX markets (no prefix) don't need filtering - they're always included.\n * Patterns without colons are treated as HIP-3 DEX shorthand.\n *\n * @param pattern - Pattern string (e.g., \"xyz:*\", \"xyz:TSLA\", \"xyz\")\n * @returns Compiled matcher (RegExp for wildcards/shorthand, string for exact match)\n *\n * @example Wildcard - matches all markets from a DEX\n * compileMarketPattern(\"xyz:*\") // → /^xyz:/\n *\n * @example DEX shorthand - equivalent to wildcard\n * compileMarketPattern(\"xyz\") // → /^xyz:/ (matches all xyz markets)\n *\n * @example Exact match - matches specific market\n * compileMarketPattern(\"xyz:TSLA\") // → \"xyz:TSLA\"\n */\nexport const compileMarketPattern = (pattern: string): MarketPatternMatcher => {\n // Trim and validate pattern before compilation to prevent regex DoS\n const normalizedPattern = pattern.trim();\n validateMarketPattern(normalizedPattern);\n\n if (normalizedPattern.endsWith(':*')) {\n // Wildcard: \"xyz:*\" → regex /^xyz:/\n const prefix = normalizedPattern.slice(0, -2);\n return new RegExp(`^${escapeRegex(prefix)}:`, 'u');\n }\n\n if (!normalizedPattern.includes(':')) {\n // DEX shorthand: \"xyz\" → regex /^xyz:/\n return new RegExp(`^${escapeRegex(normalizedPattern)}:`, 'u');\n }\n\n // Exact match: just use string (fastest)\n return normalizedPattern;\n};\n\n/**\n * Check if a symbol matches a compiled pattern matcher\n *\n * @param symbol - Market symbol (e.g., \"BTC\", \"xyz:TSLA\")\n * @param matcher - Compiled matcher (string or RegExp)\n * @returns true if symbol matches the pattern\n */\nexport const matchesMarketPattern = (\n symbol: string,\n matcher: MarketPatternMatcher,\n): boolean => {\n if (typeof matcher === 'string') {\n // Exact match - fastest\n return symbol === matcher;\n }\n\n // RegExp match - still very fast\n return matcher.test(symbol);\n};\n\n/**\n * Check if a market should be included based on HIP-3 master switch and whitelist/blacklist patterns\n * Main DEX markets (null dex) are ALWAYS included (no filtering)\n *\n * Logic: Check master switch → apply whitelist (if non-empty) → apply blacklist\n *\n * @param symbol - Market symbol (e.g., \"BTC\", \"xyz:TSLA\")\n * @param dex - DEX identifier (null for main DEX, \"xyz\" for HIP-3 DEX)\n * @param hip3Enabled - Master switch for HIP-3 markets (false = block all HIP-3)\n * @param compiledEnabledPatterns - Pre-compiled whitelist patterns (empty = allow all)\n * @param compiledBlockedPatterns - Pre-compiled blacklist patterns (empty = block none)\n * @returns true if market should be shown to users\n *\n * @example Main DEX market (always included)\n * shouldIncludeMarket(\"BTC\", null, true, [...], [...]) // → true\n *\n * @example HIP-3 when master switch is OFF\n * shouldIncludeMarket(\"xyz:TSLA\", \"xyz\", false, [...], [...]) // → false (HIP-3 disabled)\n *\n * @example HIP-3 with empty whitelist (discovery mode)\n * shouldIncludeMarket(\"xyz:TSLA\", \"xyz\", true, [], []) // → true (allow all)\n *\n * @example HIP-3 with whitelist\n * shouldIncludeMarket(\"xyz:TSLA\", \"xyz\", true,\n * [{pattern: \"xyz:*\", matcher: /^xyz:/}], []) // → true (matches whitelist)\n *\n * @example HIP-3 with blacklist\n * shouldIncludeMarket(\"xyz:SCAM\", \"xyz\", true, [],\n * [{pattern: \"xyz:SCAM\", matcher: \"xyz:SCAM\"}]) // → false (blocked)\n */\nexport const shouldIncludeMarket = (\n symbol: string,\n dex: string | null,\n hip3Enabled: boolean,\n compiledEnabledPatterns: CompiledMarketPattern[],\n compiledBlockedPatterns: CompiledMarketPattern[],\n): boolean => {\n // ALWAYS include main DEX markets (no filtering)\n if (dex === null) {\n return true;\n }\n\n // Enforce HIP-3 master switch: if disabled, block ALL HIP-3 markets\n if (!hip3Enabled) {\n return false;\n }\n\n // Step 1: Apply whitelist only if non-empty\n if (compiledEnabledPatterns.length > 0) {\n const whitelisted = compiledEnabledPatterns.some(({ matcher }) =>\n matchesMarketPattern(symbol, matcher),\n );\n if (!whitelisted) {\n return false;\n }\n }\n\n // Step 2: Apply blacklist ONLY if non-empty (early return optimization)\n if (compiledBlockedPatterns.length === 0) {\n return true; // No blacklist to check - accept immediately\n }\n\n // Only reach here if blacklist has values\n const blacklisted = compiledBlockedPatterns.some(({ matcher }) =>\n matchesMarketPattern(symbol, matcher),\n );\n\n return !blacklisted;\n};\n\n/**\n * Extract the display symbol from a full symbol string\n * Strips DEX prefix for HIP-3 markets (e.g., \"xyz:XYZ100\" -> \"XYZ100\")\n * Returns the symbol unchanged if no DEX prefix is present\n *\n * @param symbol - Full symbol (e.g., \"BTC\" or \"xyz:XYZ100\")\n * @returns Display symbol without DEX prefix (e.g., \"BTC\" or \"XYZ100\")\n */\nexport const getPerpsDisplaySymbol = (symbol: string): string => {\n if (!symbol || typeof symbol !== 'string') {\n return symbol;\n }\n\n // Check for DEX prefix pattern (dex:symbol)\n const colonIndex = symbol.indexOf(':');\n if (colonIndex > 0 && colonIndex < symbol.length - 1) {\n // Return everything after the colon\n return symbol.substring(colonIndex + 1);\n }\n\n // No DEX prefix found, return original symbol\n return symbol;\n};\n\n/**\n * Extract the DEX identifier from a full symbol string\n * Returns the DEX prefix for HIP-3 markets (e.g., \"xyz:XYZ100\" -> \"xyz\")\n * Returns null if no DEX prefix is present (main DEX market)\n *\n * @param symbol - Full symbol (e.g., \"BTC\" or \"xyz:XYZ100\")\n * @returns DEX identifier or null if main DEX (e.g., \"xyz\" or null)\n */\nexport const getPerpsDexFromSymbol = (symbol: string): string | null => {\n if (!symbol || typeof symbol !== 'string') {\n return null;\n }\n\n // Check for DEX prefix pattern (dex:symbol)\n const colonIndex = symbol.indexOf(':');\n if (colonIndex > 0 && colonIndex < symbol.length - 1) {\n // Return the DEX prefix (everything before the colon)\n return symbol.substring(0, colonIndex);\n }\n\n // No DEX prefix found, this is a main DEX market\n return null;\n};\n\ntype FundingCountdownParams = {\n /**\n * Next funding time in milliseconds since epoch (optional, market-specific)\n */\n nextFundingTime?: number;\n /**\n * Funding interval in hours (optional, market-specific)\n * Default is 1 hour for HyperLiquid (funding is paid every hour)\n */\n fundingIntervalHours?: number;\n};\n\n/**\n * Calculate the time until the next funding period.\n * Supports market-specific funding times when provided.\n * Falls back to default HyperLiquid 1-hour periods (funding paid every hour).\n *\n * @param params - Optional funding countdown parameters\n * @returns Formatted countdown string in HH:MM:SS format\n */\nexport const calculateFundingCountdown = (\n params?: FundingCountdownParams,\n): string => {\n const now = new Date();\n const nowMs = now.getTime();\n\n // If we have a specific next funding time, check if it's reasonable for HyperLiquid's hourly funding\n if (params?.nextFundingTime && params.nextFundingTime > nowMs) {\n const msUntilFunding = params.nextFundingTime - nowMs;\n const hoursUntilFunding = msUntilFunding / (1000 * 60 * 60);\n\n // If API shows >1.1 hours, it's likely incorrect for HyperLiquid's hourly funding\n // Use fallback calculation instead to show time until next hour\n if (hoursUntilFunding <= 1.1) {\n const totalSeconds = Math.floor(msUntilFunding / 1000);\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n // Format as HH:MM:SS\n const formattedHours = String(hours).padStart(2, '0');\n const formattedMinutes = String(minutes).padStart(2, '0');\n const formattedSeconds = String(seconds).padStart(2, '0');\n\n return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;\n }\n // If >1.1 hours, fall through to use hourly calculation instead\n }\n\n // Fall back to default calculation for HyperLiquid (1-hour periods)\n // HyperLiquid pays funding every hour, so next funding is at the next hour\n const utcMinutes = now.getUTCMinutes();\n const utcSeconds = now.getUTCSeconds();\n\n // Calculate time remaining until next hour (next funding time)\n const minutesUntilNextHour = 59 - utcMinutes;\n const secondsUntilNextHour = 60 - utcSeconds;\n\n // Handle edge case where seconds equals 60\n const finalSeconds = secondsUntilNextHour === 60 ? 0 : secondsUntilNextHour;\n const finalMinutes =\n secondsUntilNextHour === 60\n ? minutesUntilNextHour + 1\n : minutesUntilNextHour;\n\n // For HyperLiquid 1-hour funding, hours should always be 0\n // (countdown should never exceed 59:59 since funding happens every hour)\n const finalHours = finalMinutes === 60 ? 1 : 0;\n const adjustedMinutes = finalMinutes === 60 ? 0 : finalMinutes;\n\n // Format as HH:MM:SS\n const formattedHours = String(finalHours).padStart(2, '0');\n const formattedMinutes = String(adjustedMinutes).padStart(2, '0');\n const formattedSeconds = String(finalSeconds).padStart(2, '0');\n\n return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;\n};\n\n/**\n * Calculate 24h high and low from candlestick data.\n *\n * @param candleData - Candlestick data containing price candles\n * @returns Object with high and low prices for the last 24 hours\n */\nexport const calculate24hHighLow = (\n candleData: CandleData | null,\n): { high: number; low: number } => {\n if (!candleData?.candles || candleData.candles.length === 0) {\n return { high: 0, low: 0 };\n }\n\n // Get candles from last 24 hours\n const now = Date.now();\n const twentyFourHoursAgo = now - 24 * 60 * 60 * 1000;\n\n let last24hCandles = candleData.candles.filter(\n (candle: CandleStick) => candle.time >= twentyFourHoursAgo,\n );\n\n if (last24hCandles.length === 0) {\n // If no 24h data, use all available candles\n last24hCandles = [...candleData.candles];\n }\n\n const highs = last24hCandles.map((candle: CandleStick) =>\n parseFloat(candle.high),\n );\n const lows = last24hCandles.map((candle: CandleStick) =>\n parseFloat(candle.low),\n );\n\n return {\n high: Math.max(...highs),\n low: Math.min(...lows),\n };\n};\n\n/**\n * Determine badge type for a market based on its metadata\n * Prioritizes explicit marketType over generic experimental badge\n *\n * @param market - Market data object (only needs marketType and marketSource fields)\n * @returns Badge type to display, or undefined for no badge (main DEX)\n *\n * @example Main DEX\n * getMarketBadgeType({ symbol: 'BTC', marketSource: null }) // → undefined\n *\n * @example Mapped HIP-3 DEX\n * getMarketBadgeType({ symbol: 'xyz:XYZ100', marketSource: 'xyz', marketType: 'equity' }) // → 'equity'\n *\n * @example Unmapped HIP-3 DEX\n * getMarketBadgeType({ symbol: 'abc:ABC100', marketSource: 'abc' }) // → 'experimental'\n */\nexport const getMarketBadgeType = (\n market: Pick<PerpsMarketData, 'marketType' | 'marketSource'>,\n): BadgeType | undefined =>\n // Prioritize explicit marketType (e.g., 'equity' for xyz DEX)\n // Fall back to 'experimental' for unmapped HIP-3 DEXs\n // Main DEX markets without marketType show no badge\n market.marketType ?? (market.marketSource ? 'experimental' : undefined);\n\n/**\n * Filter markets by search query\n * Searches through both symbol and name fields (case-insensitive)\n *\n * @param markets - Array of markets to filter\n * @param searchQuery - Search query string\n * @returns Filtered array of markets matching the query\n *\n * @example\n * filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], 'btc') // → [{ symbol: 'BTC', name: 'Bitcoin' }]\n * filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], 'coin') // → [{ symbol: 'BTC', name: 'Bitcoin' }]\n * filterMarketsByQuery([{ symbol: 'BTC', name: 'Bitcoin' }], '') // → [{ symbol: 'BTC', name: 'Bitcoin' }]\n */\nexport const filterMarketsByQuery = (\n markets: PerpsMarketData[],\n searchQuery: string,\n): PerpsMarketData[] => {\n // Return all markets if query is empty\n if (!searchQuery?.trim()) {\n return markets;\n }\n\n const lowerQuery = searchQuery.toLowerCase().trim();\n\n return markets.filter(\n (market) =>\n market.symbol?.toLowerCase().includes(lowerQuery) ||\n market.name?.toLowerCase().includes(lowerQuery),\n );\n};\n\n/**\n * Generate the appropriate icon URL for an asset symbol\n * Handles both regular assets and HIP-3 assets (dex:symbol format)\n *\n * @param symbol - Asset symbol (e.g., \"BTC\" or \"xyz:TSLA\")\n * @param kPrefixAssets - Optional set of assets that have a 'k' prefix to remove\n * @returns Icon URL for the asset\n *\n * @example Regular asset\n * getAssetIconUrl('BTC') // → 'https://app.hyperliquid.xyz/coins/BTC.svg'\n *\n * @example HIP-3 asset\n * getAssetIconUrl('xyz:TSLA') // → 'https://raw.githubusercontent.com/.../hip3%3Axyz_TSLA.svg'\n *\n * @example With k-prefix handling\n * getAssetIconUrl('kBONK', new Set(['KBONK'])) // → 'https://app.hyperliquid.xyz/coins/BONK.svg'\n */\nexport const getAssetIconUrl = (\n symbol: string,\n kPrefixAssets?: Set<string>,\n): string => {\n if (!symbol) {\n return '';\n }\n\n // Check for HIP-3 asset (contains colon) BEFORE uppercasing\n if (symbol.includes(':')) {\n const [dex, assetSymbol] = symbol.split(':');\n return `${HYPERLIQUID_ASSET_ICONS_BASE_URL}${dex.toLowerCase()}:${assetSymbol.toUpperCase()}.svg`;\n }\n\n // For regular assets, uppercase the entire symbol\n let processedSymbol = symbol.toUpperCase();\n\n // Remove 'k' prefix only for specific assets if provided\n if (kPrefixAssets?.has(processedSymbol)) {\n processedSymbol = processedSymbol.substring(1);\n }\n\n // Regular asset\n return `${HYPERLIQUID_ASSET_ICONS_BASE_URL}${processedSymbol}.svg`;\n};\n\n/**\n * Icon URLs with primary (MetaMask-hosted) and fallback (HyperLiquid) sources\n */\nexport type AssetIconUrls = {\n /** MetaMask contract-metadata repo (preferred source) */\n primary: string;\n /** HyperLiquid CDN (fallback source) */\n fallback: string;\n};\n\n/**\n * Generate icon URLs for an asset symbol with fallback support\n *\n * Resolution order:\n * 1. Primary: MetaMask contract-metadata repo (manually curated)\n * 2. Fallback: HyperLiquid CDN (always available)\n *\n * @param symbol - Asset symbol (e.g., \"BTC\" or \"xyz:TSLA\")\n * @param kPrefixAssets - Optional set of assets that have a 'k' prefix to remove\n * @returns Object with primary and fallback URLs, or null if no symbol\n *\n * @example Regular asset\n * getAssetIconUrls('BTC')\n * // → { primary: 'https://raw.githubusercontent.com/.../BTC.svg',\n * // fallback: 'https://app.hyperliquid.xyz/coins/BTC.svg' }\n *\n * @example HIP-3 asset\n * getAssetIconUrls('xyz:TSLA')\n * // → { primary: 'https://raw.githubusercontent.com/.../hip3:xyz_TSLA.svg',\n * // fallback: 'https://app.hyperliquid.xyz/coins/xyz:TSLA.svg' }\n */\nexport const getAssetIconUrls = (\n symbol: string,\n kPrefixAssets?: Set<string>,\n): AssetIconUrls | null => {\n if (!symbol) {\n return null;\n }\n\n // Check for HIP-3 asset (contains colon) BEFORE uppercasing\n if (symbol.includes(':')) {\n const [dex, assetSymbol] = symbol.split(':');\n // HyperLiquid uses dex:SYMBOL format\n const hyperliquidFormat = `${dex.toLowerCase()}:${assetSymbol.toUpperCase()}`;\n // MetaMask contract-metadata uses hip3:dex_SYMBOL format\n const metamaskFormat = `hip3:${dex.toLowerCase()}_${assetSymbol.toUpperCase()}`;\n return {\n primary: `${METAMASK_PERPS_ICONS_BASE_URL}${metamaskFormat}.svg`,\n fallback: `${HYPERLIQUID_ASSET_ICONS_BASE_URL}${hyperliquidFormat}.svg`,\n };\n }\n\n // For regular assets, uppercase the entire symbol\n let processedSymbol = symbol.toUpperCase();\n\n // Remove 'k' prefix only for specific assets if provided\n if (kPrefixAssets?.has(processedSymbol)) {\n processedSymbol = processedSymbol.substring(1);\n }\n\n return {\n primary: `${METAMASK_PERPS_ICONS_BASE_URL}${processedSymbol}.svg`,\n fallback: `${HYPERLIQUID_ASSET_ICONS_BASE_URL}${processedSymbol}.svg`,\n };\n};\n"]}
|