lynx-client 0.0.34 → 0.0.36
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/dist/cjs/index.js +2 -0
- package/dist/cjs/lib/addresses/lensAddresses.js +6 -6
- package/dist/cjs/lib/constants/feeIds.js +20 -0
- package/dist/cjs/lib/constants/groupIds.js +20 -0
- package/dist/cjs/lib/constants/pairIds.js +43 -1
- package/dist/cjs/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.js +3 -0
- package/dist/cjs/lib/contractsIntegration/TradingFloorLensService/TradingFloorLensService.js +1 -0
- package/dist/cjs/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.js +31 -1
- package/dist/cjs/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.js +60 -0
- package/dist/cjs/lib/marketHours/marketHoursUtils.js +663 -0
- package/dist/cjs/lib/priceFeeds/flare/flareFeedConstants.js +22 -0
- package/dist/cjs/lib/priceFeeds/pyth/pythFeedConstants.js +44 -0
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/IntentsVerifier/TradeIntentsVerifierV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/Lex/LexPool/LexPoolV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/Lex/PoolAccountant/PoolAccountantV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/OrderBook/OrderBookV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/Registry/RegistryV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/TradersPortal/TradersPortalV1__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.js +21 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.js +222 -1
- package/dist/cjs/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.js +5 -0
- package/dist/cjs/lib/typechain/factories/contracts/Peripheral/Lens/LexLens__factory.js +1 -1
- package/dist/cjs/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.js +46 -1
- package/dist/cjs/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.js +337 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/lib/addresses/lensAddresses.d.ts +6 -6
- package/dist/esm/lib/addresses/lensAddresses.js +6 -6
- package/dist/esm/lib/constants/feeIds.d.ts +5 -1
- package/dist/esm/lib/constants/feeIds.d.ts.map +1 -1
- package/dist/esm/lib/constants/feeIds.js +20 -0
- package/dist/esm/lib/constants/groupIds.d.ts +5 -1
- package/dist/esm/lib/constants/groupIds.d.ts.map +1 -1
- package/dist/esm/lib/constants/groupIds.js +20 -0
- package/dist/esm/lib/constants/pairIds.d.ts +19 -1
- package/dist/esm/lib/constants/pairIds.d.ts.map +1 -1
- package/dist/esm/lib/constants/pairIds.js +43 -1
- package/dist/esm/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.d.ts +2 -1
- package/dist/esm/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.d.ts.map +1 -1
- package/dist/esm/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.js +3 -0
- package/dist/esm/lib/contractsIntegration/TradingFloorLensService/TradingFloorLensService.d.ts.map +1 -1
- package/dist/esm/lib/contractsIntegration/TradingFloorLensService/TradingFloorLensService.js +1 -0
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.d.ts +31 -1
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.d.ts.map +1 -1
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.js +31 -1
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.d.ts +8 -2
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.d.ts.map +1 -1
- package/dist/esm/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.js +60 -0
- package/dist/esm/lib/marketHours/marketHoursUtils.d.ts +52 -0
- package/dist/esm/lib/marketHours/marketHoursUtils.d.ts.map +1 -0
- package/dist/esm/lib/marketHours/marketHoursUtils.js +663 -0
- package/dist/esm/lib/priceFeeds/flare/flareFeedConstants.d.ts.map +1 -1
- package/dist/esm/lib/priceFeeds/flare/flareFeedConstants.js +22 -0
- package/dist/esm/lib/priceFeeds/pyth/pythFeedConstants.d.ts.map +1 -1
- package/dist/esm/lib/priceFeeds/pyth/pythFeedConstants.js +44 -0
- package/dist/esm/lib/typechain/contracts/Lynx/TradingFloor/TradingFloorV1.d.ts +18 -6
- package/dist/esm/lib/typechain/contracts/Lynx/TradingFloor/TradingFloorV1.d.ts.map +1 -1
- package/dist/esm/lib/typechain/contracts/Lynx/Triggers/TriggersV1.d.ts +36 -2
- package/dist/esm/lib/typechain/contracts/Lynx/Triggers/TriggersV1.d.ts.map +1 -1
- package/dist/esm/lib/typechain/contracts/Lynx/interfaces/IPriceValidatorV1.d.ts +9 -3
- package/dist/esm/lib/typechain/contracts/Lynx/interfaces/IPriceValidatorV1.d.ts.map +1 -1
- package/dist/esm/lib/typechain/contracts/Peripheral/Lens/TradingFloorLens.d.ts +10 -1
- package/dist/esm/lib/typechain/contracts/Peripheral/Lens/TradingFloorLens.d.ts.map +1 -1
- package/dist/esm/lib/typechain/contracts/Peripheral/Lens/TriggersAndPortalLens.d.ts +173 -1
- package/dist/esm/lib/typechain/contracts/Peripheral/Lens/TriggersAndPortalLens.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/IntentsVerifier/TradeIntentsVerifierV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/IntentsVerifier/TradeIntentsVerifierV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/LexPool/LexPoolV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/LexPool/LexPoolV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/PoolAccountant/PoolAccountantV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Lex/PoolAccountant/PoolAccountantV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/OrderBook/OrderBookV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/OrderBook/OrderBookV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Registry/RegistryV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Registry/RegistryV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/TradersPortal/TradersPortalV1__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/TradersPortal/TradersPortalV1__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.d.ts +17 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.js +21 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.d.ts +177 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.js +222 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.d.ts +4 -0
- package/dist/esm/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.js +5 -0
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/LexLens__factory.d.ts +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/LexLens__factory.js +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.d.ts +37 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.js +46 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.d.ts +259 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.d.ts.map +1 -1
- package/dist/esm/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.js +337 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/addresses/lensAddresses.d.ts +6 -6
- package/dist/types/lib/constants/feeIds.d.ts +5 -1
- package/dist/types/lib/constants/feeIds.d.ts.map +1 -1
- package/dist/types/lib/constants/groupIds.d.ts +5 -1
- package/dist/types/lib/constants/groupIds.d.ts.map +1 -1
- package/dist/types/lib/constants/pairIds.d.ts +19 -1
- package/dist/types/lib/constants/pairIds.d.ts.map +1 -1
- package/dist/types/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.d.ts +2 -1
- package/dist/types/lib/contractsIntegration/TradingFloorLensService/ITradingFloorLensService.d.ts.map +1 -1
- package/dist/types/lib/contractsIntegration/TradingFloorLensService/TradingFloorLensService.d.ts.map +1 -1
- package/dist/types/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.d.ts +31 -1
- package/dist/types/lib/contractsIntegration/TriggersAndPortalLensService/ITriggersAndPortalLensService.d.ts.map +1 -1
- package/dist/types/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.d.ts +8 -2
- package/dist/types/lib/contractsIntegration/TriggersAndPortalLensService/TriggersAndPortalLensService.d.ts.map +1 -1
- package/dist/types/lib/marketHours/marketHoursUtils.d.ts +52 -0
- package/dist/types/lib/marketHours/marketHoursUtils.d.ts.map +1 -0
- package/dist/types/lib/priceFeeds/flare/flareFeedConstants.d.ts.map +1 -1
- package/dist/types/lib/priceFeeds/pyth/pythFeedConstants.d.ts.map +1 -1
- package/dist/types/lib/typechain/contracts/Lynx/TradingFloor/TradingFloorV1.d.ts +18 -6
- package/dist/types/lib/typechain/contracts/Lynx/TradingFloor/TradingFloorV1.d.ts.map +1 -1
- package/dist/types/lib/typechain/contracts/Lynx/Triggers/TriggersV1.d.ts +36 -2
- package/dist/types/lib/typechain/contracts/Lynx/Triggers/TriggersV1.d.ts.map +1 -1
- package/dist/types/lib/typechain/contracts/Lynx/interfaces/IPriceValidatorV1.d.ts +9 -3
- package/dist/types/lib/typechain/contracts/Lynx/interfaces/IPriceValidatorV1.d.ts.map +1 -1
- package/dist/types/lib/typechain/contracts/Peripheral/Lens/TradingFloorLens.d.ts +10 -1
- package/dist/types/lib/typechain/contracts/Peripheral/Lens/TradingFloorLens.d.ts.map +1 -1
- package/dist/types/lib/typechain/contracts/Peripheral/Lens/TriggersAndPortalLens.d.ts +173 -1
- package/dist/types/lib/typechain/contracts/Peripheral/Lens/TriggersAndPortalLens.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/IntentsVerifier/TradeIntentsVerifierV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Lex/LexPool/LexPoolV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Lex/PNLR/PNLR__factory.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Lex/PoolAccountant/PoolAccountantV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/OrderBook/OrderBookV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Registry/RegistryV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/TradersPortal/TradersPortalV1__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.d.ts +17 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/TradingFloor/TradingFloorV1__factory.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.d.ts +177 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/Triggers/TriggersV1__factory.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.d.ts +4 -0
- package/dist/types/lib/typechain/factories/contracts/Lynx/interfaces/IPriceValidatorV1__factory.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Peripheral/Lens/LexLens__factory.d.ts +1 -1
- package/dist/types/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.d.ts +37 -1
- package/dist/types/lib/typechain/factories/contracts/Peripheral/Lens/TradingFloorLens__factory.d.ts.map +1 -1
- package/dist/types/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.d.ts +259 -1
- package/dist/types/lib/typechain/factories/contracts/Peripheral/Lens/TriggersAndPortalLens__factory.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Market hours utilities for Lynx trading pairs
|
|
4
|
+
* Data sourced from Pyth Network: https://docs.pyth.network/price-feeds/market-hours
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getMarketTypeFromGroupId = getMarketTypeFromGroupId;
|
|
8
|
+
exports.isUSInDST = isUSInDST;
|
|
9
|
+
exports.getMarketStatus = getMarketStatus;
|
|
10
|
+
exports.getForexMarketStatus = getForexMarketStatus;
|
|
11
|
+
exports.findNextForexOpen = findNextForexOpen;
|
|
12
|
+
exports.getCommoditiesMarketStatus = getCommoditiesMarketStatus;
|
|
13
|
+
exports.getNextCommoditiesClose = getNextCommoditiesClose;
|
|
14
|
+
exports.findNextCommoditiesOpen = findNextCommoditiesOpen;
|
|
15
|
+
exports.isMarketOpen = isMarketOpen;
|
|
16
|
+
exports.getMarketStatusForPair = getMarketStatusForPair;
|
|
17
|
+
exports.isMarketOpenForPair = isMarketOpenForPair;
|
|
18
|
+
exports.getMarketSchedule = getMarketSchedule;
|
|
19
|
+
exports.getMarketScheduleForPair = getMarketScheduleForPair;
|
|
20
|
+
const groupIds_1 = require("../constants/groupIds");
|
|
21
|
+
const pairIds_1 = require("../constants/pairIds");
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// NYSE Holidays (stocks market closures)
|
|
24
|
+
// Source: https://www.nyse.com/markets/hours-calendars
|
|
25
|
+
// ============================================================================
|
|
26
|
+
const NYSE_HOLIDAYS_2025 = [
|
|
27
|
+
{ date: "2025-01-01", name: "New Year's Day" },
|
|
28
|
+
{ date: "2025-01-20", name: "Martin Luther King Jr. Day" },
|
|
29
|
+
{ date: "2025-02-17", name: "Presidents Day" },
|
|
30
|
+
{ date: "2025-04-18", name: "Good Friday" },
|
|
31
|
+
{ date: "2025-05-26", name: "Memorial Day" },
|
|
32
|
+
{ date: "2025-06-19", name: "Juneteenth" },
|
|
33
|
+
{ date: "2025-07-04", name: "Independence Day" },
|
|
34
|
+
{ date: "2025-09-01", name: "Labor Day" },
|
|
35
|
+
{ date: "2025-11-27", name: "Thanksgiving" },
|
|
36
|
+
{ date: "2025-12-25", name: "Christmas" },
|
|
37
|
+
];
|
|
38
|
+
const NYSE_HOLIDAYS_2026 = [
|
|
39
|
+
{ date: "2026-01-01", name: "New Year's Day" },
|
|
40
|
+
{ date: "2026-01-19", name: "Martin Luther King Jr. Day" },
|
|
41
|
+
{ date: "2026-02-16", name: "Presidents Day" },
|
|
42
|
+
{ date: "2026-04-03", name: "Good Friday" },
|
|
43
|
+
{ date: "2026-05-25", name: "Memorial Day" },
|
|
44
|
+
{ date: "2026-06-19", name: "Juneteenth" },
|
|
45
|
+
{ date: "2026-07-03", name: "Independence Day (observed)" },
|
|
46
|
+
{ date: "2026-09-07", name: "Labor Day" },
|
|
47
|
+
{ date: "2026-11-26", name: "Thanksgiving" },
|
|
48
|
+
{ date: "2026-12-25", name: "Christmas" },
|
|
49
|
+
];
|
|
50
|
+
const ALL_NYSE_HOLIDAYS = [
|
|
51
|
+
...NYSE_HOLIDAYS_2025,
|
|
52
|
+
...NYSE_HOLIDAYS_2026,
|
|
53
|
+
];
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Market Schedules
|
|
56
|
+
// All times are in EST (UTC-5), adjusted for EDT (UTC-4) when DST is active
|
|
57
|
+
// ============================================================================
|
|
58
|
+
const CRYPTO_SCHEDULE = {
|
|
59
|
+
marketType: "crypto",
|
|
60
|
+
sessions: [], // 24/7, no session boundaries
|
|
61
|
+
holidays: [],
|
|
62
|
+
};
|
|
63
|
+
// Forex: Sunday 5:00 PM ET → Friday 5:00 PM ET
|
|
64
|
+
// EST: Sunday 22:00 UTC → Friday 22:00 UTC
|
|
65
|
+
// EDT: Sunday 21:00 UTC → Friday 21:00 UTC
|
|
66
|
+
const FOREX_SCHEDULE = {
|
|
67
|
+
marketType: "forex",
|
|
68
|
+
sessions: [
|
|
69
|
+
// Represented as: opens Sunday evening, closes Friday evening
|
|
70
|
+
{ dayOfWeek: 0, openTimeUTC: "22:00", closeTimeUTC: "23:59" }, // Sunday open
|
|
71
|
+
{ dayOfWeek: 1, openTimeUTC: "00:00", closeTimeUTC: "23:59" }, // Monday
|
|
72
|
+
{ dayOfWeek: 2, openTimeUTC: "00:00", closeTimeUTC: "23:59" }, // Tuesday
|
|
73
|
+
{ dayOfWeek: 3, openTimeUTC: "00:00", closeTimeUTC: "23:59" }, // Wednesday
|
|
74
|
+
{ dayOfWeek: 4, openTimeUTC: "00:00", closeTimeUTC: "23:59" }, // Thursday
|
|
75
|
+
{ dayOfWeek: 5, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Friday close
|
|
76
|
+
],
|
|
77
|
+
holidays: [
|
|
78
|
+
{ date: "2025-12-25", name: "Christmas" },
|
|
79
|
+
{ date: "2026-12-25", name: "Christmas" },
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
// US Stocks: Weekdays 9:30 AM - 4:00 PM ET
|
|
83
|
+
// EST: 14:30 - 21:00 UTC
|
|
84
|
+
// EDT: 13:30 - 20:00 UTC
|
|
85
|
+
const STOCKS_SCHEDULE = {
|
|
86
|
+
marketType: "stocks",
|
|
87
|
+
sessions: [
|
|
88
|
+
{ dayOfWeek: 1, openTimeUTC: "14:30", closeTimeUTC: "21:00" }, // Monday
|
|
89
|
+
{ dayOfWeek: 2, openTimeUTC: "14:30", closeTimeUTC: "21:00" }, // Tuesday
|
|
90
|
+
{ dayOfWeek: 3, openTimeUTC: "14:30", closeTimeUTC: "21:00" }, // Wednesday
|
|
91
|
+
{ dayOfWeek: 4, openTimeUTC: "14:30", closeTimeUTC: "21:00" }, // Thursday
|
|
92
|
+
{ dayOfWeek: 5, openTimeUTC: "14:30", closeTimeUTC: "21:00" }, // Friday
|
|
93
|
+
],
|
|
94
|
+
holidays: ALL_NYSE_HOLIDAYS,
|
|
95
|
+
};
|
|
96
|
+
// Commodities: Sunday 6:00 PM ET → Friday 5:00 PM ET with daily 5-6 PM break
|
|
97
|
+
// EST: Sunday 23:00 UTC → Friday 22:00 UTC, daily break 22:00-23:00 UTC
|
|
98
|
+
// EDT: Sunday 22:00 UTC → Friday 21:00 UTC, daily break 21:00-22:00 UTC
|
|
99
|
+
const COMMODITIES_SCHEDULE = {
|
|
100
|
+
marketType: "commodities",
|
|
101
|
+
sessions: [
|
|
102
|
+
{ dayOfWeek: 0, openTimeUTC: "23:00", closeTimeUTC: "23:59" }, // Sunday open
|
|
103
|
+
{ dayOfWeek: 1, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Monday (break at 22:00)
|
|
104
|
+
{ dayOfWeek: 1, openTimeUTC: "23:00", closeTimeUTC: "23:59" }, // Monday reopen
|
|
105
|
+
{ dayOfWeek: 2, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Tuesday
|
|
106
|
+
{ dayOfWeek: 2, openTimeUTC: "23:00", closeTimeUTC: "23:59" }, // Tuesday reopen
|
|
107
|
+
{ dayOfWeek: 3, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Wednesday
|
|
108
|
+
{ dayOfWeek: 3, openTimeUTC: "23:00", closeTimeUTC: "23:59" }, // Wednesday reopen
|
|
109
|
+
{ dayOfWeek: 4, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Thursday
|
|
110
|
+
{ dayOfWeek: 4, openTimeUTC: "23:00", closeTimeUTC: "23:59" }, // Thursday reopen
|
|
111
|
+
{ dayOfWeek: 5, openTimeUTC: "00:00", closeTimeUTC: "22:00" }, // Friday close
|
|
112
|
+
],
|
|
113
|
+
holidays: [
|
|
114
|
+
{ date: "2025-12-25", name: "Christmas" },
|
|
115
|
+
{ date: "2026-12-25", name: "Christmas" },
|
|
116
|
+
],
|
|
117
|
+
dailyBreaks: [
|
|
118
|
+
{ startTimeUTC: "22:00", endTimeUTC: "23:00", daysOfWeek: [1, 2, 3, 4] },
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
// ============================================================================
|
|
122
|
+
// Group ID to Market Type Mapping
|
|
123
|
+
// ============================================================================
|
|
124
|
+
const GROUP_ID_TO_MARKET_TYPE = {
|
|
125
|
+
[groupIds_1.GROUP_CONFIGS_IDS.basicCryptoGroup]: "crypto",
|
|
126
|
+
[groupIds_1.GROUP_CONFIGS_IDS.catCryptoGroup]: "crypto",
|
|
127
|
+
[groupIds_1.GROUP_CONFIGS_IDS.forexGroup]: "forex",
|
|
128
|
+
[groupIds_1.GROUP_CONFIGS_IDS.catForexGroup]: "forex",
|
|
129
|
+
[groupIds_1.GROUP_CONFIGS_IDS.stocksGroup]: "stocks",
|
|
130
|
+
[groupIds_1.GROUP_CONFIGS_IDS.catStocksGroup]: "stocks",
|
|
131
|
+
[groupIds_1.GROUP_CONFIGS_IDS.commoditiesGroup]: "commodities",
|
|
132
|
+
[groupIds_1.GROUP_CONFIGS_IDS.catCommoditiesGroup]: "commodities",
|
|
133
|
+
};
|
|
134
|
+
const MARKET_TYPE_TO_SCHEDULE = {
|
|
135
|
+
crypto: CRYPTO_SCHEDULE,
|
|
136
|
+
forex: FOREX_SCHEDULE,
|
|
137
|
+
stocks: STOCKS_SCHEDULE,
|
|
138
|
+
commodities: COMMODITIES_SCHEDULE,
|
|
139
|
+
};
|
|
140
|
+
function getMarketTypeFromGroupId(groupId) {
|
|
141
|
+
const marketType = GROUP_ID_TO_MARKET_TYPE[groupId];
|
|
142
|
+
if (!marketType) {
|
|
143
|
+
throw new Error(`Unknown group ID: ${groupId}`);
|
|
144
|
+
}
|
|
145
|
+
return marketType;
|
|
146
|
+
}
|
|
147
|
+
// ============================================================================
|
|
148
|
+
// DST Detection
|
|
149
|
+
// US DST: 2nd Sunday of March 2:00 AM → 1st Sunday of November 2:00 AM
|
|
150
|
+
// ============================================================================
|
|
151
|
+
/**
|
|
152
|
+
* Get the nth occurrence of a specific day of week in a month
|
|
153
|
+
* @param year Full year (e.g., 2025)
|
|
154
|
+
* @param month Month (0-11)
|
|
155
|
+
* @param dayOfWeek Day of week (0 = Sunday)
|
|
156
|
+
* @param n Which occurrence (1 = first, 2 = second, etc.)
|
|
157
|
+
* @returns Date object for that day at 00:00 UTC
|
|
158
|
+
*/
|
|
159
|
+
function getNthDayOfMonth(year, month, dayOfWeek, n) {
|
|
160
|
+
const firstDay = new Date(Date.UTC(year, month, 1));
|
|
161
|
+
const firstDayOfWeek = firstDay.getUTCDay();
|
|
162
|
+
let dayOffset = dayOfWeek - firstDayOfWeek;
|
|
163
|
+
if (dayOffset < 0)
|
|
164
|
+
dayOffset += 7;
|
|
165
|
+
const nthDay = 1 + dayOffset + (n - 1) * 7;
|
|
166
|
+
return new Date(Date.UTC(year, month, nthDay));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if a given timestamp falls within US Daylight Saving Time
|
|
170
|
+
* DST starts: 2nd Sunday of March at 2:00 AM local (7:00 UTC)
|
|
171
|
+
* DST ends: 1st Sunday of November at 2:00 AM local (6:00 UTC)
|
|
172
|
+
*/
|
|
173
|
+
function isUSInDST(timestamp) {
|
|
174
|
+
const date = new Date(timestamp);
|
|
175
|
+
const year = date.getUTCFullYear();
|
|
176
|
+
// DST starts: 2nd Sunday of March at 7:00 UTC (2:00 AM EST → 3:00 AM EDT)
|
|
177
|
+
const dstStart = getNthDayOfMonth(year, 2, 0, 2); // March, Sunday, 2nd
|
|
178
|
+
dstStart.setUTCHours(7, 0, 0, 0);
|
|
179
|
+
// DST ends: 1st Sunday of November at 6:00 UTC (2:00 AM EDT → 1:00 AM EST)
|
|
180
|
+
const dstEnd = getNthDayOfMonth(year, 10, 0, 1); // November, Sunday, 1st
|
|
181
|
+
dstEnd.setUTCHours(6, 0, 0, 0);
|
|
182
|
+
return timestamp >= dstStart.getTime() && timestamp < dstEnd.getTime();
|
|
183
|
+
}
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Internal Helpers
|
|
186
|
+
// ============================================================================
|
|
187
|
+
function getScheduleForGroupId(groupId) {
|
|
188
|
+
const marketType = getMarketTypeFromGroupId(groupId);
|
|
189
|
+
return MARKET_TYPE_TO_SCHEDULE[marketType];
|
|
190
|
+
}
|
|
191
|
+
function parseTimeUTC(timeStr) {
|
|
192
|
+
const [hours, minutes] = timeStr.split(':').map(Number);
|
|
193
|
+
return { hours, minutes };
|
|
194
|
+
}
|
|
195
|
+
function adjustTimeForDST(timeStr, isDST) {
|
|
196
|
+
if (!isDST)
|
|
197
|
+
return timeStr;
|
|
198
|
+
const { hours, minutes } = parseTimeUTC(timeStr);
|
|
199
|
+
const adjustedHours = hours - 1; // DST = 1 hour earlier in UTC
|
|
200
|
+
return `${adjustedHours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
201
|
+
}
|
|
202
|
+
function getDateString(timestamp) {
|
|
203
|
+
const date = new Date(timestamp);
|
|
204
|
+
const year = date.getUTCFullYear();
|
|
205
|
+
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
|
|
206
|
+
const day = date.getUTCDate().toString().padStart(2, '0');
|
|
207
|
+
return `${year}-${month}-${day}`;
|
|
208
|
+
}
|
|
209
|
+
function isHoliday(timestamp, holidays) {
|
|
210
|
+
const dateStr = getDateString(timestamp);
|
|
211
|
+
return holidays.some(h => h.date === dateStr);
|
|
212
|
+
}
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// Public API
|
|
215
|
+
// ============================================================================
|
|
216
|
+
function getMarketStatus(groupId, timestamp) {
|
|
217
|
+
const ts = timestamp ?? Date.now();
|
|
218
|
+
const schedule = getScheduleForGroupId(groupId);
|
|
219
|
+
// Crypto is always open
|
|
220
|
+
if (schedule.marketType === "crypto") {
|
|
221
|
+
return {
|
|
222
|
+
isOpen: true,
|
|
223
|
+
nextOpen: null,
|
|
224
|
+
nextClose: null,
|
|
225
|
+
marketType: "crypto",
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
if (schedule.marketType === "stocks") {
|
|
229
|
+
return getStocksMarketStatus(ts, schedule);
|
|
230
|
+
}
|
|
231
|
+
if (schedule.marketType === "forex") {
|
|
232
|
+
return getForexMarketStatus(ts, schedule);
|
|
233
|
+
}
|
|
234
|
+
if (schedule.marketType === "commodities") {
|
|
235
|
+
return getCommoditiesMarketStatus(ts, schedule);
|
|
236
|
+
}
|
|
237
|
+
throw new Error(`Market type ${schedule.marketType} not yet implemented`);
|
|
238
|
+
}
|
|
239
|
+
function getStocksMarketStatus(timestamp, schedule) {
|
|
240
|
+
const date = new Date(timestamp);
|
|
241
|
+
const dayOfWeek = date.getUTCDay();
|
|
242
|
+
const isDST = isUSInDST(timestamp);
|
|
243
|
+
// Check if it's a holiday
|
|
244
|
+
if (isHoliday(timestamp, schedule.holidays)) {
|
|
245
|
+
return {
|
|
246
|
+
isOpen: false,
|
|
247
|
+
nextOpen: findNextStocksOpen(timestamp, schedule, isDST),
|
|
248
|
+
nextClose: null,
|
|
249
|
+
marketType: "stocks",
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
// Check if it's a weekend
|
|
253
|
+
if (dayOfWeek === 0 || dayOfWeek === 6) {
|
|
254
|
+
return {
|
|
255
|
+
isOpen: false,
|
|
256
|
+
nextOpen: findNextStocksOpen(timestamp, schedule, isDST),
|
|
257
|
+
nextClose: null,
|
|
258
|
+
marketType: "stocks",
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
// Find today's session
|
|
262
|
+
const session = schedule.sessions.find(s => s.dayOfWeek === dayOfWeek);
|
|
263
|
+
if (!session) {
|
|
264
|
+
return {
|
|
265
|
+
isOpen: false,
|
|
266
|
+
nextOpen: findNextStocksOpen(timestamp, schedule, isDST),
|
|
267
|
+
nextClose: null,
|
|
268
|
+
marketType: "stocks",
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
// Adjust times for DST
|
|
272
|
+
const openTime = adjustTimeForDST(session.openTimeUTC, isDST);
|
|
273
|
+
const closeTime = adjustTimeForDST(session.closeTimeUTC, isDST);
|
|
274
|
+
const { hours: openHours, minutes: openMinutes } = parseTimeUTC(openTime);
|
|
275
|
+
const { hours: closeHours, minutes: closeMinutes } = parseTimeUTC(closeTime);
|
|
276
|
+
const currentHours = date.getUTCHours();
|
|
277
|
+
const currentMinutes = date.getUTCMinutes();
|
|
278
|
+
const currentTimeMinutes = currentHours * 60 + currentMinutes;
|
|
279
|
+
const openTimeMinutes = openHours * 60 + openMinutes;
|
|
280
|
+
const closeTimeMinutes = closeHours * 60 + closeMinutes;
|
|
281
|
+
if (currentTimeMinutes >= openTimeMinutes && currentTimeMinutes < closeTimeMinutes) {
|
|
282
|
+
// Market is open
|
|
283
|
+
const closeDate = new Date(timestamp);
|
|
284
|
+
closeDate.setUTCHours(closeHours, closeMinutes, 0, 0);
|
|
285
|
+
return {
|
|
286
|
+
isOpen: true,
|
|
287
|
+
nextOpen: null,
|
|
288
|
+
nextClose: closeDate,
|
|
289
|
+
marketType: "stocks",
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
// Market is closed
|
|
293
|
+
return {
|
|
294
|
+
isOpen: false,
|
|
295
|
+
nextOpen: findNextStocksOpen(timestamp, schedule, isDST),
|
|
296
|
+
nextClose: null,
|
|
297
|
+
marketType: "stocks",
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function findNextStocksOpen(timestamp, schedule, isDST) {
|
|
301
|
+
const date = new Date(timestamp);
|
|
302
|
+
let checkDate = new Date(timestamp);
|
|
303
|
+
// Get the open time (adjusted for DST)
|
|
304
|
+
const baseOpenTime = schedule.sessions.find(s => s.dayOfWeek === 1).openTimeUTC;
|
|
305
|
+
const openTime = adjustTimeForDST(baseOpenTime, isDST);
|
|
306
|
+
const { hours: openHours, minutes: openMinutes } = parseTimeUTC(openTime);
|
|
307
|
+
// If we're before today's open and today is a trading day, return today's open
|
|
308
|
+
const currentTimeMinutes = date.getUTCHours() * 60 + date.getUTCMinutes();
|
|
309
|
+
const openTimeMinutes = openHours * 60 + openMinutes;
|
|
310
|
+
const dayOfWeek = date.getUTCDay();
|
|
311
|
+
if (dayOfWeek >= 1 &&
|
|
312
|
+
dayOfWeek <= 5 &&
|
|
313
|
+
currentTimeMinutes < openTimeMinutes &&
|
|
314
|
+
!isHoliday(timestamp, schedule.holidays)) {
|
|
315
|
+
checkDate.setUTCHours(openHours, openMinutes, 0, 0);
|
|
316
|
+
return checkDate;
|
|
317
|
+
}
|
|
318
|
+
// Otherwise, find the next trading day
|
|
319
|
+
checkDate.setUTCDate(checkDate.getUTCDate() + 1);
|
|
320
|
+
checkDate.setUTCHours(openHours, openMinutes, 0, 0);
|
|
321
|
+
// Loop until we find a valid trading day (max 10 days to prevent infinite loop)
|
|
322
|
+
for (let i = 0; i < 10; i++) {
|
|
323
|
+
const checkDayOfWeek = checkDate.getUTCDay();
|
|
324
|
+
// Skip weekends
|
|
325
|
+
if (checkDayOfWeek === 0) {
|
|
326
|
+
checkDate.setUTCDate(checkDate.getUTCDate() + 1);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (checkDayOfWeek === 6) {
|
|
330
|
+
checkDate.setUTCDate(checkDate.getUTCDate() + 2);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
// Check DST for the check date and adjust if needed
|
|
334
|
+
const checkIsDST = isUSInDST(checkDate.getTime());
|
|
335
|
+
if (checkIsDST !== isDST) {
|
|
336
|
+
const newOpenTime = adjustTimeForDST(baseOpenTime, checkIsDST);
|
|
337
|
+
const { hours: newOpenHours, minutes: newOpenMinutes } = parseTimeUTC(newOpenTime);
|
|
338
|
+
checkDate.setUTCHours(newOpenHours, newOpenMinutes, 0, 0);
|
|
339
|
+
}
|
|
340
|
+
// Skip holidays
|
|
341
|
+
if (isHoliday(checkDate.getTime(), schedule.holidays)) {
|
|
342
|
+
checkDate.setUTCDate(checkDate.getUTCDate() + 1);
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
return checkDate;
|
|
346
|
+
}
|
|
347
|
+
return checkDate;
|
|
348
|
+
}
|
|
349
|
+
function getForexMarketStatus(timestamp, schedule) {
|
|
350
|
+
const date = new Date(timestamp);
|
|
351
|
+
const dayOfWeek = date.getUTCDay();
|
|
352
|
+
const isDST = isUSInDST(timestamp);
|
|
353
|
+
// Forex hours (EST): Sunday 22:00 UTC → Friday 22:00 UTC
|
|
354
|
+
// EDT adjustment: Sunday 21:00 UTC → Friday 21:00 UTC
|
|
355
|
+
const openHour = isDST ? 21 : 22;
|
|
356
|
+
const closeHour = isDST ? 21 : 22;
|
|
357
|
+
// Check if holiday
|
|
358
|
+
if (isHoliday(timestamp, schedule.holidays)) {
|
|
359
|
+
return {
|
|
360
|
+
isOpen: false,
|
|
361
|
+
nextOpen: findNextForexOpen(timestamp, isDST),
|
|
362
|
+
nextClose: null,
|
|
363
|
+
marketType: "forex",
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const currentHours = date.getUTCHours();
|
|
367
|
+
// Saturday: always closed
|
|
368
|
+
if (dayOfWeek === 6) {
|
|
369
|
+
return {
|
|
370
|
+
isOpen: false,
|
|
371
|
+
nextOpen: findNextForexOpen(timestamp, isDST),
|
|
372
|
+
nextClose: null,
|
|
373
|
+
marketType: "forex",
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
// Sunday: open after openHour
|
|
377
|
+
if (dayOfWeek === 0) {
|
|
378
|
+
if (currentHours >= openHour) {
|
|
379
|
+
// Find Friday close time
|
|
380
|
+
const fridayClose = new Date(timestamp);
|
|
381
|
+
fridayClose.setUTCDate(fridayClose.getUTCDate() + 5); // Next Friday
|
|
382
|
+
fridayClose.setUTCHours(closeHour, 0, 0, 0);
|
|
383
|
+
return {
|
|
384
|
+
isOpen: true,
|
|
385
|
+
nextOpen: null,
|
|
386
|
+
nextClose: fridayClose,
|
|
387
|
+
marketType: "forex",
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
return {
|
|
392
|
+
isOpen: false,
|
|
393
|
+
nextOpen: findNextForexOpen(timestamp, isDST),
|
|
394
|
+
nextClose: null,
|
|
395
|
+
marketType: "forex",
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
// Friday: closed after closeHour
|
|
400
|
+
if (dayOfWeek === 5) {
|
|
401
|
+
if (currentHours >= closeHour) {
|
|
402
|
+
return {
|
|
403
|
+
isOpen: false,
|
|
404
|
+
nextOpen: findNextForexOpen(timestamp, isDST),
|
|
405
|
+
nextClose: null,
|
|
406
|
+
marketType: "forex",
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
// Monday-Friday (before close): open
|
|
411
|
+
const fridayClose = new Date(timestamp);
|
|
412
|
+
fridayClose.setUTCDate(date.getUTCDate() + (5 - dayOfWeek));
|
|
413
|
+
fridayClose.setUTCHours(closeHour, 0, 0, 0);
|
|
414
|
+
return {
|
|
415
|
+
isOpen: true,
|
|
416
|
+
nextOpen: null,
|
|
417
|
+
nextClose: fridayClose,
|
|
418
|
+
marketType: "forex",
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function findNextForexOpen(timestamp, isDST) {
|
|
422
|
+
const date = new Date(timestamp);
|
|
423
|
+
const dayOfWeek = date.getUTCDay();
|
|
424
|
+
const openHour = isDST ? 21 : 22;
|
|
425
|
+
// Calculate days until next Sunday
|
|
426
|
+
let daysUntilSunday = (7 - dayOfWeek) % 7;
|
|
427
|
+
if (dayOfWeek === 0 && date.getUTCHours() >= openHour) {
|
|
428
|
+
// It's Sunday after open, next open is next week
|
|
429
|
+
daysUntilSunday = 7;
|
|
430
|
+
}
|
|
431
|
+
if (dayOfWeek === 0 && date.getUTCHours() < openHour) {
|
|
432
|
+
// It's Sunday before open, open is today
|
|
433
|
+
daysUntilSunday = 0;
|
|
434
|
+
}
|
|
435
|
+
const nextOpen = new Date(timestamp);
|
|
436
|
+
nextOpen.setUTCDate(date.getUTCDate() + daysUntilSunday);
|
|
437
|
+
nextOpen.setUTCHours(openHour, 0, 0, 0);
|
|
438
|
+
// Check DST for the open date
|
|
439
|
+
const openIsDST = isUSInDST(nextOpen.getTime());
|
|
440
|
+
if (openIsDST !== isDST) {
|
|
441
|
+
nextOpen.setUTCHours(openIsDST ? 21 : 22, 0, 0, 0);
|
|
442
|
+
}
|
|
443
|
+
return nextOpen;
|
|
444
|
+
}
|
|
445
|
+
// ============================================================================
|
|
446
|
+
// Commodities Market Functions
|
|
447
|
+
// Schedule: Sunday 23:00 UTC (EST) → Friday 22:00 UTC (EST)
|
|
448
|
+
// Sunday 22:00 UTC (EDT) → Friday 21:00 UTC (EDT)
|
|
449
|
+
// Daily break: 22:00-23:00 UTC (EST) / 21:00-22:00 UTC (EDT) on Mon-Thu
|
|
450
|
+
// ============================================================================
|
|
451
|
+
function getCommoditiesMarketStatus(timestamp, schedule) {
|
|
452
|
+
const date = new Date(timestamp);
|
|
453
|
+
const dayOfWeek = date.getUTCDay();
|
|
454
|
+
const isDST = isUSInDST(timestamp);
|
|
455
|
+
// Commodities hours (EST): Sunday 23:00 UTC → Friday 22:00 UTC
|
|
456
|
+
// EDT adjustment: Sunday 22:00 UTC → Friday 21:00 UTC
|
|
457
|
+
// Daily break (EST): 22:00-23:00 UTC on Mon-Thu
|
|
458
|
+
// Daily break (EDT): 21:00-22:00 UTC on Mon-Thu
|
|
459
|
+
const openHour = isDST ? 22 : 23; // Sunday open
|
|
460
|
+
const closeHour = isDST ? 21 : 22; // Friday close and daily break start
|
|
461
|
+
const breakEndHour = isDST ? 22 : 23; // Daily break end
|
|
462
|
+
// Check if holiday
|
|
463
|
+
if (isHoliday(timestamp, schedule.holidays)) {
|
|
464
|
+
return {
|
|
465
|
+
isOpen: false,
|
|
466
|
+
nextOpen: findNextCommoditiesOpen(timestamp, isDST),
|
|
467
|
+
nextClose: null,
|
|
468
|
+
marketType: "commodities",
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const currentHours = date.getUTCHours();
|
|
472
|
+
// Saturday: always closed
|
|
473
|
+
if (dayOfWeek === 6) {
|
|
474
|
+
return {
|
|
475
|
+
isOpen: false,
|
|
476
|
+
nextOpen: findNextCommoditiesOpen(timestamp, isDST),
|
|
477
|
+
nextClose: null,
|
|
478
|
+
marketType: "commodities",
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
// Sunday: open after openHour (23:00 EST / 22:00 EDT)
|
|
482
|
+
if (dayOfWeek === 0) {
|
|
483
|
+
if (currentHours >= openHour) {
|
|
484
|
+
return {
|
|
485
|
+
isOpen: true,
|
|
486
|
+
nextOpen: null,
|
|
487
|
+
nextClose: getNextCommoditiesClose(timestamp, isDST),
|
|
488
|
+
marketType: "commodities",
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
return {
|
|
493
|
+
isOpen: false,
|
|
494
|
+
nextOpen: findNextCommoditiesOpen(timestamp, isDST),
|
|
495
|
+
nextClose: null,
|
|
496
|
+
marketType: "commodities",
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
// Friday: closed after closeHour (22:00 EST / 21:00 EDT)
|
|
501
|
+
if (dayOfWeek === 5) {
|
|
502
|
+
if (currentHours >= closeHour) {
|
|
503
|
+
return {
|
|
504
|
+
isOpen: false,
|
|
505
|
+
nextOpen: findNextCommoditiesOpen(timestamp, isDST),
|
|
506
|
+
nextClose: null,
|
|
507
|
+
marketType: "commodities",
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
// Friday before close - market is open
|
|
511
|
+
return {
|
|
512
|
+
isOpen: true,
|
|
513
|
+
nextOpen: null,
|
|
514
|
+
nextClose: getNextCommoditiesClose(timestamp, isDST),
|
|
515
|
+
marketType: "commodities",
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
// Monday-Thursday: check for daily break (22:00-23:00 EST / 21:00-22:00 EDT)
|
|
519
|
+
if (dayOfWeek >= 1 && dayOfWeek <= 4) {
|
|
520
|
+
// During break
|
|
521
|
+
if (currentHours >= closeHour && currentHours < breakEndHour) {
|
|
522
|
+
// During daily break - return next open as end of break
|
|
523
|
+
const breakEnd = new Date(timestamp);
|
|
524
|
+
breakEnd.setUTCHours(breakEndHour, 0, 0, 0);
|
|
525
|
+
return {
|
|
526
|
+
isOpen: false,
|
|
527
|
+
nextOpen: breakEnd,
|
|
528
|
+
nextClose: null,
|
|
529
|
+
marketType: "commodities",
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
// Before break or after break reopens
|
|
533
|
+
return {
|
|
534
|
+
isOpen: true,
|
|
535
|
+
nextOpen: null,
|
|
536
|
+
nextClose: getNextCommoditiesClose(timestamp, isDST),
|
|
537
|
+
marketType: "commodities",
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
// Should not reach here, but fallback
|
|
541
|
+
return {
|
|
542
|
+
isOpen: false,
|
|
543
|
+
nextOpen: findNextCommoditiesOpen(timestamp, isDST),
|
|
544
|
+
nextClose: null,
|
|
545
|
+
marketType: "commodities",
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function getNextCommoditiesClose(timestamp, isDST) {
|
|
549
|
+
const date = new Date(timestamp);
|
|
550
|
+
const dayOfWeek = date.getUTCDay();
|
|
551
|
+
const currentHours = date.getUTCHours();
|
|
552
|
+
const closeHour = isDST ? 21 : 22; // Daily break start / Friday close
|
|
553
|
+
const breakEndHour = isDST ? 22 : 23;
|
|
554
|
+
// If we're before the daily break on Mon-Thu, the next close is today's break
|
|
555
|
+
if (dayOfWeek >= 1 && dayOfWeek <= 4) {
|
|
556
|
+
if (currentHours < closeHour) {
|
|
557
|
+
// Next close is today's daily break
|
|
558
|
+
const todayBreak = new Date(timestamp);
|
|
559
|
+
todayBreak.setUTCHours(closeHour, 0, 0, 0);
|
|
560
|
+
return todayBreak;
|
|
561
|
+
}
|
|
562
|
+
// If we're after the break reopened (>= breakEndHour), next close is tomorrow
|
|
563
|
+
if (currentHours >= breakEndHour) {
|
|
564
|
+
if (dayOfWeek === 4) {
|
|
565
|
+
// Thursday after break - next close is Friday close
|
|
566
|
+
const fridayClose = new Date(timestamp);
|
|
567
|
+
fridayClose.setUTCDate(date.getUTCDate() + 1);
|
|
568
|
+
fridayClose.setUTCHours(closeHour, 0, 0, 0);
|
|
569
|
+
return fridayClose;
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
// Mon-Wed after break - next close is tomorrow's break
|
|
573
|
+
const tomorrowBreak = new Date(timestamp);
|
|
574
|
+
tomorrowBreak.setUTCDate(date.getUTCDate() + 1);
|
|
575
|
+
tomorrowBreak.setUTCHours(closeHour, 0, 0, 0);
|
|
576
|
+
return tomorrowBreak;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
// Friday before close - next close is today
|
|
581
|
+
if (dayOfWeek === 5 && currentHours < closeHour) {
|
|
582
|
+
const fridayClose = new Date(timestamp);
|
|
583
|
+
fridayClose.setUTCHours(closeHour, 0, 0, 0);
|
|
584
|
+
return fridayClose;
|
|
585
|
+
}
|
|
586
|
+
// Sunday after open - next close is Monday's break
|
|
587
|
+
if (dayOfWeek === 0) {
|
|
588
|
+
const mondayBreak = new Date(timestamp);
|
|
589
|
+
mondayBreak.setUTCDate(date.getUTCDate() + 1);
|
|
590
|
+
mondayBreak.setUTCHours(closeHour, 0, 0, 0);
|
|
591
|
+
return mondayBreak;
|
|
592
|
+
}
|
|
593
|
+
// Fallback: return next Monday's break
|
|
594
|
+
const daysUntilMonday = (8 - dayOfWeek) % 7 || 7;
|
|
595
|
+
const mondayBreak = new Date(timestamp);
|
|
596
|
+
mondayBreak.setUTCDate(date.getUTCDate() + daysUntilMonday);
|
|
597
|
+
mondayBreak.setUTCHours(closeHour, 0, 0, 0);
|
|
598
|
+
return mondayBreak;
|
|
599
|
+
}
|
|
600
|
+
function findNextCommoditiesOpen(timestamp, isDST) {
|
|
601
|
+
const date = new Date(timestamp);
|
|
602
|
+
const dayOfWeek = date.getUTCDay();
|
|
603
|
+
const currentHours = date.getUTCHours();
|
|
604
|
+
const openHour = isDST ? 22 : 23; // Sunday open
|
|
605
|
+
const breakEndHour = isDST ? 22 : 23; // Daily break end
|
|
606
|
+
// During daily break (Mon-Thu) - next open is end of break (same day)
|
|
607
|
+
const closeHour = isDST ? 21 : 22;
|
|
608
|
+
if (dayOfWeek >= 1 && dayOfWeek <= 4) {
|
|
609
|
+
if (currentHours >= closeHour && currentHours < breakEndHour) {
|
|
610
|
+
const breakEnd = new Date(timestamp);
|
|
611
|
+
breakEnd.setUTCHours(breakEndHour, 0, 0, 0);
|
|
612
|
+
return breakEnd;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// Sunday before open - open is today
|
|
616
|
+
if (dayOfWeek === 0 && currentHours < openHour) {
|
|
617
|
+
const sundayOpen = new Date(timestamp);
|
|
618
|
+
sundayOpen.setUTCHours(openHour, 0, 0, 0);
|
|
619
|
+
return sundayOpen;
|
|
620
|
+
}
|
|
621
|
+
// Calculate days until next Sunday
|
|
622
|
+
let daysUntilSunday = (7 - dayOfWeek) % 7;
|
|
623
|
+
if (dayOfWeek === 0 && currentHours >= openHour) {
|
|
624
|
+
// It's Sunday after open, next open is next week's Sunday
|
|
625
|
+
daysUntilSunday = 7;
|
|
626
|
+
}
|
|
627
|
+
if (daysUntilSunday === 0 && dayOfWeek !== 0) {
|
|
628
|
+
// Not Sunday, so we need to go to next Sunday
|
|
629
|
+
daysUntilSunday = 7;
|
|
630
|
+
}
|
|
631
|
+
const nextOpen = new Date(timestamp);
|
|
632
|
+
nextOpen.setUTCDate(date.getUTCDate() + daysUntilSunday);
|
|
633
|
+
nextOpen.setUTCHours(openHour, 0, 0, 0);
|
|
634
|
+
// Check DST for the open date and adjust if needed
|
|
635
|
+
const openIsDST = isUSInDST(nextOpen.getTime());
|
|
636
|
+
if (openIsDST !== isDST) {
|
|
637
|
+
nextOpen.setUTCHours(openIsDST ? 22 : 23, 0, 0, 0);
|
|
638
|
+
}
|
|
639
|
+
return nextOpen;
|
|
640
|
+
}
|
|
641
|
+
function isMarketOpen(groupId, timestamp) {
|
|
642
|
+
return getMarketStatus(groupId, timestamp).isOpen;
|
|
643
|
+
}
|
|
644
|
+
function getMarketStatusForPair(pairId, timestamp) {
|
|
645
|
+
const pairConfig = (0, pairIds_1.getPairConfigsIdentifierFromPairId)(pairId);
|
|
646
|
+
if (!pairConfig) {
|
|
647
|
+
throw new Error(`Unknown pair ID: ${pairId}`);
|
|
648
|
+
}
|
|
649
|
+
return getMarketStatus(pairConfig.groupId, timestamp);
|
|
650
|
+
}
|
|
651
|
+
function isMarketOpenForPair(pairId, timestamp) {
|
|
652
|
+
return getMarketStatusForPair(pairId, timestamp).isOpen;
|
|
653
|
+
}
|
|
654
|
+
function getMarketSchedule(groupId) {
|
|
655
|
+
return getScheduleForGroupId(groupId);
|
|
656
|
+
}
|
|
657
|
+
function getMarketScheduleForPair(pairId) {
|
|
658
|
+
const pairConfig = (0, pairIds_1.getPairConfigsIdentifierFromPairId)(pairId);
|
|
659
|
+
if (!pairConfig) {
|
|
660
|
+
throw new Error(`Unknown pair ID: ${pairId}`);
|
|
661
|
+
}
|
|
662
|
+
return getMarketSchedule(pairConfig.groupId);
|
|
663
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flareFeedConstants.d.ts","sourceRoot":"","sources":["../../../../../lib/priceFeeds/flare/flareFeedConstants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGrE,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"flareFeedConstants.d.ts","sourceRoot":"","sources":["../../../../../lib/priceFeeds/flare/flareFeedConstants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGrE,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAmE/D,CAAC;AAGF,eAAO,MAAM,2BAA2B,0BAKlC,CAAC"}
|