@vninvestcharts/widget 0.0.0-stage → 0.2.0

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.
Files changed (676) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE.md +83 -0
  3. package/README.md +851 -3
  4. package/dist/AlertsModal-WKEUDTUZ.js +2 -0
  5. package/dist/ConnectedTradingPanel-KWJMIKTN.css +2 -0
  6. package/dist/ConnectedTradingPanel-XDKMOQY5.js +2 -0
  7. package/dist/PineEditorPanel-AUXB4FD3.js +2 -0
  8. package/dist/PineEditorPanel-V6YN2OTU.css +2 -0
  9. package/dist/RightSidebarDockHost-6FPZ6EKV.css +2 -0
  10. package/dist/RightSidebarDockHost-OBFXKSIY.js +2 -0
  11. package/dist/StrategyTesterPanel-6IUTS2P4.js +2 -0
  12. package/dist/StrategyTesterPanel-LEWEUMXP.css +2 -0
  13. package/dist/VolumeProfileWorker-UREKVPUE.js +189 -0
  14. package/dist/adapters/index.cjs +2532 -0
  15. package/dist/adapters/index.d.mts +673 -0
  16. package/dist/adapters/index.d.ts +673 -0
  17. package/dist/adapters/index.js +2521 -0
  18. package/dist/adapters/index.umd.js +2535 -0
  19. package/dist/chunk-5T6DGB3V.js +2 -0
  20. package/dist/chunk-66JBEGR3.js +4 -0
  21. package/dist/chunk-6D7DVBIK.js +2 -0
  22. package/dist/chunk-76E7CKUD.js +2 -0
  23. package/dist/chunk-AKWVXRQ6.js +2 -0
  24. package/dist/chunk-FHHSTO6Z.js +2 -0
  25. package/dist/chunk-HPL723JA.js +2 -0
  26. package/dist/chunk-NVGTF73S.js +2 -0
  27. package/dist/chunk-PNIB4OM3.js +2 -0
  28. package/dist/chunk-UKJ5AKQX.js +595 -0
  29. package/dist/chunk-UYJTX3SD.js +2 -0
  30. package/dist/combined.css +3068 -0
  31. package/dist/css-modules-manifest.json +297 -0
  32. package/dist/dist-Y6PZ2RN3.js +12 -0
  33. package/dist/drawing/index.cjs +53 -0
  34. package/dist/drawing/index.d.mts +2 -0
  35. package/dist/drawing/index.d.ts +2 -0
  36. package/dist/drawing/index.js +2 -0
  37. package/dist/drawing/index.umd.js +54 -0
  38. package/dist/dts/drawing-shim.d.ts +3 -0
  39. package/dist/dts/index.d.ts +31 -0
  40. package/dist/dts/lib/Chart.d.ts +31 -0
  41. package/dist/dts/lib/ChartContext.d.ts +10 -0
  42. package/dist/dts/lib/EventCapture.d.ts +3 -0
  43. package/dist/dts/lib/GenericChartComponent.d.ts +5 -0
  44. package/dist/dts/lib/GenericComponent.d.ts +124 -0
  45. package/dist/dts/lib/StockChartContext.d.ts +53 -0
  46. package/dist/dts/lib/adapters/BaseAdapter.d.ts +25 -0
  47. package/dist/dts/lib/adapters/BinanceAdapter.d.ts +51 -0
  48. package/dist/dts/lib/adapters/CSVAdapter.d.ts +17 -0
  49. package/dist/dts/lib/adapters/ContinuousContractAdapter.d.ts +63 -0
  50. package/dist/dts/lib/adapters/ContinuousContractTypes.d.ts +154 -0
  51. package/dist/dts/lib/adapters/DBAdapter.d.ts +16 -0
  52. package/dist/dts/lib/adapters/DataAdapter.d.ts +136 -0
  53. package/dist/dts/lib/adapters/DjangoVnstockAdapter.d.ts +15 -0
  54. package/dist/dts/lib/adapters/LocalCacheAdapter.d.ts +18 -0
  55. package/dist/dts/lib/adapters/MockAdapter.d.ts +22 -0
  56. package/dist/dts/lib/adapters/RESTAdapter.d.ts +16 -0
  57. package/dist/dts/lib/adapters/StockDataAdapter.d.ts +1 -0
  58. package/dist/dts/lib/adapters/UDFDataAdapter.d.ts +29 -0
  59. package/dist/dts/lib/adapters/VNStocksAdapter.d.ts +8 -0
  60. package/dist/dts/lib/adapters/WSAdapter.d.ts +30 -0
  61. package/dist/dts/lib/adapters/gapFixture.d.ts +71 -0
  62. package/dist/dts/lib/adapters/index.d.ts +15 -0
  63. package/dist/dts/lib/adapters/rollAlgorithms.d.ts +68 -0
  64. package/dist/dts/lib/advisory/AdvisoryPanel.d.ts +5 -0
  65. package/dist/dts/lib/alerts/AlertEvaluator.d.ts +5 -0
  66. package/dist/dts/lib/alerts/AlertManager.d.ts +123 -0
  67. package/dist/dts/lib/alerts/types.d.ts +58 -0
  68. package/dist/dts/lib/cache/cacheDebug.d.ts +3 -0
  69. package/dist/dts/lib/calendars/ExchangeCalendar.d.ts +23 -0
  70. package/dist/dts/lib/calendars/calendarRegistry.d.ts +10 -0
  71. package/dist/dts/lib/calendars/index.d.ts +3 -0
  72. package/dist/dts/lib/core/ChartPane.d.ts +8 -0
  73. package/dist/dts/lib/core/ChartSplitter.d.ts +70 -0
  74. package/dist/dts/lib/core/ChartTerminal.d.ts +12 -0
  75. package/dist/dts/lib/core/ErrorBoundary.d.ts +17 -0
  76. package/dist/dts/lib/core/IndicatorLegend.d.ts +47 -0
  77. package/dist/dts/lib/core/PaneHeader.d.ts +24 -0
  78. package/dist/dts/lib/core/PaneLabel.d.ts +8 -0
  79. package/dist/dts/lib/core/PaneSplitter.d.ts +9 -0
  80. package/dist/dts/lib/core/SeriesPicker.d.ts +10 -0
  81. package/dist/dts/lib/core/calculators/alignBarsByDate.d.ts +38 -0
  82. package/dist/dts/lib/core/calculators/buildIndicatorComputationPlan.d.ts +16 -0
  83. package/dist/dts/lib/core/calculators/calcCVDApprox.d.ts +6 -0
  84. package/dist/dts/lib/core/calculators/calcStrengthElder.d.ts +7 -0
  85. package/dist/dts/lib/core/calculators/calcWhaleApprox.d.ts +6 -0
  86. package/dist/dts/lib/core/calculators/computationHelpers.d.ts +12 -0
  87. package/dist/dts/lib/core/calculators/computeIndicatorComputationResult.d.ts +3 -0
  88. package/dist/dts/lib/core/calculators/computeMarketStructure.d.ts +8 -0
  89. package/dist/dts/lib/core/calculators/computeMomentum.d.ts +22 -0
  90. package/dist/dts/lib/core/calculators/computeMovingAverage.d.ts +15 -0
  91. package/dist/dts/lib/core/calculators/computeProfile.d.ts +9 -0
  92. package/dist/dts/lib/core/calculators/computeTrend.d.ts +10 -0
  93. package/dist/dts/lib/core/calculators/computeVolatility.d.ts +14 -0
  94. package/dist/dts/lib/core/calculators/computeVolumeFlow.d.ts +19 -0
  95. package/dist/dts/lib/core/calculators/enrichData.d.ts +7 -0
  96. package/dist/dts/lib/core/calculators/enrichDataWithCanonicalStore.d.ts +33 -0
  97. package/dist/dts/lib/core/calculators/exoticChartData.d.ts +140 -0
  98. package/dist/dts/lib/core/calculators/fixtures/mockData.d.ts +2 -0
  99. package/dist/dts/lib/core/calculators/indicatorComputation.d.ts +27 -0
  100. package/dist/dts/lib/core/calculators/indicatorComputationTypes.d.ts +249 -0
  101. package/dist/dts/lib/core/calculators/materializeIndicatorValues.d.ts +3 -0
  102. package/dist/dts/lib/core/calculators/normalizePrices.d.ts +36 -0
  103. package/dist/dts/lib/core/calculators/resolveCalculationOrder.d.ts +17 -0
  104. package/dist/dts/lib/core/calculators/types.d.ts +269 -0
  105. package/dist/dts/lib/core/canvas/ChartRenderContext.d.ts +14 -0
  106. package/dist/dts/lib/core/canvas/OverlayCanvas.d.ts +19 -0
  107. package/dist/dts/lib/core/context/ChartSyncContext.d.ts +21 -0
  108. package/dist/dts/lib/core/context/DataContext.d.ts +15 -0
  109. package/dist/dts/lib/core/context/PaneManagerContext.d.ts +10 -0
  110. package/dist/dts/lib/core/hooks/paneSizingHelpers.d.ts +13 -0
  111. package/dist/dts/lib/core/hooks/useCanvasResize.d.ts +8 -0
  112. package/dist/dts/lib/core/hooks/useChartTheme.d.ts +12 -0
  113. package/dist/dts/lib/core/hooks/useDynamicPanes.d.ts +155 -0
  114. package/dist/dts/lib/core/hooks/useIndicatorSets.d.ts +20 -0
  115. package/dist/dts/lib/core/hooks/usePaneManager.d.ts +39 -0
  116. package/dist/dts/lib/core/hooks/usePaneSizes.d.ts +52 -0
  117. package/dist/dts/lib/core/index.d.ts +41 -0
  118. package/dist/dts/lib/core/paneScaleSlotDomains.d.ts +3 -0
  119. package/dist/dts/lib/core/registry/SeriesRegistry.d.ts +22 -0
  120. package/dist/dts/lib/core/registry/filterPanesBySeriesTier.d.ts +43 -0
  121. package/dist/dts/lib/core/registry/marketStructure.d.ts +7 -0
  122. package/dist/dts/lib/core/registry/momentum.d.ts +20 -0
  123. package/dist/dts/lib/core/registry/movingAverage.d.ts +14 -0
  124. package/dist/dts/lib/core/registry/priceChartTypes.d.ts +16 -0
  125. package/dist/dts/lib/core/registry/profile.d.ts +8 -0
  126. package/dist/dts/lib/core/registry/registerAll.d.ts +1 -0
  127. package/dist/dts/lib/core/registry/registerPhaseOne.d.ts +3 -0
  128. package/dist/dts/lib/core/registry/registryCore.d.ts +77 -0
  129. package/dist/dts/lib/core/registry/trend.d.ts +11 -0
  130. package/dist/dts/lib/core/registry/volatility.d.ts +11 -0
  131. package/dist/dts/lib/core/registry/volumeFlow.d.ts +20 -0
  132. package/dist/dts/lib/core/replay/BarReplayController.d.ts +62 -0
  133. package/dist/dts/lib/core/replay/ReplayEventBus.d.ts +68 -0
  134. package/dist/dts/lib/core/replay/ReplayFillSimulator.d.ts +33 -0
  135. package/dist/dts/lib/core/replay/ReplayOrderBook.d.ts +24 -0
  136. package/dist/dts/lib/core/replay/ReplayPositionManager.d.ts +30 -0
  137. package/dist/dts/lib/core/replay/ReplaySessionAnalytics.d.ts +31 -0
  138. package/dist/dts/lib/core/replay/createReplayTradeMarkerPrimitives.d.ts +7 -0
  139. package/dist/dts/lib/core/replay/pnlUtils.d.ts +2 -0
  140. package/dist/dts/lib/core/replay/replayBrokerAdapters.d.ts +51 -0
  141. package/dist/dts/lib/core/replay/replayTradingTypes.d.ts +61 -0
  142. package/dist/dts/lib/core/scales/computeScales.d.ts +8 -0
  143. package/dist/dts/lib/core/seriesValueResolver.d.ts +27 -0
  144. package/dist/dts/lib/core/sets/builtins.d.ts +2 -0
  145. package/dist/dts/lib/core/sets/indicatorSetCodec.d.ts +15 -0
  146. package/dist/dts/lib/core/trading/AnalyticsEngine.d.ts +56 -0
  147. package/dist/dts/lib/core/trading/BrokerAPI.d.ts +40 -0
  148. package/dist/dts/lib/core/trading/ExecutionSimulator.d.ts +53 -0
  149. package/dist/dts/lib/core/trading/FillSettlement.d.ts +38 -0
  150. package/dist/dts/lib/core/trading/MarketDataPort.d.ts +41 -0
  151. package/dist/dts/lib/core/trading/MarketRules.d.ts +58 -0
  152. package/dist/dts/lib/core/trading/OrderManagementSystem.d.ts +57 -0
  153. package/dist/dts/lib/core/trading/PositionManager.d.ts +79 -0
  154. package/dist/dts/lib/core/trading/RiskEngine.d.ts +40 -0
  155. package/dist/dts/lib/core/trading/SettlementCalendar.d.ts +10 -0
  156. package/dist/dts/lib/core/trading/VirtualBrokerEngine.d.ts +92 -0
  157. package/dist/dts/lib/core/trading/orderMargin.d.ts +3 -0
  158. package/dist/dts/lib/core/trading/storage/InMemoryStorageAdapter.d.ts +10 -0
  159. package/dist/dts/lib/core/trading/storage/TradingStorage.d.ts +34 -0
  160. package/dist/dts/lib/core/trading/types.d.ts +99 -0
  161. package/dist/dts/lib/core/types/chart.d.ts +21 -0
  162. package/dist/dts/lib/core/types/indicator-catalog.d.ts +38 -0
  163. package/dist/dts/lib/core/types/indicator-set.d.ts +19 -0
  164. package/dist/dts/lib/core/types/pane-descriptor.d.ts +46 -0
  165. package/dist/dts/lib/core/types/seriesComponents.d.ts +15 -0
  166. package/dist/dts/lib/credentials/credentialStore.d.ts +93 -0
  167. package/dist/dts/lib/helper/SaveChartAsImage.d.ts +90 -0
  168. package/dist/dts/lib/indicator/defaultOptionsForAppearance.d.ts +105 -0
  169. package/dist/dts/lib/indicators/builtin/MTFWrapper.d.ts +3 -0
  170. package/dist/dts/lib/indicators/builtin/VolumeProfileWorker.d.ts +19 -0
  171. package/dist/dts/lib/indicators/builtin/ac.d.ts +4 -0
  172. package/dist/dts/lib/indicators/builtin/alligator.d.ts +5 -0
  173. package/dist/dts/lib/indicators/builtin/anchoredVwap.d.ts +5 -0
  174. package/dist/dts/lib/indicators/builtin/ao.d.ts +4 -0
  175. package/dist/dts/lib/indicators/builtin/bbi.d.ts +10 -0
  176. package/dist/dts/lib/indicators/builtin/bias.d.ts +4 -0
  177. package/dist/dts/lib/indicators/builtin/bollinger.d.ts +9 -0
  178. package/dist/dts/lib/indicators/builtin/brar.d.ts +4 -0
  179. package/dist/dts/lib/indicators/builtin/cci.d.ts +4 -0
  180. package/dist/dts/lib/indicators/builtin/chaikinOscillator.d.ts +14 -0
  181. package/dist/dts/lib/indicators/builtin/chaikinVol.d.ts +4 -0
  182. package/dist/dts/lib/indicators/builtin/ci.d.ts +4 -0
  183. package/dist/dts/lib/indicators/builtin/cmf.d.ts +4 -0
  184. package/dist/dts/lib/indicators/builtin/cr.d.ts +4 -0
  185. package/dist/dts/lib/indicators/builtin/cvd.d.ts +4 -0
  186. package/dist/dts/lib/indicators/builtin/deltaProfile.d.ts +5 -0
  187. package/dist/dts/lib/indicators/builtin/dema.d.ts +4 -0
  188. package/dist/dts/lib/indicators/builtin/dma.d.ts +4 -0
  189. package/dist/dts/lib/indicators/builtin/dmi.d.ts +4 -0
  190. package/dist/dts/lib/indicators/builtin/donchian.d.ts +5 -0
  191. package/dist/dts/lib/indicators/builtin/ema.d.ts +4 -0
  192. package/dist/dts/lib/indicators/builtin/emv.d.ts +4 -0
  193. package/dist/dts/lib/indicators/builtin/footprint.d.ts +5 -0
  194. package/dist/dts/lib/indicators/builtin/fractals.d.ts +5 -0
  195. package/dist/dts/lib/indicators/builtin/gator.d.ts +5 -0
  196. package/dist/dts/lib/indicators/builtin/hma.d.ts +4 -0
  197. package/dist/dts/lib/indicators/builtin/hv.d.ts +4 -0
  198. package/dist/dts/lib/indicators/builtin/ichimoku.d.ts +5 -0
  199. package/dist/dts/lib/indicators/builtin/kdj.d.ts +4 -0
  200. package/dist/dts/lib/indicators/builtin/keltner.d.ts +5 -0
  201. package/dist/dts/lib/indicators/builtin/ma.d.ts +10 -0
  202. package/dist/dts/lib/indicators/builtin/maRibbon.d.ts +5 -0
  203. package/dist/dts/lib/indicators/builtin/macd.d.ts +9 -0
  204. package/dist/dts/lib/indicators/builtin/marketProfile.d.ts +5 -0
  205. package/dist/dts/lib/indicators/builtin/mfi.d.ts +4 -0
  206. package/dist/dts/lib/indicators/builtin/mtm.d.ts +4 -0
  207. package/dist/dts/lib/indicators/builtin/obv.d.ts +10 -0
  208. package/dist/dts/lib/indicators/builtin/pivotHighLow.d.ts +5 -0
  209. package/dist/dts/lib/indicators/builtin/pivotStandard.d.ts +5 -0
  210. package/dist/dts/lib/indicators/builtin/psy.d.ts +4 -0
  211. package/dist/dts/lib/indicators/builtin/pvt.d.ts +4 -0
  212. package/dist/dts/lib/indicators/builtin/roc.d.ts +4 -0
  213. package/dist/dts/lib/indicators/builtin/rsi.d.ts +4 -0
  214. package/dist/dts/lib/indicators/builtin/sar.d.ts +10 -0
  215. package/dist/dts/lib/indicators/builtin/sma.d.ts +4 -0
  216. package/dist/dts/lib/indicators/builtin/smfi.d.ts +8 -0
  217. package/dist/dts/lib/indicators/builtin/stdDev.d.ts +4 -0
  218. package/dist/dts/lib/indicators/builtin/strengthRelative.d.ts +7 -0
  219. package/dist/dts/lib/indicators/builtin/supertrend.d.ts +5 -0
  220. package/dist/dts/lib/indicators/builtin/tema.d.ts +4 -0
  221. package/dist/dts/lib/indicators/builtin/trix.d.ts +4 -0
  222. package/dist/dts/lib/indicators/builtin/volOsc.d.ts +4 -0
  223. package/dist/dts/lib/indicators/builtin/volume.d.ts +4 -0
  224. package/dist/dts/lib/indicators/builtin/volumeProfile.d.ts +8 -0
  225. package/dist/dts/lib/indicators/builtin/vr.d.ts +10 -0
  226. package/dist/dts/lib/indicators/builtin/vwap.d.ts +5 -0
  227. package/dist/dts/lib/indicators/builtin/vwma.d.ts +4 -0
  228. package/dist/dts/lib/indicators/builtin/wma.d.ts +4 -0
  229. package/dist/dts/lib/indicators/builtin/wr.d.ts +10 -0
  230. package/dist/dts/lib/indicators/builtin/wyckoffWave.d.ts +15 -0
  231. package/dist/dts/lib/indicators/index.d.ts +63 -0
  232. package/dist/dts/lib/indicators/indicatorValueShapes.d.ts +15 -0
  233. package/dist/dts/lib/indicators/outputKeys.d.ts +50 -0
  234. package/dist/dts/lib/indicators/overlays/CVDIndicator.d.ts +26 -0
  235. package/dist/dts/lib/indicators/overlays/DarkFlowBadge.d.ts +19 -0
  236. package/dist/dts/lib/indicators/overlays/ExternalCVDOverlay.d.ts +15 -0
  237. package/dist/dts/lib/indicators/overlays/WhaleBubbleOverlay.d.ts +14 -0
  238. package/dist/dts/lib/indicators/overlays/WhaleMarketBubbleOverlay.d.ts +27 -0
  239. package/dist/dts/lib/indicators/overlays/whaleDetector.d.ts +66 -0
  240. package/dist/dts/lib/indicators/registry.d.ts +6 -0
  241. package/dist/dts/lib/indicators/types.d.ts +5 -0
  242. package/dist/dts/lib/indicators/utils.d.ts +259 -0
  243. package/dist/dts/lib/pinescript/PineCompiler.d.ts +34 -0
  244. package/dist/dts/lib/pinescript/ast.d.ts +73 -0
  245. package/dist/dts/lib/pinescript/compile.d.ts +40 -0
  246. package/dist/dts/lib/pinescript/grammar.d.ts +12 -0
  247. package/dist/dts/lib/pinescript/pine.worker.d.ts +1 -0
  248. package/dist/dts/lib/pinescript/pineBlocks.d.ts +54 -0
  249. package/dist/dts/lib/pinescript/pineBuiltins.d.ts +47 -0
  250. package/dist/dts/lib/pinescript/pineEnv.d.ts +46 -0
  251. package/dist/dts/lib/pinescript/pineMath.d.ts +13 -0
  252. package/dist/dts/lib/pinescript/pineParse.d.ts +25 -0
  253. package/dist/dts/lib/pinescript/pineStrings.d.ts +50 -0
  254. package/dist/dts/lib/pinescript/runtime.d.ts +5 -0
  255. package/dist/dts/lib/pinescript/scriptRegistry.d.ts +40 -0
  256. package/dist/dts/lib/pinescript/series-value.d.ts +64 -0
  257. package/dist/dts/lib/pinescript/vnscript-completion.d.ts +1 -0
  258. package/dist/dts/lib/pinescript/vnscript-grammar.d.ts +19 -0
  259. package/dist/dts/lib/scale/discontinuousTimeScaleProvider.d.ts +3 -0
  260. package/dist/dts/lib/scale/financeDiscontinuousScale.d.ts +15 -0
  261. package/dist/dts/lib/scale/index.d.ts +1 -0
  262. package/dist/dts/lib/scale/levels.d.ts +12 -0
  263. package/dist/dts/lib/series/AlternatingFillAreaSeries.d.ts +13 -0
  264. package/dist/dts/lib/series/AreaOnlySeries.d.ts +10 -0
  265. package/dist/dts/lib/series/AreaSeries.d.ts +30 -0
  266. package/dist/dts/lib/series/BarSeries.d.ts +40 -0
  267. package/dist/dts/lib/series/BollingerSeries.d.ts +11 -0
  268. package/dist/dts/lib/series/CandlestickSeries.d.ts +56 -0
  269. package/dist/dts/lib/series/CircleMarker.d.ts +28 -0
  270. package/dist/dts/lib/series/ElderRaySeries.d.ts +14 -0
  271. package/dist/dts/lib/series/FootprintSeries.d.ts +21 -0
  272. package/dist/dts/lib/series/GroupedBarSeries.d.ts +9 -0
  273. package/dist/dts/lib/series/HTFOverlaySeries.d.ts +32 -0
  274. package/dist/dts/lib/series/HistogramSeries.d.ts +51 -0
  275. package/dist/dts/lib/series/KagiSeries.d.ts +9 -0
  276. package/dist/dts/lib/series/LineBreakSeries.d.ts +28 -0
  277. package/dist/dts/lib/series/LineSeries.d.ts +54 -0
  278. package/dist/dts/lib/series/MACDSeries.d.ts +28 -0
  279. package/dist/dts/lib/series/MarketProfileSeries.d.ts +18 -0
  280. package/dist/dts/lib/series/OHLCSeries.d.ts +9 -0
  281. package/dist/dts/lib/series/OverlayBarSeries.d.ts +9 -0
  282. package/dist/dts/lib/series/PointAndFigureSeries.d.ts +45 -0
  283. package/dist/dts/lib/series/RSISeries.d.ts +38 -0
  284. package/dist/dts/lib/series/RenkoSeries.d.ts +9 -0
  285. package/dist/dts/lib/series/SARSeries.d.ts +10 -0
  286. package/dist/dts/lib/series/SVGComponent.d.ts +5 -0
  287. package/dist/dts/lib/series/ScatterSeries.d.ts +9 -0
  288. package/dist/dts/lib/series/SquareMarker.d.ts +28 -0
  289. package/dist/dts/lib/series/StackedBarSeries.d.ts +19 -0
  290. package/dist/dts/lib/series/StochasticSeries.d.ts +9 -0
  291. package/dist/dts/lib/series/StraightLine.d.ts +18 -0
  292. package/dist/dts/lib/series/TriangleMarker.d.ts +30 -0
  293. package/dist/dts/lib/series/VolumeProfileSeries.d.ts +9 -0
  294. package/dist/dts/lib/series/index.d.ts +28 -0
  295. package/dist/dts/lib/strategy/BrokerSimulator.d.ts +11 -0
  296. package/dist/dts/lib/strategy/types.d.ts +35 -0
  297. package/dist/dts/lib/tape/TapePanel.d.ts +5 -0
  298. package/dist/dts/lib/types/adapter.d.ts +1 -0
  299. package/dist/dts/lib/types/index.d.ts +5 -0
  300. package/dist/dts/lib/types/indicator.d.ts +11 -0
  301. package/dist/dts/lib/types/ohlcv.d.ts +1 -0
  302. package/dist/dts/lib/types/pane.d.ts +23 -0
  303. package/dist/dts/lib/types/runtime.d.ts +11 -0
  304. package/dist/dts/lib/types/vninvest.d.ts +320 -0
  305. package/dist/dts/lib/types.d.ts +45 -0
  306. package/dist/dts/lib/utils/ChartDataUtil.d.ts +26 -0
  307. package/dist/dts/lib/utils/PureComponent.d.ts +5 -0
  308. package/dist/dts/lib/utils/accumulatingWindow.d.ts +1 -0
  309. package/dist/dts/lib/utils/axisPriceFormat.d.ts +6 -0
  310. package/dist/dts/lib/utils/barWidth.d.ts +14 -0
  311. package/dist/dts/lib/utils/identity.d.ts +1 -0
  312. package/dist/dts/lib/utils/index.d.ts +70 -0
  313. package/dist/dts/lib/utils/logger.d.ts +28 -0
  314. package/dist/dts/lib/utils/mappedSlidingWindow.d.ts +1 -0
  315. package/dist/dts/lib/utils/merge.d.ts +6 -0
  316. package/dist/dts/lib/utils/noop.d.ts +1 -0
  317. package/dist/dts/lib/utils/rebind.d.ts +1 -0
  318. package/dist/dts/lib/utils/shallowEqual.d.ts +1 -0
  319. package/dist/dts/lib/utils/slidingWindow.d.ts +1 -0
  320. package/dist/dts/lib/utils/storage.d.ts +32 -0
  321. package/dist/dts/lib/utils/strokeDasharray.d.ts +3 -0
  322. package/dist/dts/lib/utils/timezoneFormatter.d.ts +14 -0
  323. package/dist/dts/lib/utils/zipper.d.ts +4 -0
  324. package/dist/dts/public-api.d.ts +31 -0
  325. package/dist/dts/widget/BackfillWorkerFlags.d.ts +12 -0
  326. package/dist/dts/widget/CanaryRollbackHelper.d.ts +95 -0
  327. package/dist/dts/widget/CanaryRolloutConfig.d.ts +100 -0
  328. package/dist/dts/widget/DrawingPriceLabelsOverlay.d.ts +20 -0
  329. package/dist/dts/widget/ForkDrawingsOverlay.d.ts +16 -0
  330. package/dist/dts/widget/MeasurementOverlay.d.ts +24 -0
  331. package/dist/dts/widget/VNInvestCharts.d.ts +5 -0
  332. package/dist/dts/widget/VNInvestChartsProps.d.ts +302 -0
  333. package/dist/dts/widget/VNInvestMultiCharts.d.ts +8 -0
  334. package/dist/dts/widget/VNInvestMultiCharts.types.d.ts +130 -0
  335. package/dist/dts/widget/WidgetEmptyState.d.ts +11 -0
  336. package/dist/dts/widget/WidgetErrorBoundary.d.ts +26 -0
  337. package/dist/dts/widget/adapters/ContinuousFuturesStockDataAdapter.d.ts +18 -0
  338. package/dist/dts/widget/adapters/DataProviderAdapterWrapper.d.ts +14 -0
  339. package/dist/dts/widget/adapters/MultiSourceDataAdapter.d.ts +24 -0
  340. package/dist/dts/widget/adapters/VNInvestClient.d.ts +161 -0
  341. package/dist/dts/widget/adapters/VNInvestDataAdapter.d.ts +77 -0
  342. package/dist/dts/widget/adapters/VNInvestWebSocketClient.d.ts +79 -0
  343. package/dist/dts/widget/adapters/barsPagingPolicy.d.ts +18 -0
  344. package/dist/dts/widget/adapters/corporateEvents.d.ts +13 -0
  345. package/dist/dts/widget/adapters/index.d.ts +20 -0
  346. package/dist/dts/widget/adapters/nativeShapes.d.ts +32 -0
  347. package/dist/dts/widget/adapters/watchlistRealtimeSync.d.ts +16 -0
  348. package/dist/dts/widget/alerts/DrawingAlertsHost.d.ts +18 -0
  349. package/dist/dts/widget/alerts/useDrawingAlerts.d.ts +37 -0
  350. package/dist/dts/widget/canaryBarFiltering.d.ts +35 -0
  351. package/dist/dts/widget/capabilities/CapabilityResolver.d.ts +71 -0
  352. package/dist/dts/widget/capabilities/capabilityProbe.d.ts +28 -0
  353. package/dist/dts/widget/capabilities/useTierGatedFeatures.d.ts +48 -0
  354. package/dist/dts/widget/components/BottomPanelHost.d.ts +80 -0
  355. package/dist/dts/widget/components/BottomPanelSplitter.d.ts +15 -0
  356. package/dist/dts/widget/components/CapabilityGate.d.ts +65 -0
  357. package/dist/dts/widget/components/ChartDiagOverlay.d.ts +31 -0
  358. package/dist/dts/widget/components/ConfirmDialog.d.ts +12 -0
  359. package/dist/dts/widget/components/DowngradeBanner.d.ts +9 -0
  360. package/dist/dts/widget/components/ForkPaneSeparators.d.ts +11 -0
  361. package/dist/dts/widget/components/ForkPaneTooltips.d.ts +23 -0
  362. package/dist/dts/widget/components/ForkXAxisOverlay.d.ts +11 -0
  363. package/dist/dts/widget/components/ForkYAxisCrosshairLabels.d.ts +9 -0
  364. package/dist/dts/widget/components/LayoutDesigner.d.ts +26 -0
  365. package/dist/dts/widget/components/PremiumFeatureGate.d.ts +10 -0
  366. package/dist/dts/widget/components/ShortcutHelpModal.d.ts +44 -0
  367. package/dist/dts/widget/components/SystemMenu.d.ts +66 -0
  368. package/dist/dts/widget/components/Toast.d.ts +20 -0
  369. package/dist/dts/widget/components/canvas/BarCountdownBadge.d.ts +8 -0
  370. package/dist/dts/widget/components/canvas/ChartA11ySummary.d.ts +40 -0
  371. package/dist/dts/widget/components/canvas/ChartStatusLine.d.ts +39 -0
  372. package/dist/dts/widget/components/canvas/PricePaneHeader.d.ts +24 -0
  373. package/dist/dts/widget/components/canvas/PriceScaleMenu.d.ts +27 -0
  374. package/dist/dts/widget/components/canvas/TimeAxisScrollbar.d.ts +18 -0
  375. package/dist/dts/widget/components/common/Icons.d.ts +67 -0
  376. package/dist/dts/widget/components/dock/DataWindow.d.ts +7 -0
  377. package/dist/dts/widget/components/dock/DockUpgradeNudge.d.ts +10 -0
  378. package/dist/dts/widget/components/dock/RightSidebarDockHost.d.ts +57 -0
  379. package/dist/dts/widget/components/dock/WatchlistPanel.d.ts +7 -0
  380. package/dist/dts/widget/components/dock/WorkspaceRightDockSlot.d.ts +46 -0
  381. package/dist/dts/widget/components/dock/dockAccess.d.ts +20 -0
  382. package/dist/dts/widget/components/dock/drawingDockContentBuilders.d.ts +29 -0
  383. package/dist/dts/widget/components/drawing/DrawingDock.d.ts +47 -0
  384. package/dist/dts/widget/components/drawing/DrawingInspector.d.ts +94 -0
  385. package/dist/dts/widget/components/drawing/DrawingListPanel.d.ts +62 -0
  386. package/dist/dts/widget/components/drawing/DrawingSemanticPointLegend.d.ts +14 -0
  387. package/dist/dts/widget/components/drawing/FloatingDrawingInspector.d.ts +18 -0
  388. package/dist/dts/widget/components/drawing/IconPickerPanel.d.ts +5 -0
  389. package/dist/dts/widget/components/drawing/InlineTextEditor.d.ts +20 -0
  390. package/dist/dts/widget/components/drawing/PatternScanPanel.d.ts +27 -0
  391. package/dist/dts/widget/components/drawing/TemplateManagerPanel.d.ts +18 -0
  392. package/dist/dts/widget/components/events/CorporateEventsOverlay.d.ts +23 -0
  393. package/dist/dts/widget/components/events/EventMarkerIcon.d.ts +6 -0
  394. package/dist/dts/widget/components/footer/ChartFooter.d.ts +26 -0
  395. package/dist/dts/widget/components/footer/MultiChartsFooter.d.ts +37 -0
  396. package/dist/dts/widget/components/footer/TimeframeFooter.d.ts +25 -0
  397. package/dist/dts/widget/components/footer/useBarCountdown.d.ts +5 -0
  398. package/dist/dts/widget/components/header/OHLCHeader.d.ts +72 -0
  399. package/dist/dts/widget/components/layout/DrawingConflictNotice.d.ts +4 -0
  400. package/dist/dts/widget/components/layout/GridContainer.d.ts +70 -0
  401. package/dist/dts/widget/components/layout/GridSlotErrorBoundary.d.ts +17 -0
  402. package/dist/dts/widget/components/layout/Splitter.d.ts +23 -0
  403. package/dist/dts/widget/components/layout/gridSplitterMath.d.ts +40 -0
  404. package/dist/dts/widget/components/layout/useGridSplitterDrag.d.ts +18 -0
  405. package/dist/dts/widget/components/mobile/MobileChartCarousel.d.ts +11 -0
  406. package/dist/dts/widget/components/mobile/MobileToolbar.d.ts +29 -0
  407. package/dist/dts/widget/components/overlays/AdvisoryPanel.d.ts +25 -0
  408. package/dist/dts/widget/components/overlays/TapePanel.d.ts +25 -0
  409. package/dist/dts/widget/components/overlays/WhalePanel.d.ts +5 -0
  410. package/dist/dts/widget/components/panels/AdvisoryPanel.d.ts +25 -0
  411. package/dist/dts/widget/components/panels/PineEditorPanel.d.ts +18 -0
  412. package/dist/dts/widget/components/panels/StrategyTesterPanel.d.ts +7 -0
  413. package/dist/dts/widget/components/panels/TapePanel.d.ts +17 -0
  414. package/dist/dts/widget/components/panels/index.d.ts +8 -0
  415. package/dist/dts/widget/components/replay/FloatingReplayToolbar.d.ts +24 -0
  416. package/dist/dts/widget/components/replay/ReplayCutOverlay.d.ts +8 -0
  417. package/dist/dts/widget/components/search/SymbolCompareModal.d.ts +24 -0
  418. package/dist/dts/widget/components/search/SymbolSearchModal.d.ts +12 -0
  419. package/dist/dts/widget/components/search/VNSymbolSearch.d.ts +83 -0
  420. package/dist/dts/widget/components/settings/AlertsModal.d.ts +74 -0
  421. package/dist/dts/widget/components/settings/SettingsContext.d.ts +58 -0
  422. package/dist/dts/widget/components/settings/SettingsModal.d.ts +78 -0
  423. package/dist/dts/widget/components/settings/SettingsRangeSlider.d.ts +17 -0
  424. package/dist/dts/widget/components/settings/SnapshotPreviewModal.d.ts +16 -0
  425. package/dist/dts/widget/components/settings/WorkspaceSettingsContext.d.ts +27 -0
  426. package/dist/dts/widget/components/settings/helpers/seriesFormatters.d.ts +11 -0
  427. package/dist/dts/widget/components/settings/model/appearancePayload.d.ts +31 -0
  428. package/dist/dts/widget/components/settings/model/chartSettingsSchema.d.ts +100 -0
  429. package/dist/dts/widget/components/settings/model/defaultSettings.d.ts +5 -0
  430. package/dist/dts/widget/components/settings/model/indicatorShare.d.ts +29 -0
  431. package/dist/dts/widget/components/settings/storageKeys.d.ts +29 -0
  432. package/dist/dts/widget/components/settings/tabs/AppearanceSettingsTab.d.ts +5 -0
  433. package/dist/dts/widget/components/settings/tabs/IndicatorParamsForm.d.ts +12 -0
  434. package/dist/dts/widget/components/settings/tabs/IndicatorsSettingsTab.d.ts +34 -0
  435. package/dist/dts/widget/components/settings/tabs/LicensingSettingsTab.d.ts +5 -0
  436. package/dist/dts/widget/components/settings/tabs/PanesLayoutSettingsTab.d.ts +11 -0
  437. package/dist/dts/widget/components/settings/tabs/ResetSettingsTab.d.ts +8 -0
  438. package/dist/dts/widget/components/settings/tabs/ScalesSettingsTab.d.ts +5 -0
  439. package/dist/dts/widget/components/settings/tabs/StatusLineSettingsTab.d.ts +5 -0
  440. package/dist/dts/widget/components/settings/tabs/SymbolSettingsTab.d.ts +5 -0
  441. package/dist/dts/widget/components/settings/tabs/ThemePaletteSettingsTab.d.ts +9 -0
  442. package/dist/dts/widget/components/settings/tabs/TradingEventsSettingsTab.d.ts +8 -0
  443. package/dist/dts/widget/components/toolbar/DrawingToolIcon.d.ts +10 -0
  444. package/dist/dts/widget/components/toolbar/DrawingToolbar.d.ts +33 -0
  445. package/dist/dts/widget/components/toolbar/FloatingChartBar.d.ts +20 -0
  446. package/dist/dts/widget/components/toolbar/FloatingFavoritesBar.d.ts +18 -0
  447. package/dist/dts/widget/components/toolbar/MultiChartTopbar.d.ts +47 -0
  448. package/dist/dts/widget/components/toolbar/UnifiedDrawingToolbar.d.ts +28 -0
  449. package/dist/dts/widget/components/trading/PaperTradePanel.d.ts +41 -0
  450. package/dist/dts/widget/components/workspace/WorkspaceToolbar.d.ts +25 -0
  451. package/dist/dts/widget/config/toolGroups.d.ts +11 -0
  452. package/dist/dts/widget/config/toolShortcuts.d.ts +27 -0
  453. package/dist/dts/widget/constants/comparison.d.ts +1 -0
  454. package/dist/dts/widget/constants/symbolSearch.d.ts +14 -0
  455. package/dist/dts/widget/constants/vn30.d.ts +7 -0
  456. package/dist/dts/widget/context/DataProviderContext.d.ts +7 -0
  457. package/dist/dts/widget/context/HoverEmitter.d.ts +50 -0
  458. package/dist/dts/widget/context/SyncContextShare.d.ts +11 -0
  459. package/dist/dts/widget/context/VNInvestChartsConfigContext.d.ts +24 -0
  460. package/dist/dts/widget/context/VNInvestChartsContext.d.ts +70 -0
  461. package/dist/dts/widget/context/VNInvestChartsStateContext.d.ts +50 -0
  462. package/dist/dts/widget/context/WidgetI18nContext.d.ts +25 -0
  463. package/dist/dts/widget/context/WorkspaceLiveTradingContext.d.ts +30 -0
  464. package/dist/dts/widget/context/WorkspacePaperVisibilityContext.d.ts +23 -0
  465. package/dist/dts/widget/context/WorkspaceReplayTradingContext.d.ts +36 -0
  466. package/dist/dts/widget/contexts/SaaSFeatureContext.d.ts +23 -0
  467. package/dist/dts/widget/data/DataEnvelope.d.ts +100 -0
  468. package/dist/dts/widget/drawingPriceLabelInputs.d.ts +3 -0
  469. package/dist/dts/widget/export/chartCsv.d.ts +59 -0
  470. package/dist/dts/widget/forkAnchorReconciliation.d.ts +6 -0
  471. package/dist/dts/widget/forkInteractionHelpers.d.ts +69 -0
  472. package/dist/dts/widget/grid/DeviceProfiles.d.ts +49 -0
  473. package/dist/dts/widget/grid/GridChartRegistry.d.ts +9 -0
  474. package/dist/dts/widget/grid/MemoryBudgetManager.d.ts +63 -0
  475. package/dist/dts/widget/grid/PerformanceMonitor.d.ts +70 -0
  476. package/dist/dts/widget/grid/customPresets.d.ts +42 -0
  477. package/dist/dts/widget/grid/presets.d.ts +18 -0
  478. package/dist/dts/widget/grid/types.d.ts +39 -0
  479. package/dist/dts/widget/history/BackfillDedupContext.d.ts +63 -0
  480. package/dist/dts/widget/history/RequestCoordinator.d.ts +59 -0
  481. package/dist/dts/widget/history/SharedBarStoreContext.d.ts +22 -0
  482. package/dist/dts/widget/history/cache/IndexedDBCacheMatrix.d.ts +16 -0
  483. package/dist/dts/widget/history/cache/LocalCacheMatrix.d.ts +86 -0
  484. package/dist/dts/widget/history/cache/index.d.ts +3 -0
  485. package/dist/dts/widget/history/chunkStore.d.ts +77 -0
  486. package/dist/dts/widget/history/externalBarsNormalization.d.ts +9 -0
  487. package/dist/dts/widget/history/externalBarsNormalization.worker.d.ts +1 -0
  488. package/dist/dts/widget/history/externalBarsNormalizationAsync.d.ts +25 -0
  489. package/dist/dts/widget/history/historyDataUtils.d.ts +82 -0
  490. package/dist/dts/widget/history/historyWindowPlanner.d.ts +89 -0
  491. package/dist/dts/widget/history/inflightController.d.ts +15 -0
  492. package/dist/dts/widget/history/requestCoalescing.d.ts +10 -0
  493. package/dist/dts/widget/history/sessionGuards.d.ts +3 -0
  494. package/dist/dts/widget/history/singleWriterLane.d.ts +4 -0
  495. package/dist/dts/widget/history/useExternalBarsNormalization.d.ts +5 -0
  496. package/dist/dts/widget/hooks/ShortcutManager.d.ts +65 -0
  497. package/dist/dts/widget/hooks/overlays/PaneHeaderWrapper.d.ts +11 -0
  498. package/dist/dts/widget/hooks/overlays/overlayHelpers.d.ts +60 -0
  499. package/dist/dts/widget/hooks/overlays/useDrawingDockNode.d.ts +15 -0
  500. package/dist/dts/widget/hooks/overlays/useLegendChrome.d.ts +36 -0
  501. package/dist/dts/widget/hooks/overlays/useMultiSelectActions.d.ts +22 -0
  502. package/dist/dts/widget/hooks/overlays/useSidebarResize.d.ts +13 -0
  503. package/dist/dts/widget/hooks/resolveEntitlement.d.ts +73 -0
  504. package/dist/dts/widget/hooks/useBottomPanelBehavior.d.ts +38 -0
  505. package/dist/dts/widget/hooks/useBottomPanelHeight.d.ts +39 -0
  506. package/dist/dts/widget/hooks/useCanvasTheme.d.ts +24 -0
  507. package/dist/dts/widget/hooks/useChartImperativeHandle.d.ts +57 -0
  508. package/dist/dts/widget/hooks/useClockAdapter.d.ts +11 -0
  509. package/dist/dts/widget/hooks/useComparisonState.d.ts +29 -0
  510. package/dist/dts/widget/hooks/useDialogFocus.d.ts +25 -0
  511. package/dist/dts/widget/hooks/useDrawingToolShortcuts.d.ts +16 -0
  512. package/dist/dts/widget/hooks/useFeatureGate.d.ts +28 -0
  513. package/dist/dts/widget/hooks/useFloatingChartBar.d.ts +33 -0
  514. package/dist/dts/widget/hooks/useForkRuntime.d.ts +155 -0
  515. package/dist/dts/widget/hooks/useIndicatorsShareApplier.d.ts +1 -0
  516. package/dist/dts/widget/hooks/useIntersectionObserver.d.ts +49 -0
  517. package/dist/dts/widget/hooks/useKeyboardAdapter.d.ts +9 -0
  518. package/dist/dts/widget/hooks/useLayoutHistory.d.ts +8 -0
  519. package/dist/dts/widget/hooks/useLicenseDiagnostics.d.ts +15 -0
  520. package/dist/dts/widget/hooks/useMultiChartReplaySync.d.ts +31 -0
  521. package/dist/dts/widget/hooks/useMultiWorkspacePersistence.d.ts +49 -0
  522. package/dist/dts/widget/hooks/usePaperTradeConfig.d.ts +27 -0
  523. package/dist/dts/widget/hooks/usePaperTradeInteraction.d.ts +27 -0
  524. package/dist/dts/widget/hooks/usePatTierAuthentication.d.ts +42 -0
  525. package/dist/dts/widget/hooks/usePineScriptRestore.d.ts +23 -0
  526. package/dist/dts/widget/hooks/usePortalAdapter.d.ts +8 -0
  527. package/dist/dts/widget/hooks/useRecentSymbols.d.ts +3 -0
  528. package/dist/dts/widget/hooks/useReplayState.d.ts +28 -0
  529. package/dist/dts/widget/hooks/useReplayTrading.d.ts +26 -0
  530. package/dist/dts/widget/hooks/useResizeAdapter.d.ts +13 -0
  531. package/dist/dts/widget/hooks/useScaleOverlays.d.ts +62 -0
  532. package/dist/dts/widget/hooks/useScriptPersistence.d.ts +72 -0
  533. package/dist/dts/widget/hooks/useSymbolSearch.d.ts +30 -0
  534. package/dist/dts/widget/hooks/useViewportBreakpoint.d.ts +15 -0
  535. package/dist/dts/widget/hooks/useWidgetCoordinateBridge.d.ts +70 -0
  536. package/dist/dts/widget/hooks/useWidgetData.d.ts +138 -0
  537. package/dist/dts/widget/hooks/useWidgetDataBackfill.d.ts +67 -0
  538. package/dist/dts/widget/hooks/useWidgetDataEnrichment.d.ts +32 -0
  539. package/dist/dts/widget/hooks/useWidgetDrawings.d.ts +38 -0
  540. package/dist/dts/widget/hooks/useWidgetForkInteraction.d.ts +68 -0
  541. package/dist/dts/widget/hooks/useWidgetInteractionActions.d.ts +36 -0
  542. package/dist/dts/widget/hooks/useWidgetOverlays.d.ts +190 -0
  543. package/dist/dts/widget/hooks/useWidgetRuntime.d.ts +20 -0
  544. package/dist/dts/widget/hooks/useWidgetSettings.d.ts +244 -0
  545. package/dist/dts/widget/hooks/useWidgetWorkspaceIO.d.ts +24 -0
  546. package/dist/dts/widget/hooks/useWorkspaceDockPanels.d.ts +11 -0
  547. package/dist/dts/widget/hooks/useWorkspaceLiveTrading.d.ts +28 -0
  548. package/dist/dts/widget/hooks/useWorkspaceReplayTrading.d.ts +22 -0
  549. package/dist/dts/widget/i18n/a11y.messages.en.d.ts +8 -0
  550. package/dist/dts/widget/i18n/a11y.messages.vi.d.ts +3 -0
  551. package/dist/dts/widget/i18n/capability.messages.en.d.ts +7 -0
  552. package/dist/dts/widget/i18n/capability.messages.vi.d.ts +3 -0
  553. package/dist/dts/widget/i18n/dock.messages.en.d.ts +2 -0
  554. package/dist/dts/widget/i18n/dock.messages.vi.d.ts +2 -0
  555. package/dist/dts/widget/i18n/messages.en.d.ts +2 -0
  556. package/dist/dts/widget/i18n/messages.licensing.d.ts +48 -0
  557. package/dist/dts/widget/i18n/messages.vi.d.ts +2 -0
  558. package/dist/dts/widget/i18n/trading.messages.en.d.ts +2 -0
  559. package/dist/dts/widget/i18n/trading.messages.vi.d.ts +2 -0
  560. package/dist/dts/widget/i18n/types.d.ts +3 -0
  561. package/dist/dts/widget/iframe/builtInAdapters.d.ts +63 -0
  562. package/dist/dts/widget/iframe/host-entry.d.ts +11 -0
  563. package/dist/dts/widget/iframe/hostSDK.d.ts +151 -0
  564. package/dist/dts/widget/iframe/iframeBridge.d.ts +165 -0
  565. package/dist/dts/widget/iframe/iframeEntry.d.ts +52 -0
  566. package/dist/dts/widget/iframe/iframeFrame.d.ts +15 -0
  567. package/dist/dts/widget/iframe/iframeQuotes.d.ts +20 -0
  568. package/dist/dts/widget/iframe/messageProtocol.d.ts +545 -0
  569. package/dist/dts/widget/iframe/quoteHub.d.ts +20 -0
  570. package/dist/dts/widget/iframe/useVNInvestChartsHost.d.ts +8 -0
  571. package/dist/dts/widget/iife-entry.d.ts +61 -0
  572. package/dist/dts/widget/iifeWidgetInstance.d.ts +60 -0
  573. package/dist/dts/widget/index.d.ts +56 -0
  574. package/dist/dts/widget/multiChartDefaults.d.ts +18 -0
  575. package/dist/dts/widget/paneInteractionUtils.d.ts +25 -0
  576. package/dist/dts/widget/patterns/autoPatternScan.d.ts +77 -0
  577. package/dist/dts/widget/patterns/patternDrawingFactory.d.ts +87 -0
  578. package/dist/dts/widget/plugin/ProPluginRegistry.d.ts +40 -0
  579. package/dist/dts/widget/runtime/ChartScaleAdapter.d.ts +73 -0
  580. package/dist/dts/widget/runtime/ChartSerializer.d.ts +12 -0
  581. package/dist/dts/widget/runtime/ForkRuntimeAdapter.d.ts +19 -0
  582. package/dist/dts/widget/runtime/IRuntimeEngine.d.ts +40 -0
  583. package/dist/dts/widget/runtime/WorkspaceSerializer.d.ts +31 -0
  584. package/dist/dts/widget/runtimePolicy.d.ts +36 -0
  585. package/dist/dts/widget/styles/injectStyles.d.ts +9 -0
  586. package/dist/dts/widget/theme/ThemeConfig.d.ts +21 -0
  587. package/dist/dts/widget/theme/applyTheme.d.ts +3 -0
  588. package/dist/dts/widget/trading/chart/DraggableOrderHandles.d.ts +15 -0
  589. package/dist/dts/widget/trading/chart/InteractivePositionOverlay.d.ts +19 -0
  590. package/dist/dts/widget/trading/chart/PendingOrderOverlay.d.ts +11 -0
  591. package/dist/dts/widget/trading/chart/QuickTradingHeader.d.ts +20 -0
  592. package/dist/dts/widget/trading/chart/TradingChartSurface.d.ts +8 -0
  593. package/dist/dts/widget/trading/chart/TradingOverlaysHost.d.ts +28 -0
  594. package/dist/dts/widget/trading/chart/priceTicks.d.ts +1 -0
  595. package/dist/dts/widget/trading/chart/useFloatingDrag.d.ts +40 -0
  596. package/dist/dts/widget/trading/chart/useTradingHotkeys.d.ts +21 -0
  597. package/dist/dts/widget/trading/config/paperRuntimeConfig.d.ts +53 -0
  598. package/dist/dts/widget/trading/context/PaperPanelRegistry.d.ts +45 -0
  599. package/dist/dts/widget/trading/context/TradingContext.d.ts +80 -0
  600. package/dist/dts/widget/trading/context/WorkspaceTradingSync.d.ts +24 -0
  601. package/dist/dts/widget/trading/hooks/usePaperRuntimeConfig.d.ts +36 -0
  602. package/dist/dts/widget/trading/index.d.ts +5 -0
  603. package/dist/dts/widget/trading/panel/AccountSummaryTab.d.ts +7 -0
  604. package/dist/dts/widget/trading/panel/ActiveChartPaperPanel.d.ts +26 -0
  605. package/dist/dts/widget/trading/panel/ConnectedTradingPanel.d.ts +3 -0
  606. package/dist/dts/widget/trading/panel/HistoryTab.d.ts +5 -0
  607. package/dist/dts/widget/trading/panel/MarketFallbackBanner.d.ts +4 -0
  608. package/dist/dts/widget/trading/panel/OrdersTab.d.ts +8 -0
  609. package/dist/dts/widget/trading/panel/PaperCapitalDialog.d.ts +8 -0
  610. package/dist/dts/widget/trading/panel/PaperSettingsModal.d.ts +17 -0
  611. package/dist/dts/widget/trading/panel/PositionsTab.d.ts +15 -0
  612. package/dist/dts/widget/trading/panel/TradeHistoryTab.d.ts +5 -0
  613. package/dist/dts/widget/trading/panel/TradingBottomPanel.d.ts +36 -0
  614. package/dist/dts/widget/trading/panel/TradingLogTab.d.ts +8 -0
  615. package/dist/dts/widget/trading/panel/TradingPanelHeader.d.ts +17 -0
  616. package/dist/dts/widget/trading/panel/csvExport.d.ts +18 -0
  617. package/dist/dts/widget/trading/ticket/ConnectedTradingDockPanel.d.ts +5 -0
  618. package/dist/dts/widget/trading/ticket/OrderTicketForm.d.ts +31 -0
  619. package/dist/dts/widget/trading/ticket/OrderTicketModal.d.ts +29 -0
  620. package/dist/dts/widget/trading/ticket/RegistryTradingDockPanel.d.ts +9 -0
  621. package/dist/dts/widget/trading/ticket/RiskCalculatorView.d.ts +9 -0
  622. package/dist/dts/widget/trading/ticket/TradingDockPanel.d.ts +36 -0
  623. package/dist/dts/widget/trading/ticket/orderTicketModel.d.ts +49 -0
  624. package/dist/dts/widget/trading/visibility/paperVisibility.d.ts +38 -0
  625. package/dist/dts/widget/types/dataProvider.d.ts +8 -0
  626. package/dist/dts/widget/types/fullChartHandle.d.ts +25 -0
  627. package/dist/dts/widget/types/saas.d.ts +83 -0
  628. package/dist/dts/widget/types/symbolSearch.d.ts +9 -0
  629. package/dist/dts/widget/types/watchlist.d.ts +26 -0
  630. package/dist/dts/widget/utils/axisHit.d.ts +16 -0
  631. package/dist/dts/widget/utils/chartRange.d.ts +12 -0
  632. package/dist/dts/widget/utils/chartTypeOptions.d.ts +38 -0
  633. package/dist/dts/widget/utils/clickOutside.d.ts +1 -0
  634. package/dist/dts/widget/utils/coordinateBridge.d.ts +31 -0
  635. package/dist/dts/widget/utils/crosshairSync.d.ts +50 -0
  636. package/dist/dts/widget/utils/drawingSync.d.ts +198 -0
  637. package/dist/dts/widget/utils/enrichedHash.d.ts +15 -0
  638. package/dist/dts/widget/utils/headerSync.d.ts +12 -0
  639. package/dist/dts/widget/utils/numberFormat.d.ts +13 -0
  640. package/dist/dts/widget/utils/paperTradeAdapters.d.ts +11 -0
  641. package/dist/dts/widget/utils/pineSeriesData.d.ts +71 -0
  642. package/dist/dts/widget/utils/rangeSync.d.ts +29 -0
  643. package/dist/dts/widget/utils/telemetry.d.ts +19 -0
  644. package/dist/dts/widget/utils/widgetEquality.d.ts +57 -0
  645. package/dist/dts/widget/utils/widgetErrors.d.ts +29 -0
  646. package/dist/dts/widget/utils/widgetHelpers.d.ts +395 -0
  647. package/dist/dts/widget/utils/xAxisTickFormatter.d.ts +33 -0
  648. package/dist/dts/widget/visibleRangeBridge.d.ts +28 -0
  649. package/dist/dts/widget/visibleRangeDiagnostics.d.ts +10 -0
  650. package/dist/dts/widget/visibleRangePolicies.d.ts +6 -0
  651. package/dist/dts/widget/workspace/WorkspaceManager.d.ts +23 -0
  652. package/dist/dts/widget/workspace/WorkspaceStore.d.ts +85 -0
  653. package/dist/dts/widget/workspace/types.d.ts +21 -0
  654. package/dist/externalBarsNormalization.worker.js +108 -0
  655. package/dist/iframe/index.html +63 -0
  656. package/dist/iframe/injected.css +6456 -0
  657. package/dist/iframe/vninvestchart.iframe.css +2 -0
  658. package/dist/iframe/vninvestchart.iframe.js +945 -0
  659. package/dist/iframe-host/host-entry.cjs +687 -0
  660. package/dist/iframe-host/host-entry.d.mts +818 -0
  661. package/dist/iframe-host/host-entry.d.ts +818 -0
  662. package/dist/iframe-host/host-entry.js +680 -0
  663. package/dist/index.cjs +7253 -0
  664. package/dist/index.css +3390 -0
  665. package/dist/index.d.ts +31 -0
  666. package/dist/index.js +6461 -0
  667. package/dist/injected.css +6456 -0
  668. package/dist/rollAlgorithms-2P2ZKKHO.js +2 -0
  669. package/dist/types/runtime.cjs +8 -0
  670. package/dist/types/runtime.d.mts +92 -0
  671. package/dist/types/runtime.d.ts +92 -0
  672. package/dist/types/runtime.js +5 -0
  673. package/dist/types/runtime.umd.js +14 -0
  674. package/dist/vninvestchart.iife.css +2 -0
  675. package/dist/vninvestchart.iife.js +945 -0
  676. package/package.json +225 -5
@@ -0,0 +1,2535 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@vninvestcharts/engine-core'), require('react')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@vninvestcharts/engine-core', 'react'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.VNInvestChartsAdapters = {}, global.engineCore, global.react));
5
+ })(this, (function (exports, engineCore, react) { 'use strict';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+
17
+ // src/lib/adapters/rollAlgorithms.ts
18
+ var rollAlgorithms_exports = {};
19
+ __export(rollAlgorithms_exports, {
20
+ computeRollAdjustment: () => computeRollAdjustment,
21
+ computeSingleRollAdjustment: () => computeSingleRollAdjustment,
22
+ generateTestBarsWithRollGap: () => generateTestBarsWithRollGap,
23
+ generateTestContractChain: () => generateTestContractChain,
24
+ verifyNoPriceGaps: () => verifyNoPriceGaps
25
+ });
26
+ function computeRollAdjustment(input) {
27
+ const { contracts, contractBars, config, from, to } = input;
28
+ const { rollMethod, adjustVolumes } = config;
29
+ const allBars = [];
30
+ const rollPoints = [];
31
+ const warnings = [];
32
+ let cumulativeAdjustment = 0;
33
+ let currentRatioFactor = 1;
34
+ let currentPriceOffset = 0;
35
+ for (let i = 0; i < contracts.length; i++) {
36
+ const contract = contracts[i];
37
+ const bars = contractBars.get(contract.symbol) ?? [];
38
+ const contractStart = Math.max(contract.firstTradeDate, from);
39
+ const contractEnd = Math.min(contract.lastTradeDate, to);
40
+ let relevantBars = bars.filter(
41
+ (b) => b.timestamp >= contractStart && b.timestamp <= contractEnd
42
+ );
43
+ if (relevantBars.length === 0) {
44
+ warnings.push(`No data for contract ${contract.symbol} in range [${new Date(contractStart).toISOString()}, ${new Date(contractEnd).toISOString()}]`);
45
+ continue;
46
+ }
47
+ if (i > 0) {
48
+ relevantBars = applyCumulativeAdjustment(relevantBars, rollMethod, currentRatioFactor, currentPriceOffset, adjustVolumes);
49
+ }
50
+ allBars.push(...relevantBars);
51
+ if (i < contracts.length - 1) {
52
+ const nextContract = contracts[i + 1];
53
+ const nextBars = contractBars.get(nextContract.symbol) ?? [];
54
+ const rollDate = contract.lastTradeDate;
55
+ const fromBar = findBarAtOrBefore(relevantBars, rollDate);
56
+ const toBar = findBarAtOrAfter(nextBars, rollDate);
57
+ if (fromBar && toBar) {
58
+ const fromPrice = fromBar.close;
59
+ const toPrice = toBar.close;
60
+ const fromBarRaw = findBarAtOrBefore(bars, rollDate);
61
+ const rawFromPrice = fromBarRaw ? fromBarRaw.close : fromPrice;
62
+ const rawToPrice = toPrice;
63
+ let adjustmentFactor = 1;
64
+ let priceOffset = 0;
65
+ if (rollMethod === "ratio") {
66
+ adjustmentFactor = rawFromPrice / rawToPrice;
67
+ currentRatioFactor *= adjustmentFactor;
68
+ } else if (rollMethod === "panama") {
69
+ priceOffset = rawFromPrice - rawToPrice;
70
+ currentPriceOffset += priceOffset;
71
+ cumulativeAdjustment += priceOffset;
72
+ } else if (rollMethod === "backward-ratio") {
73
+ adjustmentFactor = rawToPrice / rawFromPrice;
74
+ currentRatioFactor *= adjustmentFactor;
75
+ }
76
+ const adjustedFromPrice = fromPrice;
77
+ let adjustedToPrice = toPrice;
78
+ if (rollMethod === "ratio") {
79
+ adjustedToPrice = toPrice * currentRatioFactor;
80
+ } else if (rollMethod === "panama") {
81
+ adjustedToPrice = toPrice + currentPriceOffset;
82
+ } else if (rollMethod === "backward-ratio") {
83
+ adjustedToPrice = toPrice / currentRatioFactor;
84
+ }
85
+ rollPoints.push({
86
+ timestamp: rollDate,
87
+ fromContract: contract.symbol,
88
+ toContract: nextContract.symbol,
89
+ fromPrice: adjustedFromPrice,
90
+ toPrice: adjustedToPrice,
91
+ adjustmentFactor: rollMethod === "panama" ? priceOffset : adjustmentFactor,
92
+ cumulativeAdjustment,
93
+ method: rollMethod
94
+ });
95
+ } else {
96
+ warnings.push(`Could not determine roll prices at ${new Date(rollDate).toISOString()} for ${contract.symbol} -> ${nextContract.symbol}`);
97
+ }
98
+ }
99
+ }
100
+ allBars.sort((a, b) => a.timestamp - b.timestamp);
101
+ const dedupedBars = deduplicateBars(allBars);
102
+ return {
103
+ bars: dedupedBars,
104
+ rollPoints,
105
+ totalCumulativeAdjustment: cumulativeAdjustment,
106
+ warnings
107
+ };
108
+ }
109
+ function applyCumulativeAdjustment(bars, method, ratioFactor, priceOffset, adjustVolumes) {
110
+ return bars.map((bar) => {
111
+ let { open, high, low, close, volume } = bar;
112
+ if (method === "ratio") {
113
+ open *= ratioFactor;
114
+ high *= ratioFactor;
115
+ low *= ratioFactor;
116
+ close *= ratioFactor;
117
+ if (adjustVolumes) {
118
+ volume = Math.round(volume / ratioFactor);
119
+ }
120
+ } else if (method === "panama") {
121
+ open += priceOffset;
122
+ high += priceOffset;
123
+ low += priceOffset;
124
+ close += priceOffset;
125
+ } else if (method === "backward-ratio") {
126
+ open /= ratioFactor;
127
+ high /= ratioFactor;
128
+ low /= ratioFactor;
129
+ close /= ratioFactor;
130
+ if (adjustVolumes) {
131
+ volume = Math.round(volume * ratioFactor);
132
+ }
133
+ }
134
+ return { ...bar, open, high, low, close, volume };
135
+ });
136
+ }
137
+ function findBarAtOrBefore(bars, timestamp) {
138
+ let result = null;
139
+ for (const bar of bars) {
140
+ if (bar.timestamp <= timestamp) {
141
+ result = bar;
142
+ } else {
143
+ break;
144
+ }
145
+ }
146
+ return result;
147
+ }
148
+ function findBarAtOrAfter(bars, timestamp) {
149
+ for (const bar of bars) {
150
+ if (bar.timestamp >= timestamp) {
151
+ return bar;
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+ function deduplicateBars(bars) {
157
+ const seen = /* @__PURE__ */ new Map();
158
+ for (const bar of bars) {
159
+ const existing = seen.get(bar.timestamp);
160
+ if (!existing || bar.volume > existing.volume) {
161
+ seen.set(bar.timestamp, bar);
162
+ }
163
+ }
164
+ return Array.from(seen.values()).sort((a, b) => a.timestamp - b.timestamp);
165
+ }
166
+ function computeSingleRollAdjustment(fromPrice, toPrice, method) {
167
+ if (method === "ratio" && toPrice === 0) {
168
+ throw new Error("toPrice cannot be zero for ratio roll adjustment");
169
+ }
170
+ if (method === "backward-ratio" && fromPrice === 0) {
171
+ throw new Error("fromPrice cannot be zero for backward-ratio roll adjustment");
172
+ }
173
+ switch (method) {
174
+ case "ratio":
175
+ return { factor: fromPrice / toPrice, offset: 0 };
176
+ case "panama":
177
+ return { factor: 1, offset: fromPrice - toPrice };
178
+ case "backward-ratio":
179
+ return { factor: toPrice / fromPrice, offset: 0 };
180
+ default:
181
+ throw new Error(`Unknown roll method: ${method}`);
182
+ }
183
+ }
184
+ function verifyNoPriceGaps(rollPoints, thresholdPercent = 0.1) {
185
+ const gaps = rollPoints.map((rp) => {
186
+ const gapPercent = Math.abs((rp.fromPrice - rp.toPrice) / rp.fromPrice) * 100;
187
+ return { rollPoint: rp, gapPercent };
188
+ });
189
+ const maxGap = Math.max(...gaps.map((g) => g.gapPercent), 0);
190
+ return {
191
+ passed: maxGap <= thresholdPercent,
192
+ gaps
193
+ };
194
+ }
195
+ function generateTestContractChain(rootSymbol, count, startDate, intervalDays = 90) {
196
+ const contracts = [];
197
+ const monthCodes = ["F", "G", "H", "J", "K", "M", "N", "Q", "U", "V", "X", "Z"];
198
+ for (let i = 0; i < count; i++) {
199
+ const firstTrade = startDate + i * intervalDays * 24 * 60 * 60 * 1e3;
200
+ const expiry = firstTrade + intervalDays * 24 * 60 * 60 * 1e3;
201
+ const lastTrade = expiry - 3 * 24 * 60 * 60 * 1e3;
202
+ const monthCode = monthCodes[i % 12];
203
+ const year = Math.floor(startDate / (365 * 24 * 60 * 60 * 1e3) + i / 4) % 100;
204
+ contracts.push({
205
+ symbol: `${rootSymbol}${year.toString().padStart(2, "0")}${monthCode}`,
206
+ rootSymbol,
207
+ expiry,
208
+ firstTradeDate: firstTrade,
209
+ lastTradeDate: lastTrade,
210
+ monthCode,
211
+ year,
212
+ tickSize: 0.1,
213
+ multiplier: 1e5,
214
+ exchange: "VNX"
215
+ });
216
+ }
217
+ return contracts;
218
+ }
219
+ function generateTestBarsWithRollGap(contracts, rollMethod, gapPercent = 0) {
220
+ const barsMap = /* @__PURE__ */ new Map();
221
+ let basePrice = 1e3;
222
+ for (let i = 0; i < contracts.length; i++) {
223
+ const contract = contracts[i];
224
+ const bars = [];
225
+ const days = Math.ceil((contract.lastTradeDate - contract.firstTradeDate) / (24 * 60 * 60 * 1e3));
226
+ if (i > 0 && gapPercent !== 0) {
227
+ const gapFactor = 1 + gapPercent / 100;
228
+ if (rollMethod === "ratio") {
229
+ basePrice *= gapFactor;
230
+ } else if (rollMethod === "panama") {
231
+ basePrice += basePrice * gapPercent / 100;
232
+ }
233
+ }
234
+ for (let d = 0; d < days; d++) {
235
+ const timestamp = contract.firstTradeDate + d * 24 * 60 * 60 * 1e3;
236
+ const date = new Date(timestamp);
237
+ if (date.getDay() === 0 || date.getDay() === 6) continue;
238
+ const volatility = 0.01;
239
+ const change = (Math.random() - 0.5) * 2 * volatility * basePrice;
240
+ basePrice = Math.max(10, basePrice + change);
241
+ const open = basePrice * (1 + (Math.random() - 0.5) * 3e-3);
242
+ const close = basePrice * (1 + (Math.random() - 0.5) * 3e-3);
243
+ const high = Math.max(open, close) * (1 + Math.random() * 3e-3);
244
+ const low = Math.min(open, close) * (1 - Math.random() * 3e-3);
245
+ const volume = Math.floor(1e4 + Math.random() * 5e4);
246
+ bars.push({ timestamp, open, high, low, close, volume });
247
+ }
248
+ barsMap.set(contract.symbol, bars);
249
+ }
250
+ return barsMap;
251
+ }
252
+ var init_rollAlgorithms = __esm({
253
+ "src/lib/adapters/rollAlgorithms.ts"() {
254
+ }
255
+ });
256
+
257
+ // src/widget/adapters/barsPagingPolicy.ts
258
+ function asFiniteNumber(value) {
259
+ if (typeof value === "number" && Number.isFinite(value)) {
260
+ return value;
261
+ }
262
+ if (typeof value === "string") {
263
+ const parsed = Number(value.trim());
264
+ return Number.isFinite(parsed) ? parsed : null;
265
+ }
266
+ return null;
267
+ }
268
+ function resolveOldestBarTimestamp(bars) {
269
+ if (bars.length === 0) {
270
+ return null;
271
+ }
272
+ let oldest = Number.POSITIVE_INFINITY;
273
+ for (const bar of bars) {
274
+ const ts = bar.date instanceof Date ? bar.date.valueOf() : new Date(bar.date).valueOf();
275
+ if (Number.isFinite(ts) && ts < oldest) {
276
+ oldest = ts;
277
+ }
278
+ }
279
+ return Number.isFinite(oldest) ? oldest : null;
280
+ }
281
+ function normalizeBarsPagingMeta(payload, bars) {
282
+ const explicitHasMoreBefore = payload.has_more_before;
283
+ const explicitHasMoreAfter = payload.has_more_after;
284
+ const explicitNextBefore = asFiniteNumber(payload.next_before);
285
+ const explicitNextAfter = asFiniteNumber(payload.next_after);
286
+ const snapshotId = typeof payload.snapshot_id === "string" ? payload.snapshot_id : null;
287
+ const oldestBarTs = resolveOldestBarTimestamp(bars);
288
+ const nextBefore = explicitNextBefore ?? oldestBarTs;
289
+ const hasMoreBefore = typeof explicitHasMoreBefore === "boolean" ? explicitHasMoreBefore : nextBefore !== null;
290
+ const hasMoreAfter = typeof explicitHasMoreAfter === "boolean" ? explicitHasMoreAfter : false;
291
+ return {
292
+ hasMoreBefore,
293
+ hasMoreAfter,
294
+ nextBefore: hasMoreBefore ? nextBefore : null,
295
+ nextAfter: hasMoreAfter ? explicitNextAfter : null,
296
+ snapshotId
297
+ };
298
+ }
299
+ function buildBackwardPageRequest(meta, fallbackBefore, limit) {
300
+ if (!meta.hasMoreBefore) {
301
+ return null;
302
+ }
303
+ const before = meta.nextBefore ?? fallbackBefore;
304
+ if (!Number.isFinite(before)) {
305
+ return null;
306
+ }
307
+ return {
308
+ before,
309
+ limit,
310
+ snapshotId: meta.snapshotId ?? void 0
311
+ };
312
+ }
313
+
314
+ // src/widget/adapters/nativeShapes.ts
315
+ var BARS_LIMIT_MAX = 1e3;
316
+ function clampBarsLimit(raw) {
317
+ if (raw == null) return raw;
318
+ if (!Number.isFinite(raw)) return BARS_LIMIT_MAX;
319
+ return Math.max(1, Math.min(BARS_LIMIT_MAX, Math.floor(raw)));
320
+ }
321
+ var ORDER_FLOW_WINDOW_MINUTES = { "5m": 5, "15m": 15, "30m": 30, "1h": 60 };
322
+ var DARK_FLOW_SIGNAL_TYPES = ["none", "absorption", "iceberg", "twap_bot", "mixed"];
323
+ function parseDarkFlowSignalType(value) {
324
+ return typeof value === "string" && DARK_FLOW_SIGNAL_TYPES.includes(value) ? value : "none";
325
+ }
326
+ function asFiniteNumber2(value) {
327
+ if (typeof value === "number" && Number.isFinite(value)) return value;
328
+ if (typeof value === "string" && value.trim() !== "") {
329
+ const parsed = Number(value);
330
+ return Number.isFinite(parsed) ? parsed : null;
331
+ }
332
+ return null;
333
+ }
334
+ function mapNativeSignal(s) {
335
+ return {
336
+ id: typeof s["id"] === "number" || typeof s["id"] === "string" ? s["id"] : -1,
337
+ symbol: typeof s["symbol"] === "string" ? s["symbol"] : "",
338
+ signal_type: typeof s["signal_type"] === "string" ? s["signal_type"] : "unknown",
339
+ strength: asFiniteNumber2(s["strength"]) ?? 0,
340
+ confidence: asFiniteNumber2(s["confidence"]) ?? 0,
341
+ tick_rate: asFiniteNumber2(s["tick_rate"]) ?? 0,
342
+ small_order_ratio: asFiniteNumber2(s["small_order_ratio"]) ?? 0,
343
+ cvd_at_signal: asFiniteNumber2(s["cvd_at_signal"]),
344
+ price_at_signal: asFiniteNumber2(s["price_at_signal"]),
345
+ created_at: typeof s["created_at"] === "string" ? s["created_at"] : "",
346
+ event_id: typeof s["event_id"] === "string" ? s["event_id"] : null,
347
+ severity: typeof s["severity"] === "string" ? s["severity"] : void 0
348
+ };
349
+ }
350
+ function mapNativeOrderFlow(obj, window2) {
351
+ const rawSignals = Array.isArray(obj["signals"]) ? obj["signals"] : [];
352
+ const darkRaw = obj["dark_flow"] ?? {};
353
+ const latestRaw = obj["latest_signal"] ?? null;
354
+ return {
355
+ ok: true,
356
+ symbol: typeof obj["symbol"] === "string" ? obj["symbol"] : "",
357
+ window: typeof obj["window"] === "string" ? obj["window"] : window2,
358
+ window_minutes: ORDER_FLOW_WINDOW_MINUTES[window2] ?? 30,
359
+ latest_signal: latestRaw ? mapNativeSignal(latestRaw) : null,
360
+ signals: rawSignals.map(mapNativeSignal),
361
+ cvd_series: [],
362
+ dark_flow: {
363
+ signal_type: parseDarkFlowSignalType(darkRaw["signal_type"]),
364
+ strength: asFiniteNumber2(darkRaw["strength"]) ?? 0,
365
+ confidence: asFiniteNumber2(darkRaw["confidence"]) ?? 0,
366
+ components: darkRaw["components"],
367
+ triggered_at: typeof darkRaw["triggered_at"] === "string" ? darkRaw["triggered_at"] : null
368
+ },
369
+ tick_rate: obj["tick_rate"] ?? {},
370
+ size_distribution: obj["size_distribution"] ?? {}
371
+ };
372
+ }
373
+ var ZERO_WHALE_SUMMARY = {
374
+ buy_value: 0,
375
+ sell_value: 0,
376
+ shark_buy: 0,
377
+ shark_sell: 0,
378
+ whale_buy: 0,
379
+ whale_sell: 0,
380
+ small_buy: 0,
381
+ small_sell: 0
382
+ };
383
+ function mapNativeWhaleFeed(obj) {
384
+ const rawAlerts = Array.isArray(obj["alerts"]) ? obj["alerts"] : [];
385
+ const alerts = rawAlerts.map((a) => ({
386
+ id: typeof a["id"] === "string" ? a["id"] : "",
387
+ alert_type: typeof a["alert_type"] === "string" ? a["alert_type"] : "signal",
388
+ severity: typeof a["severity"] === "string" ? a["severity"] : "",
389
+ title: typeof a["title"] === "string" ? a["title"] : "",
390
+ value: typeof a["value"] === "string" || typeof a["value"] === "number" ? a["value"] : null,
391
+ direction: typeof a["direction"] === "string" ? a["direction"] : "",
392
+ triggered_at: typeof a["triggered_at"] === "string" ? a["triggered_at"] : ""
393
+ }));
394
+ return {
395
+ symbol: typeof obj["symbol"] === "string" ? obj["symbol"] : "",
396
+ whale_orders: [],
397
+ summary: { ...ZERO_WHALE_SUMMARY },
398
+ alerts
399
+ };
400
+ }
401
+ function mapNativeTape(obj) {
402
+ const rawTrades = Array.isArray(obj["trades"]) ? obj["trades"] : [];
403
+ const entries = rawTrades.map((t, index) => {
404
+ const price = asFiniteNumber2(t["price"]) ?? 0;
405
+ const volume = asFiniteNumber2(t["volume"]) ?? 0;
406
+ const sideRaw = typeof t["side"] === "string" ? t["side"].toLowerCase() : "";
407
+ const side = sideRaw === "buy" || sideRaw === "sell" ? sideRaw : "unknown";
408
+ const ts = typeof t["ts"] === "string" ? t["ts"] : typeof t["time"] === "string" ? t["time"] : "";
409
+ return {
410
+ id: `${ts}|${price}|${volume}|${index}`,
411
+ ts,
412
+ price,
413
+ volume,
414
+ value: price * volume,
415
+ side,
416
+ is_whale: false
417
+ };
418
+ });
419
+ return {
420
+ ok: true,
421
+ symbol: typeof obj["symbol"] === "string" ? obj["symbol"] : "",
422
+ entries
423
+ };
424
+ }
425
+
426
+ // src/lib/cache/cacheDebug.ts
427
+ typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
428
+ var qs = () => typeof window !== "undefined" ? new URLSearchParams(window.location.search) : new URLSearchParams();
429
+ function getCacheTTL(defaultMs) {
430
+ const override = Number(qs().get("bars-ttl"));
431
+ return Number.isFinite(override) && override > 0 ? override : defaultMs;
432
+ }
433
+
434
+ // src/widget/history/historyDataUtils.ts
435
+ function resolveTimeframeMs(timeframe) {
436
+ const result = (() => {
437
+ switch (timeframe) {
438
+ case "1m":
439
+ return 6e4;
440
+ case "3m":
441
+ return 3 * 6e4;
442
+ case "5m":
443
+ return 5 * 6e4;
444
+ case "15m":
445
+ return 15 * 6e4;
446
+ case "30m":
447
+ return 30 * 6e4;
448
+ case "1h":
449
+ return 60 * 6e4;
450
+ case "2h":
451
+ return 2 * 60 * 6e4;
452
+ case "4h":
453
+ return 4 * 60 * 6e4;
454
+ case "1d":
455
+ case "1D":
456
+ return 24 * 60 * 6e4;
457
+ case "1w":
458
+ case "1W":
459
+ return 7 * 24 * 60 * 6e4;
460
+ case "1M":
461
+ return 30 * 24 * 60 * 6e4;
462
+ default:
463
+ return 24 * 60 * 6e4;
464
+ }
465
+ })();
466
+ return result;
467
+ }
468
+
469
+ // src/widget/data/DataEnvelope.ts
470
+ var NUMERIC_SENTINELS = /* @__PURE__ */ new Set(["", "-", "--", "N/A", "n/a", "null", "undefined", "NaN"]);
471
+ function toNum(value) {
472
+ if (typeof value === "number") {
473
+ return Number.isFinite(value) ? value : null;
474
+ }
475
+ if (typeof value === "string") {
476
+ const trimmed = value.trim();
477
+ if (NUMERIC_SENTINELS.has(trimmed)) return null;
478
+ const parsed = Number(trimmed);
479
+ return Number.isFinite(parsed) ? parsed : null;
480
+ }
481
+ return null;
482
+ }
483
+ function toNumOrZero(value) {
484
+ const n = toNum(value);
485
+ return n === null ? 0 : n;
486
+ }
487
+ var DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
488
+ var NAIVE_DATETIME_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(:\d{2})?(\.\d+)?$/;
489
+ function toTimestampMs(value) {
490
+ if (value instanceof Date) {
491
+ const t = value.getTime();
492
+ return Number.isFinite(t) ? t : null;
493
+ }
494
+ if (typeof value === "number") {
495
+ if (!Number.isFinite(value) || value <= 0) return null;
496
+ return value < 1e11 ? Math.round(value * 1e3) : Math.round(value);
497
+ }
498
+ if (typeof value !== "string") return null;
499
+ const trimmed = value.trim();
500
+ if (NUMERIC_SENTINELS.has(trimmed)) return null;
501
+ if (/^-?\d+(\.\d+)?$/.test(trimmed)) return toTimestampMs(Number(trimmed));
502
+ if (DATE_ONLY_RE.test(trimmed)) return Date.parse(`${trimmed}T00:00:00Z`);
503
+ if (NAIVE_DATETIME_RE.test(trimmed)) {
504
+ const iso = trimmed.replace(" ", "T");
505
+ const withSeconds = iso.length === 16 ? `${iso}:00` : iso;
506
+ return Date.parse(`${withSeconds}Z`);
507
+ }
508
+ const parsed = Date.parse(trimmed);
509
+ return Number.isFinite(parsed) ? parsed : null;
510
+ }
511
+ function readRecord(raw) {
512
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
513
+ return raw;
514
+ }
515
+ return null;
516
+ }
517
+ function readBarTimestamp(rec) {
518
+ for (const key of ["timestamp", "date", "time", "t", "ts"]) {
519
+ const ms = toTimestampMs(rec[key]);
520
+ if (ms !== null) return ms;
521
+ }
522
+ return null;
523
+ }
524
+ function readBarSource(rec) {
525
+ if (rec.timestamp !== void 0) return "bars";
526
+ if (rec.date !== void 0 || rec.time !== void 0) return "chart";
527
+ return "unknown";
528
+ }
529
+ function normalizeBar(raw) {
530
+ const rec = readRecord(raw);
531
+ if (!rec) return null;
532
+ const timestamp = readBarTimestamp(rec);
533
+ if (timestamp === null) return null;
534
+ return {
535
+ timestamp,
536
+ open: toNum(rec.open ?? rec.o),
537
+ high: toNum(rec.high ?? rec.h),
538
+ low: toNum(rec.low ?? rec.l),
539
+ close: toNum(rec.close ?? rec.c),
540
+ volume: toNumOrZero(rec.volume ?? rec.v),
541
+ adjClose: toNum(rec.adj_close ?? rec.adjClose),
542
+ adjFactor: toNum(rec.adj_factor ?? rec.adjFactor),
543
+ isPartial: rec.isPartial === true || rec.is_partial === true,
544
+ source: readBarSource(rec)
545
+ };
546
+ }
547
+
548
+ // src/lib/utils/storage.ts
549
+ function getSafeStorage() {
550
+ try {
551
+ if (typeof localStorage === "undefined") return null;
552
+ return localStorage;
553
+ } catch {
554
+ return null;
555
+ }
556
+ }
557
+ function readString(key) {
558
+ const store = getSafeStorage();
559
+ if (!store) return null;
560
+ try {
561
+ return store.getItem(key);
562
+ } catch {
563
+ return null;
564
+ }
565
+ }
566
+ function writeString(key, value) {
567
+ const store = getSafeStorage();
568
+ if (!store) return false;
569
+ try {
570
+ store.setItem(key, value);
571
+ return true;
572
+ } catch {
573
+ return false;
574
+ }
575
+ }
576
+ function removeKey(key) {
577
+ const store = getSafeStorage();
578
+ if (!store) return false;
579
+ try {
580
+ store.removeItem(key);
581
+ return true;
582
+ } catch {
583
+ return false;
584
+ }
585
+ }
586
+
587
+ // src/lib/credentials/credentialStore.ts
588
+ var LICENSE_STORAGE_KEY = "vni_license_key";
589
+ var PAT_STORAGE_KEY = "vni_pat";
590
+ var PENDING_MIGRATION_WARNING = "pending-license-migration";
591
+ var migrationState = "idle";
592
+ function isLicenseMigrationPending() {
593
+ return migrationState === "pending";
594
+ }
595
+ function isLicenseBlob(value) {
596
+ if (!value) return false;
597
+ return engineCore.parseLicenseKey(value) !== null;
598
+ }
599
+ function readRaw(key) {
600
+ return readString(key) ?? "";
601
+ }
602
+ function writeRaw(key, value) {
603
+ writeString(key, value);
604
+ }
605
+ function warnOnce(message) {
606
+ try {
607
+ if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
608
+ } catch {
609
+ }
610
+ console.warn(`[credentialStore] ${message}`);
611
+ }
612
+ function removeRaw(key) {
613
+ removeKey(key);
614
+ }
615
+ var sessionPat = null;
616
+ function readPat() {
617
+ if (sessionPat !== null) {
618
+ if (!sessionPat || isLicenseBlob(sessionPat)) return "";
619
+ return sessionPat;
620
+ }
621
+ const stored = readRaw(PAT_STORAGE_KEY);
622
+ if (!stored) return "";
623
+ if (isLicenseBlob(stored)) return "";
624
+ return stored;
625
+ }
626
+ function readSessionPat() {
627
+ if (sessionPat === null || !sessionPat || isLicenseBlob(sessionPat)) return "";
628
+ return sessionPat;
629
+ }
630
+ function writePat(value) {
631
+ const trimmed = (value ?? "").trim();
632
+ if (!trimmed) {
633
+ clearPat();
634
+ return { ok: true };
635
+ }
636
+ if (isLicenseBlob(trimmed)) {
637
+ warnOnce("refused a license blob on the PAT channel");
638
+ return { ok: false, reason: "is-license-blob" };
639
+ }
640
+ if (isLicenseMigrationPending()) {
641
+ warnOnce(`${PENDING_MIGRATION_WARNING}: PAT not saved, a license key is still being migrated`);
642
+ return { ok: false, reason: "migration-pending" };
643
+ }
644
+ sessionPat = trimmed;
645
+ writeRaw(PAT_STORAGE_KEY, trimmed);
646
+ return { ok: true };
647
+ }
648
+ function clearPat() {
649
+ sessionPat = null;
650
+ removeRaw(PAT_STORAGE_KEY);
651
+ }
652
+ var inFlight = null;
653
+ async function migrateLegacyLicenseSlot() {
654
+ if (inFlight) return inFlight;
655
+ migrationState = "pending";
656
+ inFlight = (async () => {
657
+ if (readRaw(LICENSE_STORAGE_KEY)) return { migrated: false, reason: "already-migrated" };
658
+ const stored = readRaw(PAT_STORAGE_KEY);
659
+ if (!stored) return { migrated: false, reason: "not-a-license" };
660
+ if (!isLicenseBlob(stored)) return { migrated: false, reason: "not-a-license" };
661
+ writeRaw(LICENSE_STORAGE_KEY, stored);
662
+ const verified = await engineCore.verifyLicenseKey(stored, { host: typeof location !== "undefined" ? location.hostname : "" });
663
+ if (verified) {
664
+ if (readRaw(LICENSE_STORAGE_KEY) === stored) ;
665
+ if (readRaw(PAT_STORAGE_KEY) === stored) {
666
+ sessionPat = null;
667
+ removeRaw(PAT_STORAGE_KEY);
668
+ }
669
+ return { migrated: true, reason: "already-migrated" };
670
+ }
671
+ if (readRaw(LICENSE_STORAGE_KEY) === stored) {
672
+ removeRaw(LICENSE_STORAGE_KEY);
673
+ }
674
+ return { migrated: false, reason: "verify-failed" };
675
+ })();
676
+ try {
677
+ return await inFlight;
678
+ } finally {
679
+ inFlight = null;
680
+ migrationState = "settled";
681
+ }
682
+ }
683
+ void migrateLegacyLicenseSlot();
684
+
685
+ // src/widget/adapters/VNInvestClient.ts
686
+ var API_BASE_STORAGE_KEY = "vni_api_base";
687
+ var DEFAULT_API_BASE = "https://127.0.0.1";
688
+ var DEFAULT_PAT = "";
689
+ function normalizeApiBase(value) {
690
+ const trimmed = value.trim();
691
+ return trimmed.replace(/\/+$/, "");
692
+ }
693
+ function resolveBrowserOrigin() {
694
+ try {
695
+ if (typeof location === "undefined" || typeof location.origin !== "string") {
696
+ return null;
697
+ }
698
+ const normalizedOrigin = normalizeApiBase(location.origin);
699
+ if (!/^https?:\/\//i.test(normalizedOrigin)) {
700
+ return null;
701
+ }
702
+ return normalizedOrigin;
703
+ } catch {
704
+ return null;
705
+ }
706
+ }
707
+ function resolveApiBase() {
708
+ try {
709
+ const globalScope = globalThis;
710
+ if (typeof globalScope.__VNI_API_BASE__ === "string") {
711
+ return normalizeApiBase(globalScope.__VNI_API_BASE__);
712
+ }
713
+ } catch {
714
+ }
715
+ try {
716
+ if (typeof localStorage !== "undefined") {
717
+ const stored = localStorage.getItem(API_BASE_STORAGE_KEY);
718
+ if (stored) return normalizeApiBase(stored);
719
+ }
720
+ } catch {
721
+ }
722
+ const browserOrigin = resolveBrowserOrigin();
723
+ if (browserOrigin) {
724
+ return browserOrigin;
725
+ }
726
+ return DEFAULT_API_BASE;
727
+ }
728
+ var TIMEFRAME_MAP = {
729
+ "1m": "1m",
730
+ "5m": "5m",
731
+ "15m": "15m",
732
+ "1h": "1H",
733
+ "1H": "1H",
734
+ "2H": "2H",
735
+ "4H": "4H",
736
+ "1d": "D",
737
+ "1D": "D",
738
+ "d": "D",
739
+ "D": "D",
740
+ "W": "W",
741
+ "M": "M",
742
+ "Y": "Y"
743
+ };
744
+ function normalizeTimeframe(tf) {
745
+ const result = TIMEFRAME_MAP[tf] ?? tf;
746
+ return result;
747
+ }
748
+ function isCurrentCandleResponse(response, timeframe) {
749
+ const bars = response.bars;
750
+ if (bars.length === 0) return false;
751
+ const lastBar = bars[bars.length - 1];
752
+ const tfMs = resolveTimeframeMs(timeframe);
753
+ return Date.now() - lastBar.date.getTime() < tfMs;
754
+ }
755
+ function asObject(value) {
756
+ if (value && typeof value === "object" && !Array.isArray(value)) {
757
+ return value;
758
+ }
759
+ return null;
760
+ }
761
+ function normalizeChartPoint(value) {
762
+ const bar = normalizeBar(value);
763
+ if (!bar) return null;
764
+ if (bar.open === null || bar.high === null || bar.low === null || bar.close === null) {
765
+ return null;
766
+ }
767
+ return {
768
+ date: new Date(bar.timestamp).toISOString(),
769
+ open: bar.open,
770
+ high: bar.high,
771
+ low: bar.low,
772
+ close: bar.close,
773
+ volume: bar.volume
774
+ };
775
+ }
776
+ function extractChartPoints(data) {
777
+ if (Array.isArray(data)) {
778
+ return data.map(normalizeChartPoint).filter((point) => point !== null);
779
+ }
780
+ const payload = asObject(data);
781
+ if (!payload) {
782
+ return [];
783
+ }
784
+ const nestedData = asObject(payload.data);
785
+ const candidates = [
786
+ payload.points,
787
+ nestedData?.points,
788
+ payload.candles,
789
+ nestedData?.candles,
790
+ payload.ohlcv,
791
+ nestedData?.ohlcv,
792
+ payload.results,
793
+ nestedData?.results,
794
+ payload.data
795
+ ];
796
+ for (const candidate of candidates) {
797
+ if (!Array.isArray(candidate)) {
798
+ continue;
799
+ }
800
+ const normalized = candidate.map(normalizeChartPoint).filter((point) => point !== null);
801
+ if (normalized.length > 0 || candidate.length === 0) {
802
+ return normalized;
803
+ }
804
+ }
805
+ return [];
806
+ }
807
+ function resolveTechnical(data) {
808
+ if (Array.isArray(data)) {
809
+ return void 0;
810
+ }
811
+ const payload = asObject(data);
812
+ if (!payload) {
813
+ return void 0;
814
+ }
815
+ const nestedData = asObject(payload.data);
816
+ const technical = payload.technical ?? nestedData?.technical;
817
+ return technical;
818
+ }
819
+ function normalizeChartBars(data) {
820
+ const points = extractChartPoints(data);
821
+ const technical = resolveTechnical(data);
822
+ return points.map((point) => ({
823
+ date: new Date(point.date),
824
+ open: point.open,
825
+ high: point.high,
826
+ low: point.low,
827
+ close: point.close,
828
+ volume: point.volume,
829
+ technical
830
+ })).filter((bar) => Number.isFinite(bar.date.valueOf()));
831
+ }
832
+ function isWhaleFeedResponse(data) {
833
+ if (!data || Array.isArray(data) || typeof data !== "object") {
834
+ return false;
835
+ }
836
+ return "summary" in data && "whale_orders" in data;
837
+ }
838
+ function buildEndpoints(base) {
839
+ return {
840
+ CHART: (symbol) => `${base}/core/v1/stock-management/stocks/${encodeURIComponent(symbol)}/chart/`,
841
+ BARS: (symbol) => `${base}/core/v1/stock-management/stocks/${encodeURIComponent(symbol)}/bars/`,
842
+ ORDER_FLOW: (symbol) => `${base}/core/v1/stock-management/stocks/${encodeURIComponent(symbol)}/order-flow/`,
843
+ STOCKS_LIST: `${base}/core/v1/stock-management/stocks/`,
844
+ AUTH_TOKEN: `${base}/core/v1/auth/token/`,
845
+ AUTH_ME: `${base}/core/v1/auth/me`,
846
+ TICKER: (symbol) => `${base}/core/v1/realtime/ticker/${encodeURIComponent(symbol)}/`,
847
+ WHALE_FEED: (symbol) => `${base}/core/v1/realtime/whale-feed/${encodeURIComponent(symbol)}/`,
848
+ AI_ADVISORY: `${base}/core/v1/stock_ai_advisory_session/`,
849
+ // Decision A (follow-up): native advisory session — GET reads, POST triggers refresh.
850
+ AI_ADVISORY_V2: (symbol) => `${base}/core/v1/stock-management/stocks/${encodeURIComponent(symbol)}/ai-advisory-session/`,
851
+ // BE-03: backend serves path-param style only: /intraday-tape/{symbol}/
852
+ // (verified live 2026-09-21; the old ?symbol= style 404s).
853
+ INTRADAY_TAPE: (symbol) => `${base}/core/v1/market-data/intraday-tape/${encodeURIComponent(symbol)}/`,
854
+ WIDGET_AD: `${base}/core/v1/widget/ad`
855
+ };
856
+ }
857
+ var BARS_HOT_WINDOW_TTL_MS = 15e3;
858
+ var BARS_HOT_WINDOW_STALE_MS = 6e4;
859
+ var barsHotWindowCache = /* @__PURE__ */ new Map();
860
+ var barsHotWindowInFlight = /* @__PURE__ */ new Map();
861
+ var barsHotWindowTelemetry = {
862
+ cacheHits: 0,
863
+ inFlightCollapses: 0,
864
+ networkRequests: 0,
865
+ lastUpdatedAt: null
866
+ };
867
+ function markBarsHotWindowTelemetry(metric) {
868
+ barsHotWindowTelemetry[metric] += 1;
869
+ barsHotWindowTelemetry.lastUpdatedAt = Date.now();
870
+ }
871
+ function cloneBarsHotWindowTelemetry(telemetry) {
872
+ return {
873
+ cacheHits: telemetry.cacheHits,
874
+ inFlightCollapses: telemetry.inFlightCollapses,
875
+ networkRequests: telemetry.networkRequests,
876
+ lastUpdatedAt: telemetry.lastUpdatedAt
877
+ };
878
+ }
879
+ function createBarsHotWindowKey(base, pat, params) {
880
+ const scope = [base, pat, params.symbol.trim().toUpperCase(), normalizeTimeframe(params.timeframe)].join("|");
881
+ if (params.type === "backward") {
882
+ return `${scope}|backward|${params.before}|${params.limit}|${params.snapshotId ?? ""}`;
883
+ }
884
+ return `${scope}|init|${params.from ?? ""}|${params.to ?? ""}|${params.limit ?? ""}`;
885
+ }
886
+ function cloneBarsPageResponse(response) {
887
+ return {
888
+ bars: response.bars.map((bar) => ({
889
+ date: new Date(bar.date),
890
+ open: bar.open,
891
+ high: bar.high,
892
+ low: bar.low,
893
+ close: bar.close,
894
+ volume: bar.volume,
895
+ technical: bar.technical
896
+ })),
897
+ hasMoreBefore: response.hasMoreBefore,
898
+ hasMoreAfter: response.hasMoreAfter,
899
+ nextBefore: response.nextBefore,
900
+ nextAfter: response.nextAfter,
901
+ snapshotId: response.snapshotId
902
+ };
903
+ }
904
+ function pruneExpiredBarsHotWindowEntries(now) {
905
+ for (const [key, entry] of barsHotWindowCache.entries()) {
906
+ if (entry.expiresAt <= now) {
907
+ barsHotWindowCache.delete(key);
908
+ }
909
+ }
910
+ }
911
+ async function revalidateBarsHotWindow(base, pat, cacheKey, params) {
912
+ const endpoints = buildEndpoints(base);
913
+ const urlParams = new URLSearchParams();
914
+ urlParams.set("timeframe", normalizeTimeframe(params.timeframe));
915
+ if (params.type === "backward") {
916
+ urlParams.set("before", String(params.before));
917
+ urlParams.set("limit", String(params.limit));
918
+ if (params.snapshotId) urlParams.set("snapshot_id", params.snapshotId);
919
+ } else {
920
+ if (params.from != null) urlParams.set("from", String(params.from));
921
+ if (params.to != null) urlParams.set("to", String(params.to));
922
+ if (params.limit != null) urlParams.set("limit", String(params.limit));
923
+ }
924
+ try {
925
+ markBarsHotWindowTelemetry("networkRequests");
926
+ const url = `${endpoints.BARS(params.symbol)}?${urlParams.toString()}`;
927
+ const authHeaders = {};
928
+ if (pat) authHeaders["Authorization"] = `Bearer ${pat}`;
929
+ const response = await globalThis.fetch(url, { headers: authHeaders });
930
+ if (!response.ok) return;
931
+ const data = await response.json();
932
+ const rawBars = Array.isArray(data?.bars) ? data.bars : [];
933
+ const bars = rawBars.map(normalizeChartPoint).filter((p) => p !== null).map((point) => ({
934
+ date: new Date(point.date),
935
+ open: point.open,
936
+ high: point.high,
937
+ low: point.low,
938
+ close: point.close,
939
+ volume: point.volume
940
+ })).filter((bar) => Number.isFinite(bar.date.valueOf()));
941
+ const pagingMeta = normalizeBarsPagingMeta(data, bars);
942
+ const swrResponse = {
943
+ bars,
944
+ hasMoreBefore: pagingMeta.hasMoreBefore,
945
+ hasMoreAfter: pagingMeta.hasMoreAfter,
946
+ nextBefore: pagingMeta.nextBefore,
947
+ nextAfter: pagingMeta.nextAfter,
948
+ snapshotId: pagingMeta.snapshotId
949
+ };
950
+ const ttl = getCacheTTL(BARS_HOT_WINDOW_TTL_MS);
951
+ const now = Date.now();
952
+ if (!isCurrentCandleResponse(swrResponse, params.timeframe)) {
953
+ barsHotWindowCache.set(cacheKey, {
954
+ response: cloneBarsPageResponse(swrResponse),
955
+ expiresAt: now + ttl,
956
+ fetchedAt: now
957
+ });
958
+ }
959
+ } catch {
960
+ }
961
+ }
962
+ var VNInvestClient = class _VNInvestClient {
963
+ _pat = "";
964
+ _base;
965
+ _authHandler;
966
+ constructor(patToken) {
967
+ this._base = resolveApiBase();
968
+ try {
969
+ if (typeof globalThis !== "undefined") {
970
+ const globalPat = globalThis.__VNI_PAT_TOKEN__;
971
+ if (typeof globalPat === "string" && globalPat.trim()) {
972
+ this._pat = globalPat.trim();
973
+ writePat(this._pat);
974
+ return;
975
+ }
976
+ }
977
+ } catch {
978
+ }
979
+ try {
980
+ if (typeof localStorage !== "undefined") {
981
+ const stored = localStorage.getItem(PAT_STORAGE_KEY);
982
+ if (stored) {
983
+ const isLicenseKey = !!engineCore.parseLicenseKey(stored);
984
+ if (!DEFAULT_PAT && !isLicenseKey) {
985
+ const migrationKey = "vni_pat_cleared_v1";
986
+ if (!localStorage.getItem(migrationKey)) {
987
+ clearPat();
988
+ localStorage.removeItem("vninvest_saas_features_vni_internal_Q3zRGQ2bpLoLjGdYx6R72E7TH50tQ2iIYRUecgSKfDnirANYBGQrM2wQlZQ12uP6");
989
+ localStorage.setItem(migrationKey, "1");
990
+ }
991
+ } else {
992
+ const token = readPat();
993
+ if (token) {
994
+ this._pat = token;
995
+ return;
996
+ }
997
+ }
998
+ }
999
+ }
1000
+ } catch {
1001
+ }
1002
+ if (patToken) {
1003
+ this.setPAT(patToken);
1004
+ return;
1005
+ }
1006
+ if (!this._pat) {
1007
+ const mem = readSessionPat();
1008
+ if (mem) this._pat = mem;
1009
+ }
1010
+ }
1011
+ setAuthHandler(handler) {
1012
+ this._authHandler = handler;
1013
+ }
1014
+ setPAT(token) {
1015
+ const trimmed = (token ?? "").trim();
1016
+ const changed = trimmed !== this._pat;
1017
+ if (!trimmed) {
1018
+ this._pat = "";
1019
+ clearPat();
1020
+ if (changed) this._notifyPatChanged();
1021
+ return;
1022
+ }
1023
+ const result = writePat(trimmed);
1024
+ if (!result.ok) return;
1025
+ this._pat = trimmed;
1026
+ if (changed) this._notifyPatChanged();
1027
+ }
1028
+ /**
1029
+ * Transport-only credential sync. Sets `_pat` WITHOUT touching storage —
1030
+ * storage belongs to credentialStore alone. The SaaS context calls this before
1031
+ * validation when its resolved credential (tenant > user > env) differs from
1032
+ * what this transport carries; otherwise a user-pasted PAT sits in storage
1033
+ * while requests go out with a stale or empty token, and the backend 401s with
1034
+ * "Authentication credentials were not provided." No-op when equal.
1035
+ */
1036
+ syncTransportPat(token) {
1037
+ const trimmed = (token ?? "").trim();
1038
+ if (trimmed === this._pat) return;
1039
+ this._pat = trimmed;
1040
+ this._notifyPatChanged();
1041
+ }
1042
+ _notifyPatChanged() {
1043
+ try {
1044
+ window.dispatchEvent(new CustomEvent("vni:pat-changed"));
1045
+ } catch {
1046
+ }
1047
+ }
1048
+ getPAT() {
1049
+ return this._pat;
1050
+ }
1051
+ setBase(url) {
1052
+ const trimmed = (url ?? "").trim().replace(/\/+$/, "");
1053
+ if (!trimmed) return;
1054
+ this._base = trimmed;
1055
+ try {
1056
+ if (typeof localStorage !== "undefined") {
1057
+ localStorage.setItem(API_BASE_STORAGE_KEY, trimmed);
1058
+ }
1059
+ } catch {
1060
+ }
1061
+ }
1062
+ getBase() {
1063
+ return this._base;
1064
+ }
1065
+ hasPAT() {
1066
+ return this._pat.length > 0;
1067
+ }
1068
+ buildHeaders() {
1069
+ const headers = { "Content-Type": "application/json" };
1070
+ if (this._pat) {
1071
+ headers["Authorization"] = `Bearer ${this._pat}`;
1072
+ }
1073
+ return headers;
1074
+ }
1075
+ async _fetch(url, init, isRetry = false) {
1076
+ const response = await fetch(url, { ...init, headers: this.buildHeaders() });
1077
+ if (response.status === 401) {
1078
+ if (!isRetry && this._authHandler) {
1079
+ try {
1080
+ const currentToken = await this._authHandler.getToken();
1081
+ if (currentToken && currentToken.trim() !== this._pat) {
1082
+ this.setPAT(currentToken);
1083
+ return await this._fetch(url, init, true);
1084
+ }
1085
+ if (this._authHandler.getRefreshToken) {
1086
+ const refreshToken = await this._authHandler.getRefreshToken();
1087
+ if (refreshToken) {
1088
+ const refreshUrl = `${this._base}/api/auth/token/refresh/`;
1089
+ const refreshResponse = await fetch(refreshUrl, {
1090
+ method: "POST",
1091
+ headers: { "Content-Type": "application/json" },
1092
+ body: JSON.stringify({ refresh: refreshToken })
1093
+ });
1094
+ if (refreshResponse.ok) {
1095
+ const data = await refreshResponse.json();
1096
+ const newPat = data.access || data.token || data.patToken;
1097
+ if (newPat) {
1098
+ this.setPAT(newPat);
1099
+ await this._authHandler.onTokensUpdated?.({
1100
+ patToken: newPat,
1101
+ refreshToken: data.refresh || refreshToken
1102
+ });
1103
+ return await this._fetch(url, init, true);
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+ } catch (refreshError) {
1109
+ console.warn("Auto-refresh token failed in VNInvestClient:", refreshError);
1110
+ }
1111
+ this._authHandler.onAuthError?.(new Error("TOKEN_EXPIRED"));
1112
+ }
1113
+ const err = new Error("TOKEN_EXPIRED");
1114
+ try {
1115
+ const body = await response.clone().json();
1116
+ if (typeof body?.detail === "string" && body.detail) {
1117
+ err.detail = body.detail;
1118
+ }
1119
+ } catch {
1120
+ }
1121
+ throw err;
1122
+ }
1123
+ if (response.status === 404) {
1124
+ throw new Error("SYMBOL_NOT_FOUND");
1125
+ }
1126
+ if (!response.ok) {
1127
+ const text = await response.text().catch(() => String(response.status));
1128
+ throw new Error(`HTTP_${response.status}: ${text.slice(0, 200)}`);
1129
+ }
1130
+ return response.json();
1131
+ }
1132
+ async getChart(symbol, options) {
1133
+ const endpoints = buildEndpoints(this._base);
1134
+ const params = new URLSearchParams();
1135
+ if (options?.timeframe) params.set("timeframe", normalizeTimeframe(options.timeframe));
1136
+ if (options?.days != null) params.set("days", String(options.days));
1137
+ const url = `${endpoints.CHART(symbol)}?${params.toString()}`;
1138
+ const data = await this._fetch(url);
1139
+ return normalizeChartBars(data);
1140
+ }
1141
+ async validateMe() {
1142
+ const endpoints = buildEndpoints(this._base);
1143
+ return this._fetch(endpoints.AUTH_ME);
1144
+ }
1145
+ /** Fetch eligible ad campaigns. Bearer PAT auto-attached; premium → empty list. */
1146
+ async fetchAd() {
1147
+ const endpoints = buildEndpoints(this._base);
1148
+ return this._fetch(endpoints.WIDGET_AD);
1149
+ }
1150
+ async getBarsPage(params) {
1151
+ const cacheKey = createBarsHotWindowKey(this._base, this._pat, params);
1152
+ const now = Date.now();
1153
+ pruneExpiredBarsHotWindowEntries(now);
1154
+ const tfMs = resolveTimeframeMs(params.timeframe);
1155
+ const isNearNow = params.type === "init" && params.to != null ? now - params.to < tfMs : false;
1156
+ if (!isNearNow) {
1157
+ const cachedEntry = barsHotWindowCache.get(cacheKey);
1158
+ if (cachedEntry && cachedEntry.expiresAt > now) {
1159
+ markBarsHotWindowTelemetry("cacheHits");
1160
+ return cloneBarsPageResponse(cachedEntry.response);
1161
+ }
1162
+ if (cachedEntry && now - cachedEntry.fetchedAt < BARS_HOT_WINDOW_STALE_MS) {
1163
+ markBarsHotWindowTelemetry("cacheHits");
1164
+ void this._revalidateBarsHotWindow(cacheKey, params);
1165
+ return cloneBarsPageResponse(cachedEntry.response);
1166
+ }
1167
+ }
1168
+ const inFlight2 = barsHotWindowInFlight.get(cacheKey);
1169
+ if (inFlight2) {
1170
+ markBarsHotWindowTelemetry("inFlightCollapses");
1171
+ const sharedResponse = await inFlight2;
1172
+ return cloneBarsPageResponse(sharedResponse);
1173
+ }
1174
+ const endpoints = buildEndpoints(this._base);
1175
+ const urlParams = new URLSearchParams();
1176
+ urlParams.set("timeframe", normalizeTimeframe(params.timeframe));
1177
+ const safeLimit = clampBarsLimit;
1178
+ if (params.type === "backward") {
1179
+ urlParams.set("before", String(params.before));
1180
+ urlParams.set("limit", String(safeLimit(params.limit) ?? BARS_LIMIT_MAX));
1181
+ if (params.snapshotId) urlParams.set("snapshot_id", params.snapshotId);
1182
+ } else {
1183
+ if (params.from != null) urlParams.set("from", String(params.from));
1184
+ if (params.to != null) urlParams.set("to", String(params.to));
1185
+ if (params.limit != null) urlParams.set("limit", String(safeLimit(params.limit)));
1186
+ }
1187
+ const requestPromise = (async () => {
1188
+ markBarsHotWindowTelemetry("networkRequests");
1189
+ const url = `${endpoints.BARS(params.symbol)}?${urlParams.toString()}`;
1190
+ const data = await this._fetch(url);
1191
+ const payload = data;
1192
+ const rawBars = Array.isArray(payload?.bars) ? payload.bars : [];
1193
+ const bars = rawBars.map(normalizeChartPoint).filter((p) => p !== null).map((point) => ({
1194
+ date: new Date(point.date),
1195
+ open: point.open,
1196
+ high: point.high,
1197
+ low: point.low,
1198
+ close: point.close,
1199
+ volume: point.volume
1200
+ })).filter((bar) => Number.isFinite(bar.date.valueOf()));
1201
+ const pagingMeta = normalizeBarsPagingMeta(payload, bars);
1202
+ const response = {
1203
+ bars,
1204
+ hasMoreBefore: pagingMeta.hasMoreBefore,
1205
+ hasMoreAfter: pagingMeta.hasMoreAfter,
1206
+ nextBefore: pagingMeta.nextBefore,
1207
+ nextAfter: pagingMeta.nextAfter,
1208
+ snapshotId: pagingMeta.snapshotId
1209
+ };
1210
+ const ttl = getCacheTTL(BARS_HOT_WINDOW_TTL_MS);
1211
+ const now2 = Date.now();
1212
+ if (!isCurrentCandleResponse(response, params.timeframe)) {
1213
+ barsHotWindowCache.set(cacheKey, {
1214
+ response: cloneBarsPageResponse(response),
1215
+ expiresAt: now2 + ttl,
1216
+ fetchedAt: now2
1217
+ });
1218
+ }
1219
+ return response;
1220
+ })();
1221
+ barsHotWindowInFlight.set(cacheKey, requestPromise);
1222
+ try {
1223
+ const response = await requestPromise;
1224
+ return cloneBarsPageResponse(response);
1225
+ } finally {
1226
+ barsHotWindowInFlight.delete(cacheKey);
1227
+ }
1228
+ }
1229
+ static __resetBarsHotWindowCacheForTests() {
1230
+ barsHotWindowCache.clear();
1231
+ barsHotWindowInFlight.clear();
1232
+ barsHotWindowTelemetry.cacheHits = 0;
1233
+ barsHotWindowTelemetry.inFlightCollapses = 0;
1234
+ barsHotWindowTelemetry.networkRequests = 0;
1235
+ barsHotWindowTelemetry.lastUpdatedAt = null;
1236
+ }
1237
+ static getBarsHotWindowTelemetry() {
1238
+ return cloneBarsHotWindowTelemetry(barsHotWindowTelemetry);
1239
+ }
1240
+ static __getBarsHotWindowTelemetryForTests() {
1241
+ return _VNInvestClient.getBarsHotWindowTelemetry();
1242
+ }
1243
+ async getStocks(query, exchange) {
1244
+ const endpoints = buildEndpoints(this._base);
1245
+ const params = new URLSearchParams();
1246
+ if (query) params.set("search", query);
1247
+ if (exchange) params.set("exchange", exchange);
1248
+ const url = `${endpoints.STOCKS_LIST}?${params.toString()}`;
1249
+ const data = await this._fetch(url);
1250
+ if (Array.isArray(data)) return data;
1251
+ if ("results" in data && Array.isArray(data.results)) return data.results;
1252
+ return [];
1253
+ }
1254
+ async getWhaleFeed(symbol) {
1255
+ const endpoints = buildEndpoints(this._base);
1256
+ const data = await this._fetch(endpoints.WHALE_FEED(symbol));
1257
+ if (isWhaleFeedResponse(data)) return data;
1258
+ const obj = data;
1259
+ if (obj && typeof obj === "object" && typeof obj["symbol"] === "string" && Array.isArray(obj["alerts"])) {
1260
+ return mapNativeWhaleFeed(obj);
1261
+ }
1262
+ return null;
1263
+ }
1264
+ async getOrderFlow(symbol, window2 = "30m") {
1265
+ const endpoints = buildEndpoints(this._base);
1266
+ const params = new URLSearchParams({ window: window2 });
1267
+ const url = `${endpoints.ORDER_FLOW(symbol)}?${params.toString()}`;
1268
+ const data = await this._fetch(url);
1269
+ const obj = data;
1270
+ if (!obj || typeof obj !== "object") {
1271
+ return null;
1272
+ }
1273
+ if (obj["ok"] === true) {
1274
+ return obj;
1275
+ }
1276
+ if (typeof obj["symbol"] === "string" && (Array.isArray(obj["signals"]) || typeof obj["dark_flow"] === "object")) {
1277
+ return mapNativeOrderFlow(obj, window2);
1278
+ }
1279
+ return null;
1280
+ }
1281
+ /** Shared GET/POST fetch for the native advisory session endpoint. */
1282
+ async fetchAdvisorySessionV2(url, init) {
1283
+ const data = await this._fetch(url, init).catch(() => null);
1284
+ const obj = data;
1285
+ if (!obj || typeof obj !== "object" || typeof obj["symbol"] !== "string") {
1286
+ return null;
1287
+ }
1288
+ return obj;
1289
+ }
1290
+ /**
1291
+ * Follow-up advisory V2: read the native AI advisory session.
1292
+ * Returns the session in both empty (`reason: "no_advisory_data"`) and record states;
1293
+ * null only on transport/auth failure. Never throws for empty sessions.
1294
+ */
1295
+ async getAdvisorySessionV2(symbol) {
1296
+ return this.fetchAdvisorySessionV2(buildEndpoints(this._base).AI_ADVISORY_V2(symbol));
1297
+ }
1298
+ /**
1299
+ * Follow-up advisory V2: trigger a manual refresh (queues generation server-side).
1300
+ * Returns the updated session payload; null on transport/auth failure.
1301
+ */
1302
+ async refreshAdvisorySession(symbol) {
1303
+ return this.fetchAdvisorySessionV2(buildEndpoints(this._base).AI_ADVISORY_V2(symbol), {
1304
+ method: "POST",
1305
+ headers: { "Content-Type": "application/json" },
1306
+ body: JSON.stringify({})
1307
+ });
1308
+ }
1309
+ /** @deprecated Legacy POST path 404s on current backends — use getAdvisorySessionV2. */
1310
+ async getAdvisorySession(symbol) {
1311
+ const endpoints = buildEndpoints(this._base);
1312
+ const data = await this._fetch(endpoints.AI_ADVISORY, {
1313
+ method: "POST",
1314
+ headers: { "Content-Type": "application/json" },
1315
+ body: JSON.stringify({ symbol })
1316
+ });
1317
+ const obj = data;
1318
+ if (!obj || obj["ok"] !== true) {
1319
+ return null;
1320
+ }
1321
+ return obj;
1322
+ }
1323
+ async getTapeEntries(symbol, pageSize = 100) {
1324
+ const endpoints = buildEndpoints(this._base);
1325
+ const url = `${endpoints.INTRADAY_TAPE(symbol)}?page_size=${Math.max(1, Math.min(200, Math.floor(pageSize)))}`;
1326
+ const data = await this._fetch(url);
1327
+ const obj = data;
1328
+ if (!obj || typeof obj !== "object") {
1329
+ return null;
1330
+ }
1331
+ if (obj["ok"] === true) {
1332
+ return obj;
1333
+ }
1334
+ if (typeof obj["symbol"] === "string" && Array.isArray(obj["trades"])) {
1335
+ return mapNativeTape(obj);
1336
+ }
1337
+ return null;
1338
+ }
1339
+ async _revalidateBarsHotWindow(cacheKey, params) {
1340
+ await revalidateBarsHotWindow(this._base, this._pat, cacheKey, params);
1341
+ }
1342
+ };
1343
+
1344
+ // src/widget/adapters/VNInvestWebSocketClient.ts
1345
+ function unwrapWsEnvelope(parsed) {
1346
+ const data = parsed["data"];
1347
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
1348
+ return parsed;
1349
+ }
1350
+ const body = { ...data };
1351
+ for (const key of ["event_type", "symbol", "ts", "seq"]) {
1352
+ if (body[key] === void 0 && parsed[key] !== void 0) {
1353
+ body[key] = parsed[key];
1354
+ }
1355
+ }
1356
+ return body;
1357
+ }
1358
+ var VNInvestWebSocketClient = class _VNInvestWebSocketClient {
1359
+ static MAX_RECONNECT_ATTEMPTS = 5;
1360
+ static RECONNECT_DELAY_MS = 5e3;
1361
+ static WS_PATH_CANDIDATES = ["/ws/realtime/", "/api/realtime/ws/"];
1362
+ ws = null;
1363
+ pat;
1364
+ apiBase;
1365
+ selectedWsPath = null;
1366
+ wsUnavailable = false;
1367
+ wsProbePromise = null;
1368
+ subscribedSymbols = /* @__PURE__ */ new Set();
1369
+ onTickerUpdateCb = null;
1370
+ onWhaleAlertCb = null;
1371
+ reconnectTimer = null;
1372
+ reconnectAttempts = 0;
1373
+ _isConnected = false;
1374
+ _destroyed = false;
1375
+ constructor(pat, apiBase = resolveApiBase()) {
1376
+ this.pat = pat;
1377
+ this.apiBase = apiBase;
1378
+ }
1379
+ get isConnected() {
1380
+ return this._isConnected;
1381
+ }
1382
+ get destroyed() {
1383
+ return this._destroyed;
1384
+ }
1385
+ buildWsUrl(path = "/ws/realtime/") {
1386
+ const wsBase = this.apiBase.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://").replace(/\/$/, "");
1387
+ return `${wsBase}${path}?token=${encodeURIComponent(this.pat)}`;
1388
+ }
1389
+ buildHttpProbeUrl(path) {
1390
+ const httpBase = this.apiBase.replace(/\/$/, "");
1391
+ return `${httpBase}${path}`;
1392
+ }
1393
+ async probeWsPath(path) {
1394
+ try {
1395
+ const response = await fetch(this.buildHttpProbeUrl(path), {
1396
+ method: "GET",
1397
+ headers: {
1398
+ Authorization: `Bearer ${this.pat}`
1399
+ }
1400
+ });
1401
+ if (response.status === 404 || response.status === 502 || response.status === 503) {
1402
+ return false;
1403
+ }
1404
+ return true;
1405
+ } catch {
1406
+ return false;
1407
+ }
1408
+ }
1409
+ async resolveWsPath() {
1410
+ if (this.selectedWsPath) {
1411
+ return this.selectedWsPath;
1412
+ }
1413
+ try {
1414
+ const hostname = new URL(this.apiBase).hostname;
1415
+ if (hostname.endsWith(".test")) {
1416
+ this.selectedWsPath = _VNInvestWebSocketClient.WS_PATH_CANDIDATES[0];
1417
+ return this.selectedWsPath;
1418
+ }
1419
+ } catch {
1420
+ }
1421
+ if (this.wsProbePromise) {
1422
+ return this.wsProbePromise;
1423
+ }
1424
+ this.wsProbePromise = (async () => {
1425
+ for (const candidate of _VNInvestWebSocketClient.WS_PATH_CANDIDATES) {
1426
+ const available = candidate === "/ws/realtime/" ? true : await this.probeWsPath(candidate);
1427
+ if (available) {
1428
+ this.selectedWsPath = candidate;
1429
+ return candidate;
1430
+ }
1431
+ }
1432
+ this.wsUnavailable = true;
1433
+ return null;
1434
+ })();
1435
+ const resolved = await this.wsProbePromise;
1436
+ this.wsProbePromise = null;
1437
+ return resolved;
1438
+ }
1439
+ connect() {
1440
+ if (this._destroyed || this.ws !== null || this.wsUnavailable) {
1441
+ return;
1442
+ }
1443
+ void this.openConnection();
1444
+ }
1445
+ async openConnection() {
1446
+ if (this._destroyed || this.ws !== null || this.wsUnavailable) {
1447
+ return;
1448
+ }
1449
+ const wsPath = await this.resolveWsPath();
1450
+ if (!wsPath || this._destroyed || this.wsUnavailable) {
1451
+ return;
1452
+ }
1453
+ const url = this.buildWsUrl(wsPath);
1454
+ try {
1455
+ this.ws = new WebSocket(url);
1456
+ } catch {
1457
+ this.scheduleReconnect();
1458
+ return;
1459
+ }
1460
+ this.ws.onopen = () => {
1461
+ this.reconnectAttempts = 0;
1462
+ this._isConnected = true;
1463
+ const symbols = Array.from(this.subscribedSymbols);
1464
+ if (symbols.length > 0) {
1465
+ this.sendJson({ action: "subscribe", symbols });
1466
+ }
1467
+ };
1468
+ this.ws.onmessage = (event) => {
1469
+ this.handleRawMessage(event.data);
1470
+ };
1471
+ this.ws.onclose = (event) => {
1472
+ this.ws = null;
1473
+ this._isConnected = false;
1474
+ if (event.code === 4401) {
1475
+ return;
1476
+ }
1477
+ this.scheduleReconnect();
1478
+ };
1479
+ this.ws.onerror = () => {
1480
+ };
1481
+ }
1482
+ subscribe(symbols) {
1483
+ const normalized = symbols.map((s) => s.trim().toUpperCase()).filter(Boolean);
1484
+ for (const sym of normalized) {
1485
+ this.subscribedSymbols.add(sym);
1486
+ }
1487
+ if (this._isConnected && normalized.length > 0) {
1488
+ this.sendJson({ action: "subscribe", symbols: normalized });
1489
+ }
1490
+ }
1491
+ unsubscribe(symbols) {
1492
+ const normalized = symbols.map((s) => s.trim().toUpperCase()).filter(Boolean);
1493
+ for (const sym of normalized) {
1494
+ this.subscribedSymbols.delete(sym);
1495
+ }
1496
+ if (this._isConnected && normalized.length > 0) {
1497
+ this.sendJson({ action: "unsubscribe", symbols: normalized });
1498
+ }
1499
+ }
1500
+ setOnTickerUpdate(cb) {
1501
+ this.onTickerUpdateCb = cb;
1502
+ }
1503
+ setOnWhaleAlert(cb) {
1504
+ this.onWhaleAlertCb = cb;
1505
+ }
1506
+ destroy() {
1507
+ this._destroyed = true;
1508
+ if (this.reconnectTimer !== null) {
1509
+ clearTimeout(this.reconnectTimer);
1510
+ this.reconnectTimer = null;
1511
+ }
1512
+ if (this.ws !== null) {
1513
+ this.ws.onclose = null;
1514
+ this.ws.onmessage = null;
1515
+ this.ws.onerror = null;
1516
+ this.ws.onopen = null;
1517
+ try {
1518
+ this.ws.close(1e3, "destroy");
1519
+ } catch {
1520
+ }
1521
+ this.ws = null;
1522
+ }
1523
+ this._isConnected = false;
1524
+ }
1525
+ handleRawMessage(data) {
1526
+ let parsed;
1527
+ try {
1528
+ parsed = JSON.parse(data);
1529
+ } catch {
1530
+ return;
1531
+ }
1532
+ const body = unwrapWsEnvelope(parsed);
1533
+ if (body.event_type === "ticker_update") {
1534
+ this.onTickerUpdateCb?.(body);
1535
+ } else if (body.event_type === "whale_alert") {
1536
+ this.onWhaleAlertCb?.(body);
1537
+ }
1538
+ }
1539
+ scheduleReconnect() {
1540
+ if (this._destroyed || this.wsUnavailable || this.reconnectAttempts >= _VNInvestWebSocketClient.MAX_RECONNECT_ATTEMPTS) {
1541
+ return;
1542
+ }
1543
+ this.reconnectAttempts += 1;
1544
+ const delay = _VNInvestWebSocketClient.RECONNECT_DELAY_MS * Math.pow(2, this.reconnectAttempts - 1);
1545
+ this.reconnectTimer = setTimeout(() => {
1546
+ this.reconnectTimer = null;
1547
+ if (!this._destroyed) {
1548
+ this.connect();
1549
+ }
1550
+ }, delay);
1551
+ }
1552
+ sendJson(msg) {
1553
+ if (this.ws?.readyState === WebSocket.OPEN) {
1554
+ this.ws.send(JSON.stringify(msg));
1555
+ }
1556
+ }
1557
+ };
1558
+
1559
+ // src/widget/adapters/VNInvestDataAdapter.ts
1560
+ var PAGE_LIMIT = 1e3;
1561
+ var VNInvestDataAdapter = class {
1562
+ name = "vninvest";
1563
+ client;
1564
+ wsClient = null;
1565
+ barSubscribers = /* @__PURE__ */ new Map();
1566
+ snapshotIds = /* @__PURE__ */ new Map();
1567
+ lastBackfillCoverageMap = /* @__PURE__ */ new Map();
1568
+ lastRangeCoverageMap = /* @__PURE__ */ new Map();
1569
+ constructor(config) {
1570
+ this.client = new VNInvestClient(config.patToken);
1571
+ if (config.apiBase) {
1572
+ this.client.setBase(config.apiBase);
1573
+ }
1574
+ }
1575
+ setAuthHandler(handler) {
1576
+ this.client.setAuthHandler(handler);
1577
+ }
1578
+ getSourceSemantics() {
1579
+ return {
1580
+ sourceId: this.name,
1581
+ sourceContractVersion: "vninvest-backfill-v1",
1582
+ instrumentClass: "equity",
1583
+ coverageMode: "exact-range",
1584
+ sessionModel: "exchange-calendar",
1585
+ timezone: "Asia/Ho_Chi_Minh",
1586
+ sessionCalendarId: "vn-exchange-calendar",
1587
+ supportsExactRangeFetch: true,
1588
+ supportsBackwardAnchor: true,
1589
+ supportsForwardAnchor: false,
1590
+ supportsLiveBars: true,
1591
+ maxBarsPerRequest: PAGE_LIMIT,
1592
+ finalityMode: "historically-correctable",
1593
+ correctionLookbackMs: 30 * 864e5,
1594
+ expectedGapReasons: ["not-fetched", "market-closed", "source-no-data", "rate-limited", "boundary-exhausted"]
1595
+ };
1596
+ }
1597
+ coverageKey(symbol, timeframe, chartId) {
1598
+ const scope = chartId ?? "__global__";
1599
+ return `${scope}:${symbol.toUpperCase()}:${timeframe}`;
1600
+ }
1601
+ getLastBackfillCoverage(symbol, timeframe, chartId) {
1602
+ if (!symbol || !timeframe) {
1603
+ return null;
1604
+ }
1605
+ const key = this.coverageKey(symbol, timeframe, chartId);
1606
+ return this.lastBackfillCoverageMap.get(key) ?? null;
1607
+ }
1608
+ getLastRangeCoverage(symbol, timeframe, chartId) {
1609
+ if (!symbol || !timeframe) {
1610
+ return null;
1611
+ }
1612
+ const key = this.coverageKey(symbol, timeframe, chartId);
1613
+ return this.lastRangeCoverageMap.get(key) ?? null;
1614
+ }
1615
+ /** Expose the underlying REST client for advanced use cases. */
1616
+ get restClient() {
1617
+ return this.client;
1618
+ }
1619
+ /**
1620
+ * Fetch bars in a date range.
1621
+ * Uses the cursor-paged /bars/ endpoint with backward pagination.
1622
+ *
1623
+ * 504-guard: a single wide intraday window (e.g. 90d of 1H) times the server
1624
+ * out — each request is capped to MAX_INTRADAY_SPAN_MS and the existing
1625
+ * hasMoreAfter/nextAfter loop walks the remainder. Daily+ ranges are unaffected.
1626
+ */
1627
+ async fetchBarsInRange(symbol, timeframe, from, to, chartId, signal) {
1628
+ const throwIfAborted = () => {
1629
+ if (signal?.aborted) throw new DOMException("Aborted", "AbortError");
1630
+ };
1631
+ throwIfAborted();
1632
+ const allBars = [];
1633
+ const chunkSpan = isIntradayTimeframe(timeframe) ? MAX_INTRADAY_SPAN_MS : Number.POSITIVE_INFINITY;
1634
+ const initParams = {
1635
+ type: "init",
1636
+ symbol,
1637
+ timeframe,
1638
+ from: from.valueOf(),
1639
+ to: Math.min(to.valueOf(), from.valueOf() + chunkSpan),
1640
+ limit: PAGE_LIMIT
1641
+ };
1642
+ let page = await this.client.getBarsPage(initParams);
1643
+ const key = this.coverageKey(symbol, timeframe, chartId);
1644
+ if (page.snapshotId) {
1645
+ this.snapshotIds.set(key, page.snapshotId);
1646
+ }
1647
+ let bars = sortBarsByDate(pageToOHLCV(page.bars));
1648
+ allBars.push(...bars);
1649
+ while (page.hasMoreAfter && page.nextAfter !== null) {
1650
+ throwIfAborted();
1651
+ const forwardParams = {
1652
+ type: "init",
1653
+ symbol,
1654
+ timeframe,
1655
+ from: page.nextAfter,
1656
+ to: Math.min(to.valueOf(), page.nextAfter + chunkSpan),
1657
+ limit: PAGE_LIMIT
1658
+ };
1659
+ page = await this.client.getBarsPage(forwardParams);
1660
+ if (page.snapshotId) {
1661
+ this.snapshotIds.set(key, page.snapshotId);
1662
+ }
1663
+ bars = sortBarsByDate(pageToOHLCV(page.bars));
1664
+ if (bars.length === 0) break;
1665
+ allBars.push(...bars);
1666
+ }
1667
+ if (allBars.length === 0) {
1668
+ this.lastRangeCoverageMap.set(key, [
1669
+ { fromTs: from.valueOf(), toTs: to.valueOf(), status: "unresolved", reason: "source-no-data" }
1670
+ ]);
1671
+ } else {
1672
+ const oldestTs = allBars[0].date.getTime();
1673
+ const newestTs = allBars[allBars.length - 1].date.getTime();
1674
+ const covered = { fromTs: oldestTs, toTs: newestTs, status: "covered" };
1675
+ const fragments = [covered];
1676
+ if (!page.hasMoreBefore) {
1677
+ fragments.unshift({ fromTs: 0, toTs: oldestTs, status: "unresolved", reason: "boundary-exhausted" });
1678
+ }
1679
+ if (!page.hasMoreAfter) {
1680
+ fragments.push({ fromTs: newestTs, toTs: to.valueOf(), status: "unresolved", reason: "boundary-exhausted" });
1681
+ }
1682
+ this.lastRangeCoverageMap.set(key, fragments);
1683
+ }
1684
+ return allBars;
1685
+ }
1686
+ /**
1687
+ * Fetch bars before a given anchor date (backward pagination).
1688
+ */
1689
+ async fetchBarsBefore(symbol, timeframe, before, limit = PAGE_LIMIT, chartId) {
1690
+ const key = this.coverageKey(symbol, timeframe, chartId);
1691
+ const snapshotId = this.snapshotIds.get(key);
1692
+ const params = {
1693
+ type: "backward",
1694
+ symbol,
1695
+ timeframe,
1696
+ before: before.valueOf(),
1697
+ limit,
1698
+ snapshotId
1699
+ };
1700
+ const page = await this.client.getBarsPage(params);
1701
+ if (page.snapshotId) {
1702
+ this.snapshotIds.set(key, page.snapshotId);
1703
+ }
1704
+ const bars = sortBarsByDate(pageToOHLCV(page.bars));
1705
+ if (bars.length === 0) {
1706
+ this.lastBackfillCoverageMap.set(key, [
1707
+ { fromTs: 0, toTs: before.valueOf(), status: "unresolved", reason: "boundary-exhausted" }
1708
+ ]);
1709
+ } else {
1710
+ const oldestTs = bars[0].date.getTime();
1711
+ const newestTs = bars[bars.length - 1].date.getTime();
1712
+ const covered = { fromTs: oldestTs, toTs: newestTs, status: "covered" };
1713
+ if (!page.hasMoreBefore) {
1714
+ this.lastBackfillCoverageMap.set(key, [
1715
+ { fromTs: 0, toTs: oldestTs, status: "unresolved", reason: "boundary-exhausted" },
1716
+ covered
1717
+ ]);
1718
+ } else {
1719
+ this.lastBackfillCoverageMap.set(key, [covered]);
1720
+ }
1721
+ }
1722
+ return bars;
1723
+ }
1724
+ /**
1725
+ * Subscribe to real-time bar updates via WebSocket.
1726
+ * Maps ticker_update events to OHLCVBar callbacks.
1727
+ */
1728
+ subscribeToBar(symbol, timeframe, onBar) {
1729
+ const key = `${symbol.toUpperCase()}:${timeframe}`;
1730
+ if (!this.wsClient) {
1731
+ this.wsClient = new VNInvestWebSocketClient(
1732
+ this.client.getPAT(),
1733
+ this.client.getBase()
1734
+ );
1735
+ this.wsClient.setOnTickerUpdate(this.handleTickerUpdate.bind(this));
1736
+ this.wsClient.connect();
1737
+ }
1738
+ if (!this.barSubscribers.has(key)) {
1739
+ this.barSubscribers.set(key, /* @__PURE__ */ new Set());
1740
+ this.wsClient.subscribe([symbol.toUpperCase()]);
1741
+ }
1742
+ this.barSubscribers.get(key).add(onBar);
1743
+ return () => {
1744
+ const subs = this.barSubscribers.get(key);
1745
+ if (subs) {
1746
+ subs.delete(onBar);
1747
+ if (subs.size === 0) {
1748
+ this.barSubscribers.delete(key);
1749
+ this.wsClient?.unsubscribe([symbol.toUpperCase()]);
1750
+ }
1751
+ }
1752
+ };
1753
+ }
1754
+ /** Not supported by VNInvest — returns no-op. */
1755
+ subscribeToTrades(_symbol, _onTrade) {
1756
+ return () => {
1757
+ };
1758
+ }
1759
+ /** Not supported by VNInvest — returns no-op. */
1760
+ subscribeToOrderbook(_symbol, _onUpdate) {
1761
+ return () => {
1762
+ };
1763
+ }
1764
+ /** Search symbols via GET /stocks/ endpoint. */
1765
+ async searchSymbols(query) {
1766
+ const items = await this.client.getStocks(query);
1767
+ return items.map((item) => ({
1768
+ symbol: item.symbol,
1769
+ name: item.company_name,
1770
+ exchange: item.exchange
1771
+ }));
1772
+ }
1773
+ /** Clean up: destroy WebSocket connection. */
1774
+ destroy() {
1775
+ this.wsClient?.destroy();
1776
+ this.wsClient = null;
1777
+ this.barSubscribers.clear();
1778
+ }
1779
+ handleTickerUpdate(event) {
1780
+ if (event.stale) return;
1781
+ const price = Number.isFinite(event.price) ? event.price : event.current_price;
1782
+ const currentPrice = Number.isFinite(event.current_price) ? event.current_price : price;
1783
+ if (!Number.isFinite(currentPrice)) return;
1784
+ const high = Number.isFinite(event.high_price) ? event.high_price : currentPrice;
1785
+ const low = Number.isFinite(event.low_price) ? event.low_price : currentPrice;
1786
+ const open = Number.isFinite(event.open_price) ? event.open_price : price;
1787
+ const symbolUpper = event.symbol.toUpperCase();
1788
+ const seq = Number.isFinite(event.seq) ? event.seq : 0;
1789
+ const volume = Number.isFinite(event.volume) ? event.volume : 0;
1790
+ for (const [key, subs] of this.barSubscribers.entries()) {
1791
+ if (key.startsWith(`${symbolUpper}:`)) {
1792
+ const bar = {
1793
+ date: new Date(event.ts),
1794
+ open,
1795
+ high,
1796
+ low,
1797
+ close: currentPrice,
1798
+ volume,
1799
+ index: seq,
1800
+ dataIndex: seq
1801
+ };
1802
+ for (const cb of subs) {
1803
+ cb(bar);
1804
+ }
1805
+ }
1806
+ }
1807
+ }
1808
+ };
1809
+ var INTRADAY_TIMEFRAMES = /* @__PURE__ */ new Set(["1m", "5m", "15m", "1h", "2h", "4h"]);
1810
+ var MAX_INTRADAY_SPAN_MS = 30 * 24 * 60 * 60 * 1e3;
1811
+ function isIntradayTimeframe(timeframe) {
1812
+ return INTRADAY_TIMEFRAMES.has(String(timeframe).toLowerCase());
1813
+ }
1814
+ function pageToOHLCV(bars) {
1815
+ return bars.map((bar, index) => ({
1816
+ date: bar.date,
1817
+ open: bar.open,
1818
+ high: bar.high,
1819
+ low: bar.low,
1820
+ close: bar.close,
1821
+ volume: bar.volume,
1822
+ index,
1823
+ dataIndex: index
1824
+ }));
1825
+ }
1826
+ function sortBarsByDate(bars) {
1827
+ return bars.sort((a, b) => a.date.valueOf() - b.date.valueOf());
1828
+ }
1829
+ function useWatchlistRealtimeSync({
1830
+ wsClient,
1831
+ symbols,
1832
+ onUpdate,
1833
+ throttleMs = 500
1834
+ }) {
1835
+ const [tickerData, setTickerData] = react.useState(/* @__PURE__ */ new Map());
1836
+ const bufferRef = react.useRef(/* @__PURE__ */ new Map());
1837
+ const onUpdateRef = react.useRef(onUpdate);
1838
+ onUpdateRef.current = onUpdate;
1839
+ const subscribedSymbolsRef = react.useRef(/* @__PURE__ */ new Set());
1840
+ react.useEffect(() => {
1841
+ if (!wsClient || symbols.length === 0) return;
1842
+ const ws = wsClient;
1843
+ const uppercaseSymbols = symbols.map((s) => s.trim().toUpperCase()).filter(Boolean);
1844
+ ws.subscribe(uppercaseSymbols);
1845
+ for (const sym of uppercaseSymbols) {
1846
+ subscribedSymbolsRef.current.add(sym);
1847
+ }
1848
+ const handleTickerUpdate = (event) => {
1849
+ const sym = event.symbol.toUpperCase();
1850
+ if (subscribedSymbolsRef.current.has(sym)) {
1851
+ bufferRef.current.set(sym, event);
1852
+ }
1853
+ };
1854
+ ws.setOnTickerUpdate(handleTickerUpdate);
1855
+ const intervalId = setInterval(() => {
1856
+ if (bufferRef.current.size === 0) return;
1857
+ setTickerData((prev) => {
1858
+ const next = new Map(prev);
1859
+ bufferRef.current.forEach((value, key) => {
1860
+ next.set(key, value);
1861
+ });
1862
+ onUpdateRef.current?.(next);
1863
+ return next;
1864
+ });
1865
+ bufferRef.current.clear();
1866
+ }, throttleMs);
1867
+ return () => {
1868
+ clearInterval(intervalId);
1869
+ const activeSymbols = Array.from(subscribedSymbolsRef.current);
1870
+ if (activeSymbols.length > 0) {
1871
+ ws.unsubscribe(activeSymbols);
1872
+ }
1873
+ subscribedSymbolsRef.current.clear();
1874
+ bufferRef.current.clear();
1875
+ };
1876
+ }, [wsClient, symbols, throttleMs]);
1877
+ return tickerData;
1878
+ }
1879
+
1880
+ // src/lib/adapters/ContinuousContractTypes.ts
1881
+ var DEFAULT_VN_FUTURES_ROLL_CONFIG = {
1882
+ "VN30F1M": {
1883
+ rootSymbol: "VN30F",
1884
+ rollMethod: "ratio",
1885
+ rollTrigger: "days-before-expiry",
1886
+ rollDaysBeforeExpiry: 3,
1887
+ adjustVolumes: true
1888
+ },
1889
+ "VN30F1M-panama": {
1890
+ rootSymbol: "VN30F",
1891
+ rollMethod: "panama",
1892
+ rollTrigger: "days-before-expiry",
1893
+ rollDaysBeforeExpiry: 3,
1894
+ adjustVolumes: true
1895
+ },
1896
+ "VN30F3M": {
1897
+ rootSymbol: "VN30F",
1898
+ rollMethod: "ratio",
1899
+ rollTrigger: "days-before-expiry",
1900
+ rollDaysBeforeExpiry: 5,
1901
+ adjustVolumes: true
1902
+ }
1903
+ };
1904
+
1905
+ // src/lib/utils/logger.ts
1906
+ var noop = () => {
1907
+ };
1908
+ var noopLogger = {
1909
+ log: noop,
1910
+ info: noop,
1911
+ warn: noop,
1912
+ error: noop,
1913
+ debug: noop,
1914
+ trace: noop,
1915
+ extend: () => noopLogger
1916
+ };
1917
+ function isDebugEnabled() {
1918
+ if (typeof process !== "undefined" && process.env?.DEBUG) return true;
1919
+ try {
1920
+ if (typeof localStorage !== "undefined") {
1921
+ return !!(localStorage.getItem("DEBUG") || localStorage.getItem("VNINVEST_DEBUG"));
1922
+ }
1923
+ } catch {
1924
+ }
1925
+ return false;
1926
+ }
1927
+ var enabled = isDebugEnabled();
1928
+ function createLogFn(namespace, level) {
1929
+ if (!enabled) return noop;
1930
+ return (...args) => {
1931
+ console[level](`[${namespace}]`, ...args);
1932
+ };
1933
+ }
1934
+ function createLogger(namespace) {
1935
+ if (!enabled) return noopLogger;
1936
+ return {
1937
+ log: createLogFn(namespace, "log"),
1938
+ info: createLogFn(namespace, "info"),
1939
+ warn: createLogFn(namespace, "warn"),
1940
+ error: createLogFn(namespace, "error"),
1941
+ debug: createLogFn(namespace, "debug"),
1942
+ trace: createLogFn(namespace, "trace"),
1943
+ extend: (sub) => createLogger(`${namespace}:${sub}`)
1944
+ };
1945
+ }
1946
+ function createAdapterLogger(adapterName) {
1947
+ return createLogger(`vninvestcharts-widget:adapter:${adapterName}`);
1948
+ }
1949
+
1950
+ // src/lib/adapters/ContinuousContractAdapter.ts
1951
+ var log = createAdapterLogger("continuous-contract");
1952
+ var BFF_ENDPOINT = "/api/continuous-futures/stitch";
1953
+ var metadataCache = /* @__PURE__ */ new Map();
1954
+ var barsCache = /* @__PURE__ */ new Map();
1955
+ var ContinuousContractAdapter = class {
1956
+ name = "continuous-futures";
1957
+ config;
1958
+ rootSymbol;
1959
+ fetchRawBars;
1960
+ constructor(rootSymbol, config, fetchRawBars) {
1961
+ this.rootSymbol = rootSymbol;
1962
+ const defaultConfig = DEFAULT_VN_FUTURES_ROLL_CONFIG[rootSymbol] ?? DEFAULT_VN_FUTURES_ROLL_CONFIG["VN30F1M"];
1963
+ this.config = { ...defaultConfig, ...config, rootSymbol };
1964
+ this.fetchRawBars = fetchRawBars;
1965
+ }
1966
+ /** Get the continuous contract configuration */
1967
+ getConfig() {
1968
+ return { ...this.config };
1969
+ }
1970
+ /** Update roll configuration */
1971
+ setConfig(config) {
1972
+ this.config = { ...this.config, ...config };
1973
+ metadataCache.delete(this.rootSymbol);
1974
+ }
1975
+ async getBars(params) {
1976
+ const continuousParams = this.mapToContinuousParams(params);
1977
+ const result = await this.fetchContinuousBars(continuousParams);
1978
+ return {
1979
+ bars: result.bars,
1980
+ hasMore: result.hasMore
1981
+ };
1982
+ }
1983
+ async getBarsCanonical(params) {
1984
+ const continuousParams = this.mapToContinuousParams(params);
1985
+ const result = await this.fetchContinuousBars(continuousParams);
1986
+ const coverage = this.buildCoverage(result, continuousParams);
1987
+ return {
1988
+ bars: result.bars,
1989
+ hasMore: result.hasMore,
1990
+ coverage
1991
+ };
1992
+ }
1993
+ async fetchBarsInRange(symbol, timeframe, from, to, signal) {
1994
+ const params = {
1995
+ rootSymbol: symbol,
1996
+ interval: timeframe,
1997
+ type: "init",
1998
+ timestamp: null,
1999
+ limit: Math.ceil((to.getTime() - from.getTime()) / this.intervalToMs(timeframe)) + 100,
2000
+ signal
2001
+ };
2002
+ const result = await this.fetchContinuousBars(params);
2003
+ return result.bars.filter(
2004
+ (bar) => bar.timestamp >= from.getTime() && bar.timestamp <= to.getTime()
2005
+ );
2006
+ }
2007
+ async fetchBarsBefore(symbol, timeframe, before, limit, signal) {
2008
+ const params = {
2009
+ rootSymbol: symbol,
2010
+ interval: timeframe,
2011
+ type: "backward",
2012
+ timestamp: before.getTime(),
2013
+ limit: limit ?? 500,
2014
+ signal
2015
+ };
2016
+ const result = await this.fetchContinuousBars(params);
2017
+ return result.bars;
2018
+ }
2019
+ getSourceSemantics() {
2020
+ return {
2021
+ sourceId: this.name,
2022
+ sourceContractVersion: "continuous-futures-v1",
2023
+ instrumentClass: "futures",
2024
+ coverageMode: "window-hint",
2025
+ sessionModel: "exchange-calendar",
2026
+ timezone: "Asia/Ho_Chi_Minh",
2027
+ sessionCalendarId: "vn-futures-calendar",
2028
+ supportsExactRangeFetch: true,
2029
+ supportsBackwardAnchor: true,
2030
+ supportsForwardAnchor: false,
2031
+ supportsLiveBars: true,
2032
+ maxBarsPerRequest: 5e3,
2033
+ finalityMode: "historically-correctable",
2034
+ correctionLookbackMs: 7 * 24 * 60 * 60 * 1e3,
2035
+ // 1 week
2036
+ expectedGapReasons: [
2037
+ "not-fetched",
2038
+ "market-closed",
2039
+ "source-no-data",
2040
+ "rate-limited",
2041
+ "boundary-exhausted",
2042
+ "roll-gap"
2043
+ ]
2044
+ };
2045
+ }
2046
+ /**
2047
+ * Fetch continuous contract bars - tries BFF first, falls back to local computation
2048
+ */
2049
+ async fetchContinuousBars(params) {
2050
+ const cacheKey = this.getCacheKey(params);
2051
+ const cached = barsCache.get(cacheKey);
2052
+ if (cached && params.type !== "backward") {
2053
+ const metadata = await this.getMetadata();
2054
+ return {
2055
+ bars: cached.slice(-params.limit),
2056
+ hasMore: cached.length > params.limit,
2057
+ metadata,
2058
+ rollPointsInRange: []
2059
+ };
2060
+ }
2061
+ try {
2062
+ const bffResult = await this.fetchFromBFF(params);
2063
+ if (bffResult) {
2064
+ this.cacheBars(cacheKey, bffResult.bars);
2065
+ return bffResult;
2066
+ }
2067
+ } catch (error) {
2068
+ log.warn("[ContinuousContractAdapter] BFF fetch failed, falling back to local:", error);
2069
+ }
2070
+ return this.computeLocally(params);
2071
+ }
2072
+ /**
2073
+ * Fetch from BFF endpoint
2074
+ */
2075
+ async fetchFromBFF(params) {
2076
+ const metadata = await this.getMetadata();
2077
+ const from = params.type === "backward" && params.timestamp ? params.timestamp - params.limit * this.intervalToMs(params.interval) : metadata.dataRange.from;
2078
+ const to = params.type === "backward" && params.timestamp ? params.timestamp : metadata.dataRange.to;
2079
+ const request = {
2080
+ method: "POST",
2081
+ headers: { "Content-Type": "application/json" },
2082
+ body: JSON.stringify({
2083
+ rootSymbol: params.rootSymbol,
2084
+ interval: params.interval,
2085
+ from,
2086
+ to,
2087
+ rollConfig: this.config
2088
+ }),
2089
+ signal: params.signal
2090
+ };
2091
+ const response = await fetch(BFF_ENDPOINT, request);
2092
+ if (!response.ok) {
2093
+ throw new Error(`BFF error: ${response.status}`);
2094
+ }
2095
+ const data = await response.json();
2096
+ return {
2097
+ bars: data.bars,
2098
+ hasMore: data.bars.length >= params.limit,
2099
+ metadata: data.metadata,
2100
+ rollPointsInRange: data.rollPoints
2101
+ };
2102
+ }
2103
+ /**
2104
+ * Local computation fallback - stitches contracts client-side
2105
+ * Requires individual contract data to be available via another adapter
2106
+ */
2107
+ async computeLocally(params) {
2108
+ const metadata = await this.getMetadata();
2109
+ if (!this.fetchRawBars) {
2110
+ log.warn("[ContinuousContractAdapter] fetchRawBars not provided, cannot compute locally");
2111
+ return {
2112
+ bars: [],
2113
+ hasMore: false,
2114
+ metadata,
2115
+ rollPointsInRange: []
2116
+ };
2117
+ }
2118
+ const fromMs = params.type === "backward" && params.timestamp ? params.timestamp - params.limit * this.intervalToMs(params.interval) : metadata.dataRange.from;
2119
+ const toMs = params.type === "backward" && params.timestamp ? params.timestamp : metadata.dataRange.to;
2120
+ const relevantContracts = metadata.contracts.filter(
2121
+ (c) => c.lastTradeDate >= fromMs && c.firstTradeDate <= toMs
2122
+ );
2123
+ if (relevantContracts.length === 0) {
2124
+ return {
2125
+ bars: [],
2126
+ hasMore: false,
2127
+ metadata,
2128
+ rollPointsInRange: []
2129
+ };
2130
+ }
2131
+ const contractBars = /* @__PURE__ */ new Map();
2132
+ await Promise.all(
2133
+ relevantContracts.map(async (c) => {
2134
+ try {
2135
+ const bars = await this.fetchRawBars(c.symbol, params.interval, new Date(fromMs), new Date(toMs));
2136
+ contractBars.set(c.symbol, [...bars]);
2137
+ } catch (err) {
2138
+ log.error(`Failed to fetch raw bars for contract ${c.symbol}:`, err);
2139
+ }
2140
+ })
2141
+ );
2142
+ const { computeRollAdjustment: computeRollAdjustment2 } = await Promise.resolve().then(() => (init_rollAlgorithms(), rollAlgorithms_exports));
2143
+ const stitchResult = computeRollAdjustment2({
2144
+ contracts: relevantContracts,
2145
+ contractBars,
2146
+ config: {
2147
+ rollMethod: this.config.rollMethod,
2148
+ adjustVolumes: this.config.adjustVolumes
2149
+ },
2150
+ from: fromMs,
2151
+ to: toMs
2152
+ });
2153
+ return {
2154
+ bars: stitchResult.bars,
2155
+ hasMore: stitchResult.bars.length >= params.limit,
2156
+ metadata: {
2157
+ ...metadata,
2158
+ totalCumulativeAdjustment: stitchResult.totalCumulativeAdjustment
2159
+ },
2160
+ rollPointsInRange: stitchResult.rollPoints
2161
+ };
2162
+ }
2163
+ /**
2164
+ * Get or fetch continuous contract metadata
2165
+ */
2166
+ async getMetadata() {
2167
+ if (metadataCache.has(this.rootSymbol)) {
2168
+ return metadataCache.get(this.rootSymbol);
2169
+ }
2170
+ try {
2171
+ const response = await fetch(`${BFF_ENDPOINT}/metadata?rootSymbol=${this.rootSymbol}`);
2172
+ if (response.ok) {
2173
+ const metadata2 = await response.json();
2174
+ metadataCache.set(this.rootSymbol, metadata2);
2175
+ return metadata2;
2176
+ }
2177
+ } catch {
2178
+ }
2179
+ const metadata = this.generateSyntheticMetadata();
2180
+ metadataCache.set(this.rootSymbol, metadata);
2181
+ return metadata;
2182
+ }
2183
+ /**
2184
+ * Generate synthetic metadata for development/testing
2185
+ */
2186
+ generateSyntheticMetadata() {
2187
+ const now = Date.now();
2188
+ const contracts = [
2189
+ {
2190
+ symbol: "VN30F2409",
2191
+ rootSymbol: "VN30F",
2192
+ expiry: (/* @__PURE__ */ new Date("2024-09-19")).getTime(),
2193
+ firstTradeDate: (/* @__PURE__ */ new Date("2024-06-20")).getTime(),
2194
+ lastTradeDate: (/* @__PURE__ */ new Date("2024-09-16")).getTime(),
2195
+ monthCode: "U",
2196
+ year: 24,
2197
+ tickSize: 0.1,
2198
+ multiplier: 1e5,
2199
+ exchange: "VNX"
2200
+ },
2201
+ {
2202
+ symbol: "VN30F2412",
2203
+ rootSymbol: "VN30F",
2204
+ expiry: (/* @__PURE__ */ new Date("2024-12-19")).getTime(),
2205
+ firstTradeDate: (/* @__PURE__ */ new Date("2024-09-20")).getTime(),
2206
+ lastTradeDate: (/* @__PURE__ */ new Date("2024-12-16")).getTime(),
2207
+ monthCode: "Z",
2208
+ year: 24,
2209
+ tickSize: 0.1,
2210
+ multiplier: 1e5,
2211
+ exchange: "VNX"
2212
+ },
2213
+ {
2214
+ symbol: "VN30F2503",
2215
+ rootSymbol: "VN30F",
2216
+ expiry: (/* @__PURE__ */ new Date("2025-03-20")).getTime(),
2217
+ firstTradeDate: (/* @__PURE__ */ new Date("2024-12-20")).getTime(),
2218
+ lastTradeDate: (/* @__PURE__ */ new Date("2025-03-17")).getTime(),
2219
+ monthCode: "H",
2220
+ year: 25,
2221
+ tickSize: 0.1,
2222
+ multiplier: 1e5,
2223
+ exchange: "VNX"
2224
+ }
2225
+ ];
2226
+ const rollPoints = [];
2227
+ let cumulativeAdjustment = 0;
2228
+ for (let i = 0; i < contracts.length - 1; i++) {
2229
+ const fromContract = contracts[i];
2230
+ const toContract = contracts[i + 1];
2231
+ const rollDate = fromContract.lastTradeDate;
2232
+ const fromPrice = 1200 + i * 10;
2233
+ const toPrice = 1210 + i * 10;
2234
+ let adjustmentFactor = 1;
2235
+ const method = this.config.rollMethod;
2236
+ if (method === "ratio") {
2237
+ adjustmentFactor = fromPrice / toPrice;
2238
+ } else if (method === "panama") {
2239
+ adjustmentFactor = fromPrice - toPrice;
2240
+ cumulativeAdjustment += adjustmentFactor;
2241
+ } else if (method === "backward-ratio") {
2242
+ adjustmentFactor = toPrice / fromPrice;
2243
+ }
2244
+ rollPoints.push({
2245
+ timestamp: rollDate,
2246
+ fromContract: fromContract.symbol,
2247
+ toContract: toContract.symbol,
2248
+ fromPrice,
2249
+ toPrice,
2250
+ adjustmentFactor,
2251
+ cumulativeAdjustment,
2252
+ method
2253
+ });
2254
+ }
2255
+ return {
2256
+ rootSymbol: this.rootSymbol,
2257
+ contracts,
2258
+ rollPoints,
2259
+ activeContract: contracts[contracts.length - 1].symbol,
2260
+ nextRollDate: contracts[contracts.length - 1].lastTradeDate,
2261
+ totalCumulativeAdjustment: cumulativeAdjustment,
2262
+ dataRange: {
2263
+ from: contracts[0].firstTradeDate,
2264
+ to: now
2265
+ }
2266
+ };
2267
+ }
2268
+ /**
2269
+ * Build coverage fragments for canonical fetch
2270
+ */
2271
+ buildCoverage(result, params) {
2272
+ const { bars, metadata } = result;
2273
+ if (bars.length === 0) {
2274
+ if (params.type === "backward" && params.timestamp !== null) {
2275
+ return [
2276
+ { fromTs: 0, toTs: params.timestamp, status: "unresolved", reason: "boundary-exhausted" }
2277
+ ];
2278
+ }
2279
+ return [{ fromTs: 0, toTs: Date.now(), status: "unresolved", reason: "source-no-data" }];
2280
+ }
2281
+ const oldestTs = bars[0].timestamp;
2282
+ const newestTs = bars[bars.length - 1].timestamp;
2283
+ const covered = { fromTs: oldestTs, toTs: newestTs, status: "covered" };
2284
+ const fragments = [covered];
2285
+ if (oldestTs > metadata.dataRange.from) {
2286
+ fragments.unshift({
2287
+ fromTs: metadata.dataRange.from,
2288
+ toTs: oldestTs,
2289
+ status: "unresolved",
2290
+ reason: "not-fetched"
2291
+ });
2292
+ }
2293
+ if (!result.hasMore && newestTs < metadata.dataRange.to) {
2294
+ fragments.push({
2295
+ fromTs: newestTs,
2296
+ toTs: metadata.dataRange.to,
2297
+ status: "unresolved",
2298
+ reason: "boundary-exhausted"
2299
+ });
2300
+ }
2301
+ for (const rollPoint of result.rollPointsInRange) {
2302
+ fragments.push({
2303
+ fromTs: rollPoint.timestamp,
2304
+ toTs: rollPoint.timestamp + 1,
2305
+ status: "covered",
2306
+ reason: "roll-gap"
2307
+ });
2308
+ }
2309
+ return fragments.sort((a, b) => a.fromTs - b.fromTs);
2310
+ }
2311
+ mapToContinuousParams(params) {
2312
+ return {
2313
+ rootSymbol: params.symbol,
2314
+ interval: params.interval,
2315
+ type: params.type,
2316
+ timestamp: params.timestamp,
2317
+ limit: params.limit,
2318
+ signal: params.signal
2319
+ };
2320
+ }
2321
+ getCacheKey(params) {
2322
+ return `${params.rootSymbol}|${params.interval}|${params.type}|${params.timestamp ?? "init"}|${params.limit}`;
2323
+ }
2324
+ cacheBars(key, bars) {
2325
+ if (barsCache.size > 50) {
2326
+ const firstKey = barsCache.keys().next().value;
2327
+ if (firstKey) barsCache.delete(firstKey);
2328
+ }
2329
+ barsCache.set(key, bars);
2330
+ }
2331
+ intervalToMs(interval) {
2332
+ switch (interval) {
2333
+ case "1m":
2334
+ return 6e4;
2335
+ case "3m":
2336
+ return 18e4;
2337
+ case "5m":
2338
+ return 3e5;
2339
+ case "15m":
2340
+ return 9e5;
2341
+ case "30m":
2342
+ return 18e5;
2343
+ case "1h":
2344
+ case "1H":
2345
+ return 36e5;
2346
+ case "2H":
2347
+ return 72e5;
2348
+ case "4h":
2349
+ case "4H":
2350
+ return 144e5;
2351
+ case "D":
2352
+ case "1D":
2353
+ case "1d":
2354
+ return 864e5;
2355
+ case "W":
2356
+ case "1W":
2357
+ case "1w":
2358
+ return 6048e5;
2359
+ default:
2360
+ return 864e5;
2361
+ }
2362
+ }
2363
+ };
2364
+
2365
+ // src/widget/adapters/ContinuousFuturesStockDataAdapter.ts
2366
+ var ContinuousFuturesStockDataAdapter = class {
2367
+ continuousAdapter;
2368
+ baseAdapter;
2369
+ symbol;
2370
+ constructor(symbol, baseAdapter) {
2371
+ this.baseAdapter = baseAdapter;
2372
+ this.symbol = symbol;
2373
+ const config = DEFAULT_VN_FUTURES_ROLL_CONFIG[symbol] || DEFAULT_VN_FUTURES_ROLL_CONFIG["VN30F1M"];
2374
+ this.continuousAdapter = new ContinuousContractAdapter(
2375
+ config.rootSymbol,
2376
+ config,
2377
+ async (sym, tf, from, to) => {
2378
+ const bars = await this.baseAdapter.fetchBarsInRange(sym, tf, from, to);
2379
+ return bars.map((b) => ({
2380
+ timestamp: b.date.getTime(),
2381
+ open: b.open,
2382
+ high: b.high,
2383
+ low: b.low,
2384
+ close: b.close,
2385
+ volume: b.volume
2386
+ }));
2387
+ }
2388
+ );
2389
+ }
2390
+ async fetchBarsInRange(symbol, timeframe, from, to, chartId) {
2391
+ if (symbol === this.symbol) {
2392
+ const rootSymbol = this.continuousAdapter.getConfig().rootSymbol;
2393
+ const bars = await this.continuousAdapter.fetchBarsInRange?.(rootSymbol, timeframe, from, to);
2394
+ return (bars || []).map((b, index) => ({
2395
+ date: new Date(b.timestamp),
2396
+ open: b.open,
2397
+ high: b.high,
2398
+ low: b.low,
2399
+ close: b.close,
2400
+ volume: b.volume,
2401
+ index,
2402
+ dataIndex: index
2403
+ }));
2404
+ }
2405
+ return this.baseAdapter.fetchBarsInRange(symbol, timeframe, from, to, chartId);
2406
+ }
2407
+ async fetchBarsBefore(symbol, timeframe, before, limit, chartId) {
2408
+ if (symbol === this.symbol) {
2409
+ const rootSymbol = this.continuousAdapter.getConfig().rootSymbol;
2410
+ const bars = await this.continuousAdapter.fetchBarsBefore?.(rootSymbol, timeframe, before, limit);
2411
+ return (bars || []).map((b, index) => ({
2412
+ date: new Date(b.timestamp),
2413
+ open: b.open,
2414
+ high: b.high,
2415
+ low: b.low,
2416
+ close: b.close,
2417
+ volume: b.volume,
2418
+ index,
2419
+ dataIndex: index
2420
+ }));
2421
+ }
2422
+ return this.baseAdapter.fetchBarsBefore(symbol, timeframe, before, limit, chartId);
2423
+ }
2424
+ subscribeToBar(symbol, timeframe, onBar) {
2425
+ if (symbol === this.symbol) {
2426
+ let unsubscribed = false;
2427
+ let innerUnsubscribe = null;
2428
+ this.continuousAdapter.getMetadata().then((metadata) => {
2429
+ if (unsubscribed) return;
2430
+ const activeContract = metadata.activeContract || symbol;
2431
+ innerUnsubscribe = this.baseAdapter.subscribeToBar(activeContract, timeframe, onBar);
2432
+ }).catch((err) => {
2433
+ console.warn("Failed to resolve active contract for continuous subscription:", err);
2434
+ });
2435
+ return () => {
2436
+ unsubscribed = true;
2437
+ if (innerUnsubscribe) innerUnsubscribe();
2438
+ };
2439
+ }
2440
+ return this.baseAdapter.subscribeToBar(symbol, timeframe, onBar);
2441
+ }
2442
+ subscribeToTrades(symbol, onTrade) {
2443
+ return this.baseAdapter.subscribeToTrades(symbol, onTrade);
2444
+ }
2445
+ subscribeToOrderbook(symbol, onUpdate) {
2446
+ return this.baseAdapter.subscribeToOrderbook(symbol, onUpdate);
2447
+ }
2448
+ async searchSymbols(query) {
2449
+ return this.baseAdapter.searchSymbols(query);
2450
+ }
2451
+ getSourceSemantics() {
2452
+ return this.continuousAdapter.getSourceSemantics();
2453
+ }
2454
+ getLastBackfillCoverage(symbol, timeframe, chartId) {
2455
+ return this.baseAdapter.getLastBackfillCoverage?.(symbol, timeframe, chartId) ?? null;
2456
+ }
2457
+ getLastRangeCoverage(symbol, timeframe, chartId) {
2458
+ return this.baseAdapter.getLastRangeCoverage?.(symbol, timeframe, chartId) ?? null;
2459
+ }
2460
+ };
2461
+
2462
+ // src/widget/adapters/MultiSourceDataAdapter.ts
2463
+ function matchAdapter(symbol, config) {
2464
+ const route = config.routes.find((r) => r.pattern.test(symbol));
2465
+ return route?.adapter ?? config.defaultAdapter;
2466
+ }
2467
+ var MultiSourceDataAdapter = class {
2468
+ constructor(config) {
2469
+ this.config = config;
2470
+ this._cache = /* @__PURE__ */ new Map();
2471
+ }
2472
+ config;
2473
+ _cache;
2474
+ _resolve(symbol) {
2475
+ const cached = this._cache.get(symbol);
2476
+ if (cached) {
2477
+ return cached;
2478
+ }
2479
+ const adapter = matchAdapter(symbol, this.config);
2480
+ this._cache.set(symbol, adapter);
2481
+ return adapter;
2482
+ }
2483
+ async fetchBarsInRange(symbol, timeframe, from, to, chartId) {
2484
+ return this._resolve(symbol).fetchBarsInRange(symbol, timeframe, from, to, chartId);
2485
+ }
2486
+ async fetchBarsBefore(symbol, timeframe, before, limit, chartId) {
2487
+ return this._resolve(symbol).fetchBarsBefore(symbol, timeframe, before, limit, chartId);
2488
+ }
2489
+ subscribeToBar(symbol, timeframe, onBar) {
2490
+ return this._resolve(symbol).subscribeToBar(symbol, timeframe, onBar);
2491
+ }
2492
+ subscribeToTrades(symbol, onTrade) {
2493
+ return this._resolve(symbol).subscribeToTrades(symbol, onTrade);
2494
+ }
2495
+ subscribeToOrderbook(symbol, onUpdate) {
2496
+ return this._resolve(symbol).subscribeToOrderbook(symbol, onUpdate);
2497
+ }
2498
+ async searchSymbols(query) {
2499
+ const adapters = [
2500
+ ...this.config.routes.map((r) => r.adapter),
2501
+ this.config.defaultAdapter
2502
+ ];
2503
+ const results = await Promise.all(
2504
+ adapters.map((a) => a.searchSymbols(query))
2505
+ );
2506
+ const flat = results.flat();
2507
+ const seen = /* @__PURE__ */ new Set();
2508
+ return flat.filter((s) => {
2509
+ if (seen.has(s.symbol)) return false;
2510
+ seen.add(s.symbol);
2511
+ return true;
2512
+ });
2513
+ }
2514
+ getLastBackfillCoverage(symbol, timeframe, chartId) {
2515
+ if (!symbol) return null;
2516
+ return this._resolve(symbol).getLastBackfillCoverage?.(symbol, timeframe, chartId) ?? null;
2517
+ }
2518
+ getLastRangeCoverage(symbol, timeframe, chartId) {
2519
+ if (!symbol) return null;
2520
+ return this._resolve(symbol).getLastRangeCoverage?.(symbol, timeframe, chartId) ?? null;
2521
+ }
2522
+ };
2523
+
2524
+ exports.ContinuousFuturesStockDataAdapter = ContinuousFuturesStockDataAdapter;
2525
+ exports.MultiSourceDataAdapter = MultiSourceDataAdapter;
2526
+ exports.TIMEFRAME_MAP = TIMEFRAME_MAP;
2527
+ exports.VNInvestClient = VNInvestClient;
2528
+ exports.VNInvestDataAdapter = VNInvestDataAdapter;
2529
+ exports.VNInvestWebSocketClient = VNInvestWebSocketClient;
2530
+ exports.buildBackwardPageRequest = buildBackwardPageRequest;
2531
+ exports.normalizeBarsPagingMeta = normalizeBarsPagingMeta;
2532
+ exports.resolveApiBase = resolveApiBase;
2533
+ exports.useWatchlistRealtimeSync = useWatchlistRealtimeSync;
2534
+
2535
+ }));