gloomberb 0.17.6 → 0.18.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 (768) hide show
  1. package/README.md +2 -0
  2. package/README.zh-CN.md +2 -0
  3. package/package.json +6 -1
  4. package/patches/electrobun@1.18.1.patch +74 -0
  5. package/src/account/auth-model.ts +3 -2
  6. package/src/account/device-signin-dialog.tsx +38 -13
  7. package/src/account/device-signin.ts +2 -1
  8. package/src/account/upgrade-dialog.tsx +6 -2
  9. package/src/api-client/askg.ts +5 -3
  10. package/src/api-client/bank-figures.ts +73 -0
  11. package/src/api-client/credit-boards.ts +21 -1
  12. package/src/api-client/crypto-markets.ts +88 -1
  13. package/src/api-client/data.ts +104 -4
  14. package/src/api-client/debt-maturities.ts +18 -0
  15. package/src/api-client/equity-screener.ts +3 -0
  16. package/src/api-client/errors.ts +13 -0
  17. package/src/api-client/fund-facts.ts +72 -0
  18. package/src/api-client/futures-curve.ts +26 -3
  19. package/src/api-client/geo.ts +11 -1
  20. package/src/api-client/index.ts +25 -2
  21. package/src/api-client/insider-signals.ts +95 -11
  22. package/src/api-client/normalizers.ts +1 -0
  23. package/src/api-client/paths.ts +20 -1
  24. package/src/api-client/request.ts +11 -3
  25. package/src/api-client/research-activity.ts +15 -8
  26. package/src/api-client/socket.ts +6 -3
  27. package/src/api-client/supply-chain-graph.ts +2 -2
  28. package/src/api-client/supply-chain.ts +8 -0
  29. package/src/api-client/tape.ts +12 -0
  30. package/src/api-client/types.ts +66 -2
  31. package/src/api-client/upgrade-experiment.ts +4 -3
  32. package/src/api-client/wall-experiments.ts +5 -3
  33. package/src/api-client/wall-summary.ts +3 -1
  34. package/src/api-client/web-experiments.ts +5 -2
  35. package/src/api-client/yield-curves.ts +17 -0
  36. package/src/app/command-bar-intro.ts +38 -0
  37. package/src/app/keybindings/actions.ts +1 -1
  38. package/src/app/pane-runtime/pane-template-runtime.ts +35 -7
  39. package/src/app/pane-runtime/plugin-bindings.ts +4 -0
  40. package/src/app/pane-runtime/ticker-open-runtime.ts +4 -14
  41. package/src/app/pane-runtime/ticker-open-target.ts +31 -0
  42. package/src/app/runtime/desktop-deeplink.ts +3 -4
  43. package/src/app/runtime/plugin-bindings.ts +3 -2
  44. package/src/app/runtime/startup.ts +3 -4
  45. package/src/app/runtime/ticker-refresh.ts +13 -12
  46. package/src/app/runtime/update.ts +3 -2
  47. package/src/architecture/core-builtin-allowlist.json +0 -3
  48. package/src/architecture/silent-catch-allowlist.json +3 -0
  49. package/src/architecture/ui-literals-allowlist.json +186 -0
  50. package/src/architecture/ui-tokens-allowlist.json +40 -0
  51. package/src/ask-gloom/pane-context.ts +3 -1
  52. package/src/brokers/signed-in/catalog.ts +2 -1
  53. package/src/brokers/signed-in/client.ts +7 -2
  54. package/src/brokers/signed-in/sign-in-dialog.tsx +120 -26
  55. package/src/brokers/signed-in/sign-in.ts +22 -20
  56. package/src/brokers/sync-broker-instance.ts +2 -1
  57. package/src/capabilities/chart-series.ts +2 -0
  58. package/src/capabilities/registry.ts +1 -3
  59. package/src/cli/bank-section.ts +147 -0
  60. package/src/cli/base-converter.ts +5 -2
  61. package/src/cli/board-coins.ts +70 -0
  62. package/src/cli/commands/fred-series.ts +90 -0
  63. package/src/cli/commands/market.ts +340 -69
  64. package/src/cli/commands/news-search.ts +35 -2
  65. package/src/cli/commands/options-chain.ts +7 -5
  66. package/src/cli/commands/options-leaps.ts +3 -3
  67. package/src/cli/commands/overview.ts +78 -29
  68. package/src/cli/commands/plugins.ts +1 -0
  69. package/src/cli/commands/search.ts +87 -24
  70. package/src/cli/commands/system.ts +5 -2
  71. package/src/cli/commands/ticker.ts +337 -60
  72. package/src/cli/context.ts +2 -1
  73. package/src/cli/desktop-pane-shot.ts +11 -3
  74. package/src/cli/earnings-calendar.ts +2 -1
  75. package/src/cli/errors.ts +10 -0
  76. package/src/cli/export-source.ts +18 -3
  77. package/src/cli/glossary.ts +196 -14
  78. package/src/cli/history-rows.ts +60 -9
  79. package/src/cli/index-roots.ts +26 -0
  80. package/src/cli/index.ts +34 -9
  81. package/src/cli/known-gaps.ts +156 -22
  82. package/src/cli/listing-arg.ts +156 -12
  83. package/src/cli/listing-suggestion.ts +4 -2
  84. package/src/cli/name-entries.ts +76 -0
  85. package/src/cli/not-a-ticker.ts +15 -6
  86. package/src/cli/pane-functions/access-gate.ts +22 -0
  87. package/src/cli/pane-functions/capabilities.ts +62 -4
  88. package/src/cli/pane-functions/catalog.ts +94 -39
  89. package/src/cli/pane-functions/data.ts +6 -5
  90. package/src/cli/pane-functions/discovery.ts +1 -1
  91. package/src/cli/pane-functions/dom.ts +3 -3
  92. package/src/cli/pane-functions/freshness.ts +49 -8
  93. package/src/cli/pane-functions/function-help.ts +13 -10
  94. package/src/cli/pane-functions/headless.ts +177 -42
  95. package/src/cli/pane-functions/index.ts +64 -8
  96. package/src/cli/pane-functions/options.ts +17 -3
  97. package/src/cli/pane-functions/report-notices.ts +17 -3
  98. package/src/cli/pane-functions/resolver.ts +48 -13
  99. package/src/cli/pane-functions/screenshot.ts +124 -23
  100. package/src/cli/pane-functions/shot-options.ts +68 -0
  101. package/src/cli/perpetual-contract.ts +3 -1
  102. package/src/cli/report-tables.ts +10 -2
  103. package/src/cli/staged-tickers.ts +5 -0
  104. package/src/cli/statement-filings.ts +261 -0
  105. package/src/cli/symbol-args.ts +47 -8
  106. package/src/cli/symbol-list.ts +9 -2
  107. package/src/cli/symbol-rows.ts +269 -29
  108. package/src/cli/ticker-resolution.ts +148 -34
  109. package/src/cli/treasury-yields.ts +86 -0
  110. package/src/cli/types.ts +3 -0
  111. package/src/cli/uncovered-instrument.ts +20 -0
  112. package/src/components/chart/composite/axis-overlays.tsx +16 -9
  113. package/src/components/chart/composite/composite-chart.tsx +85 -6
  114. package/src/components/chart/composite/downsample.ts +19 -3
  115. package/src/components/chart/composite/format.ts +3 -0
  116. package/src/components/chart/composite/legend.tsx +155 -76
  117. package/src/components/chart/composite/panel-bitmap.ts +8 -2
  118. package/src/components/chart/composite/panel-surface.tsx +3 -3
  119. package/src/components/chart/composite/toolbar.tsx +12 -7
  120. package/src/components/chart/composite/types.ts +6 -0
  121. package/src/components/chart/composite/use-composite-chart-keyboard.ts +28 -1
  122. package/src/components/chart/curve/curve-surface.tsx +1 -1
  123. package/src/components/chart/static/series.ts +39 -0
  124. package/src/components/chart/static/trail-chart-surface.tsx +2 -1
  125. package/src/components/command-bar/commands/collection-list.ts +45 -15
  126. package/src/components/command-bar/commands/collection.ts +10 -3
  127. package/src/components/command-bar/commands/registry.ts +2 -2
  128. package/src/components/command-bar/list/badge.ts +4 -3
  129. package/src/components/command-bar/list/model.ts +5 -0
  130. package/src/components/command-bar/list/view.tsx +1 -1
  131. package/src/components/command-bar/panel/index.tsx +19 -8
  132. package/src/components/command-bar/panel/native-surface.ts +6 -4
  133. package/src/components/command-bar/panel/prompt-example.ts +22 -0
  134. package/src/components/command-bar/routes/root/provider-search.ts +3 -9
  135. package/src/components/command-bar/routes/root/results.ts +13 -0
  136. package/src/components/command-bar/routes/root/start-here.ts +90 -0
  137. package/src/components/command-bar/routes/ticker-search/results.ts +42 -3
  138. package/src/components/command-bar/routes/ticker-search/route.ts +3 -10
  139. package/src/components/command-bar/theme-picker.tsx +3 -1
  140. package/src/components/command-bar/workflow/builtin.ts +5 -1
  141. package/src/components/command-bar/workflow/collection-actions.ts +21 -12
  142. package/src/components/command-bar/workflow/ops.ts +21 -1
  143. package/src/{plugins/builtin/portfolio-list/command-bar.ts → components/command-bar/workflow/portfolio-position.ts} +42 -9
  144. package/src/components/command-bar/workflow/tickers.ts +6 -4
  145. package/src/components/feedback-dialog.tsx +1 -1
  146. package/src/components/form-modal/broker-step.tsx +7 -63
  147. package/src/components/form-modal/content.tsx +7 -2
  148. package/src/components/form-modal/field-row.tsx +6 -8
  149. package/src/components/form-modal/host.tsx +3 -3
  150. package/src/components/form-modal/model.ts +3 -0
  151. package/src/components/form-modal/routes.ts +17 -2
  152. package/src/components/index.ts +6 -6
  153. package/src/components/input-search-bar.tsx +43 -6
  154. package/src/components/layout/detached-pane-shell.tsx +0 -1
  155. package/src/components/layout/floating-pane.tsx +0 -1
  156. package/src/components/layout/header.tsx +8 -7
  157. package/src/components/layout/pane/footer/index.tsx +7 -4
  158. package/src/components/layout/pane/footer/model.ts +28 -2
  159. package/src/components/layout/pane/header.tsx +9 -19
  160. package/src/components/layout/pane/index.tsx +0 -1
  161. package/src/components/layout/pane/instrument-coverage-gate.tsx +57 -0
  162. package/src/components/layout/pane/pane-tabs.tsx +4 -3
  163. package/src/components/layout/pane/sizing.ts +9 -0
  164. package/src/components/layout/pane/ticker-fate-gate.tsx +8 -2
  165. package/src/components/layout/shell/pane/capture.ts +44 -20
  166. package/src/components/layout/status-bar.tsx +3 -6
  167. package/src/components/markdown-text.tsx +17 -2
  168. package/src/components/market-board/index.tsx +19 -8
  169. package/src/components/metric-treemap/heat-surface.tsx +2 -7
  170. package/src/components/onboarding/account-step/qr-panel.tsx +5 -2
  171. package/src/components/onboarding/onboarding-frame.tsx +24 -21
  172. package/src/components/onboarding/portfolio-step/positions-panel.tsx +20 -10
  173. package/src/components/onboarding/wizard-positions.ts +40 -11
  174. package/src/components/pane-settings-dialog/desktop.tsx +12 -50
  175. package/src/components/pane-settings-dialog/field-dialogs.tsx +1 -1
  176. package/src/components/price-performance.tsx +18 -2
  177. package/src/components/reader/article-reader.tsx +11 -10
  178. package/src/components/reader/detail-reader.tsx +9 -5
  179. package/src/components/reader/reader-text.tsx +51 -24
  180. package/src/components/sign-in-code-panel.tsx +129 -75
  181. package/src/components/ticker/badge/index.tsx +2 -1
  182. package/src/components/ui/action-row.tsx +5 -2
  183. package/src/components/ui/audio-player.tsx +70 -0
  184. package/src/components/ui/card.tsx +75 -0
  185. package/src/components/ui/data-table/index.tsx +4 -2
  186. package/src/components/ui/data-table/types.ts +11 -0
  187. package/src/components/ui/detail-scroll-body.tsx +1 -1
  188. package/src/components/ui/dialog-actions.tsx +1 -21
  189. package/src/components/ui/display.tsx +13 -5
  190. package/src/components/ui/external-link.tsx +4 -2
  191. package/src/components/ui/fields.tsx +12 -0
  192. package/src/components/ui/figure.tsx +5 -3
  193. package/src/components/ui/frame.tsx +40 -6
  194. package/src/components/ui/icon.tsx +4 -0
  195. package/src/components/ui/index.ts +4 -1
  196. package/src/components/ui/list-view.tsx +8 -0
  197. package/src/components/ui/prose.tsx +97 -25
  198. package/src/components/ui/query-bar-keys.tsx +3 -1
  199. package/src/components/ui/query-bar.tsx +6 -0
  200. package/src/components/ui/quote.ts +42 -0
  201. package/src/components/ui/range-track.tsx +15 -2
  202. package/src/components/ui/reveal-in-scroll-box.ts +21 -3
  203. package/src/components/ui/select-button.tsx +38 -3
  204. package/src/components/ui/status.tsx +73 -4
  205. package/src/components/ui/table-layout.ts +20 -0
  206. package/src/components/use-pinned-moment.ts +19 -0
  207. package/src/core/app-runtime.ts +2 -2
  208. package/src/core/state/app/instrument.ts +18 -1
  209. package/src/core/state/app/layout.ts +6 -0
  210. package/src/core/state/app/state.ts +14 -2
  211. package/src/data/cached-query.ts +1 -1
  212. package/src/data/config/chart-settings.ts +3 -1
  213. package/src/data/config/home.ts +4 -1
  214. package/src/data/config/store/node.ts +9 -4
  215. package/src/data/config/store/normalize.ts +9 -0
  216. package/src/data/json-storage.ts +6 -3
  217. package/src/data/json-ticker-repository.ts +3 -1
  218. package/src/data/plugin-cache.ts +5 -1
  219. package/src/data/sqlite/json.ts +3 -1
  220. package/src/data/ticker-repository.ts +5 -2
  221. package/src/feedback/diagnostics.ts +2 -6
  222. package/src/i18n/es.ts +86 -6
  223. package/src/i18n/index.ts +3 -9
  224. package/src/i18n/ja.ts +86 -6
  225. package/src/i18n/ko.ts +86 -6
  226. package/src/i18n/zh-cn.ts +86 -6
  227. package/src/i18n/zh-tw.ts +86 -6
  228. package/src/layout-marketplace/gallery-desktop.tsx +8 -4
  229. package/src/market-data/bars-per-year.ts +43 -0
  230. package/src/market-data/bond-funds.ts +85 -0
  231. package/src/market-data/coordinator/auxiliary.ts +5 -2
  232. package/src/market-data/coordinator/index.ts +6 -5
  233. package/src/market-data/futures-contract.ts +102 -5
  234. package/src/market-data/hooks.tsx +20 -11
  235. package/src/market-data/market/bar-period.ts +36 -0
  236. package/src/market-data/market/format.ts +5 -13
  237. package/src/market-data/market/freshness.ts +1 -3
  238. package/src/market-data/market/index-level.ts +51 -0
  239. package/src/market-data/model-dividend-yield.ts +57 -16
  240. package/src/market-data/quotes/live-valuation.ts +48 -2
  241. package/src/market-data/realized-volatility.ts +16 -7
  242. package/src/market-data/tax-equivalent.ts +344 -0
  243. package/src/news/aggregator.ts +4 -2
  244. package/src/notifications/notification-log.ts +5 -3
  245. package/src/plugins/auto-update-node.ts +1 -0
  246. package/src/plugins/builtin/account-management/footer.ts +1 -1
  247. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  248. package/src/plugins/builtin/account-management/model.ts +1 -0
  249. package/src/plugins/builtin/account-management/pane.tsx +71 -19
  250. package/src/plugins/builtin/account-management/trial-cancel.ts +40 -0
  251. package/src/plugins/builtin/alerts/cli.ts +7 -18
  252. package/src/plugins/builtin/alerts/constants.ts +8 -0
  253. package/src/plugins/builtin/alerts/event-rows.ts +16 -0
  254. package/src/plugins/builtin/alerts/events-pane.tsx +2 -14
  255. package/src/plugins/builtin/alerts/headless.ts +182 -0
  256. package/src/plugins/builtin/alerts/index.tsx +3 -0
  257. package/src/plugins/builtin/alerts/pane.tsx +1 -7
  258. package/src/plugins/builtin/alerts/storage.ts +17 -1
  259. package/src/plugins/builtin/analytics/index.tsx +6 -1
  260. package/src/plugins/builtin/analytics/metrics.ts +47 -9
  261. package/src/plugins/builtin/analytics/risk-headless.ts +14 -2
  262. package/src/plugins/builtin/analytics/risk-math.ts +83 -0
  263. package/src/plugins/builtin/analytics/risk-model.ts +97 -4
  264. package/src/plugins/builtin/analytics/risk-pane.tsx +11 -6
  265. package/src/plugins/builtin/analytics/sector-model.ts +14 -3
  266. package/src/plugins/builtin/awards/headless.ts +6 -5
  267. package/src/plugins/builtin/awards/index.tsx +1 -1
  268. package/src/plugins/builtin/backtest/client.ts +38 -8
  269. package/src/plugins/builtin/backtest/engine.ts +25 -13
  270. package/src/plugins/builtin/backtest/export.ts +27 -0
  271. package/src/plugins/builtin/backtest/format.ts +19 -3
  272. package/src/plugins/builtin/backtest/headless.ts +42 -28
  273. package/src/plugins/builtin/backtest/index.tsx +3 -0
  274. package/src/plugins/builtin/backtest/pane.tsx +39 -10
  275. package/src/plugins/builtin/backtest/report.ts +160 -0
  276. package/src/plugins/builtin/backtest/rules.ts +2 -0
  277. package/src/plugins/builtin/backtest/window.ts +112 -0
  278. package/src/plugins/builtin/bond-calculator/headless.ts +3 -2
  279. package/src/plugins/builtin/broker-manager/add-flow.tsx +4 -4
  280. package/src/plugins/builtin/catalysts/headless.ts +24 -13
  281. package/src/plugins/builtin/catalysts/index.tsx +4 -2
  282. package/src/plugins/builtin/catalysts/model.ts +18 -1
  283. package/src/plugins/builtin/catalysts/pane.tsx +2 -2
  284. package/src/plugins/builtin/cds/client.ts +28 -5
  285. package/src/plugins/builtin/cds/headless.ts +183 -31
  286. package/src/plugins/builtin/cds/index.tsx +1 -1
  287. package/src/plugins/builtin/cds/model.ts +229 -53
  288. package/src/plugins/builtin/cds/pane.tsx +82 -26
  289. package/src/plugins/builtin/central-bank-rates/headless.ts +1 -1
  290. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +39 -1
  291. package/src/plugins/builtin/chart-composer/chart-spec-edit.ts +77 -0
  292. package/src/plugins/builtin/chart-composer/chart-spec.ts +15 -0
  293. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +22 -2
  294. package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +2 -2
  295. package/src/plugins/builtin/chart-composer/headless-schema.ts +10 -2
  296. package/src/plugins/builtin/chart-composer/headless.ts +99 -21
  297. package/src/plugins/builtin/chart-composer/index.tsx +70 -13
  298. package/src/plugins/builtin/chart-composer/pane.tsx +65 -15
  299. package/src/plugins/builtin/chart-composer/presets.ts +79 -11
  300. package/src/plugins/builtin/chart-composer/series-catalog.ts +50 -14
  301. package/src/plugins/builtin/chart-composer/series-expression.ts +9 -7
  302. package/src/plugins/builtin/chart-composer/series-listings.ts +178 -0
  303. package/src/plugins/builtin/chart-composer/session-range.ts +87 -0
  304. package/src/plugins/builtin/chat/attachments/desktop.tsx +4 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +49 -14
  306. package/src/plugins/builtin/chat/content/composer.tsx +22 -1
  307. package/src/plugins/builtin/chat/content/index.tsx +35 -5
  308. package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -0
  309. package/src/plugins/builtin/chat/content/shortcuts.ts +32 -13
  310. package/src/plugins/builtin/chat/content/snapshot.ts +29 -6
  311. package/src/plugins/builtin/chat/ghost-user.ts +11 -3
  312. package/src/plugins/builtin/chat/layout.ts +2 -0
  313. package/src/plugins/builtin/chat/message/desktop.tsx +13 -5
  314. package/src/plugins/builtin/chat/message/header.tsx +26 -4
  315. package/src/plugins/builtin/chat/message/pane-chip.tsx +131 -35
  316. package/src/plugins/builtin/chat/message/render-state.ts +28 -1
  317. package/src/plugins/builtin/chat/message/terminal.tsx +9 -3
  318. package/src/plugins/builtin/chat/pane-links/composer.ts +87 -0
  319. package/src/plugins/builtin/chat/pane-links/model.ts +1 -1
  320. package/src/plugins/builtin/chat/share/flow.tsx +9 -73
  321. package/src/plugins/builtin/cloud/askg/controller.ts +5 -3
  322. package/src/plugins/builtin/cloud/askg/executor.ts +3 -1
  323. package/src/plugins/builtin/cloud/askg/lock-note.ts +16 -0
  324. package/src/plugins/builtin/cloud/askg/pane.tsx +6 -2
  325. package/src/plugins/builtin/cloud/auth-actions.tsx +4 -2
  326. package/src/plugins/builtin/cloud/company-picker.tsx +21 -26
  327. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +5 -3
  328. package/src/plugins/builtin/cloud/plugin.tsx +2 -0
  329. package/src/plugins/builtin/cloud/team/module.tsx +5 -1
  330. package/src/plugins/builtin/cloud/team/pane.tsx +11 -4
  331. package/src/plugins/builtin/cloud/team/views.ts +11 -4
  332. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +9 -4
  333. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +3 -2
  334. package/src/plugins/builtin/cloud/thesis/detail.tsx +2 -1
  335. package/src/plugins/builtin/cloud/thesis/exposure.ts +3 -0
  336. package/src/plugins/builtin/cloud/thesis/prompts.tsx +3 -2
  337. package/src/plugins/builtin/cloud/thesis/ticker-tab.tsx +2 -1
  338. package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +2 -1
  339. package/src/plugins/builtin/cloud/verification-status-widget.tsx +2 -1
  340. package/src/plugins/builtin/commodities-energy/index.tsx +8 -5
  341. package/src/plugins/builtin/commodities-energy/view-state.ts +11 -0
  342. package/src/plugins/builtin/company-attention/headless.ts +15 -7
  343. package/src/plugins/builtin/company-attention/index.tsx +1 -1
  344. package/src/plugins/builtin/company-attention/model.ts +49 -4
  345. package/src/plugins/builtin/company-attention/pane.tsx +11 -9
  346. package/src/plugins/builtin/company-kpis/headless.ts +4 -3
  347. package/src/plugins/builtin/company-kpis/index.tsx +2 -2
  348. package/src/plugins/builtin/company-kpis/pane.tsx +9 -3
  349. package/src/plugins/builtin/congress-trades/headless.ts +23 -2
  350. package/src/plugins/builtin/correlation/relationship/pane.tsx +18 -46
  351. package/src/plugins/builtin/cot/headless.ts +5 -2
  352. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +41 -13
  353. package/src/plugins/builtin/credit-boards/client.ts +9 -2
  354. package/src/plugins/builtin/credit-boards/headless.ts +93 -27
  355. package/src/plugins/builtin/credit-boards/index.tsx +15 -4
  356. package/src/plugins/builtin/credit-boards/model.ts +105 -6
  357. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +14 -3
  358. package/src/plugins/builtin/credit-documents/detail.tsx +2 -1
  359. package/src/plugins/builtin/credit-documents/index.tsx +3 -0
  360. package/src/plugins/builtin/credit-documents/model.ts +3 -10
  361. package/src/plugins/builtin/crypto-board/client.ts +152 -2
  362. package/src/plugins/builtin/crypto-board/headless.ts +138 -19
  363. package/src/plugins/builtin/crypto-board/index.tsx +5 -3
  364. package/src/plugins/builtin/crypto-board/model.ts +210 -12
  365. package/src/plugins/builtin/crypto-board/pane.tsx +148 -9
  366. package/src/plugins/builtin/crypto-board/series.ts +52 -1
  367. package/src/plugins/builtin/crypto-board/supply.ts +123 -0
  368. package/src/plugins/builtin/debt-maturities/client.ts +54 -1
  369. package/src/plugins/builtin/debt-maturities/headless.ts +27 -3
  370. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  371. package/src/plugins/builtin/debt-maturities/model.ts +58 -13
  372. package/src/plugins/builtin/debt-maturities/pane.tsx +47 -7
  373. package/src/plugins/builtin/dividend-yield/client.ts +42 -36
  374. package/src/plugins/builtin/dividend-yield/headless.ts +113 -18
  375. package/src/plugins/builtin/dividend-yield/index.tsx +5 -2
  376. package/src/plugins/builtin/dividend-yield/pane.tsx +37 -13
  377. package/src/plugins/builtin/dividend-yield/provider-client.ts +7 -3
  378. package/src/plugins/builtin/dividend-yield/ranking.ts +187 -0
  379. package/src/plugins/builtin/dividend-yield/reference-price.ts +28 -5
  380. package/src/plugins/builtin/dividend-yield/types.ts +6 -1
  381. package/src/plugins/builtin/dividend-yield/view.ts +1 -1
  382. package/src/plugins/builtin/docs/blocks.tsx +54 -8
  383. package/src/plugins/builtin/docs/pane.tsx +8 -13
  384. package/src/plugins/builtin/earnings/headless.ts +3 -2
  385. package/src/plugins/builtin/earnings-calls/data.ts +51 -0
  386. package/src/plugins/builtin/earnings-calls/headless.ts +7 -0
  387. package/src/plugins/builtin/earnings-calls/index.tsx +1 -0
  388. package/src/plugins/builtin/earnings-calls/model.ts +97 -0
  389. package/src/plugins/builtin/earnings-calls/pane.tsx +107 -7
  390. package/src/plugins/builtin/earnings-calls/transcript-view.tsx +140 -22
  391. package/src/plugins/builtin/earnings-calls/use-call-playback.ts +194 -0
  392. package/src/plugins/builtin/econ/calendar-model.ts +22 -0
  393. package/src/plugins/builtin/econ/calendar-source.ts +35 -0
  394. package/src/plugins/builtin/econ/index.tsx +40 -8
  395. package/src/plugins/builtin/econ-statistics/defs.ts +7 -0
  396. package/src/plugins/builtin/econ-statistics/detail.tsx +8 -1
  397. package/src/plugins/builtin/econ-statistics/headless.ts +26 -5
  398. package/src/plugins/builtin/econ-statistics/pane.tsx +4 -2
  399. package/src/plugins/builtin/econ-statistics/stats.ts +10 -0
  400. package/src/plugins/builtin/econ-statistics/view.ts +19 -0
  401. package/src/plugins/builtin/equity-screener/client.ts +1 -1
  402. package/src/plugins/builtin/equity-screener/model.ts +46 -4
  403. package/src/plugins/builtin/equity-screener/pane.tsx +3 -0
  404. package/src/plugins/builtin/estimate-revisions/client.ts +32 -22
  405. package/src/plugins/builtin/estimate-revisions/headless.ts +1 -0
  406. package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
  407. package/src/plugins/builtin/estimate-revisions/pane.tsx +5 -3
  408. package/src/plugins/builtin/executives/index.tsx +1 -0
  409. package/src/plugins/builtin/exposure/editor.tsx +3 -3
  410. package/src/plugins/builtin/fear-greed/index.tsx +9 -0
  411. package/src/plugins/builtin/filing-events/index.tsx +1 -0
  412. package/src/plugins/builtin/futures/index.tsx +2 -2
  413. package/src/plugins/builtin/futures/model.ts +34 -21
  414. package/src/plugins/builtin/futures/table.tsx +1 -1
  415. package/src/plugins/builtin/futures/use-board-terms.ts +2 -2
  416. package/src/plugins/builtin/futures-curve/headless.ts +4 -2
  417. package/src/plugins/builtin/futures-curve/model.ts +5 -7
  418. package/src/plugins/builtin/help/index.tsx +55 -8
  419. package/src/plugins/builtin/help/shortcut-table.tsx +15 -2
  420. package/src/plugins/builtin/holders/headless.ts +12 -0
  421. package/src/plugins/builtin/insider/headless.ts +311 -41
  422. package/src/plugins/builtin/insider/index.tsx +280 -106
  423. package/src/plugins/builtin/insider/insiders.tsx +224 -0
  424. package/src/plugins/builtin/insider/signals-cells.tsx +52 -0
  425. package/src/plugins/builtin/insider/signals-client.ts +135 -11
  426. package/src/plugins/builtin/insider/signals-model.ts +628 -56
  427. package/src/plugins/builtin/insider/signals.tsx +283 -83
  428. package/src/plugins/builtin/ipo-calendar/headless.ts +17 -7
  429. package/src/plugins/builtin/ipo-calendar/index.tsx +23 -3
  430. package/src/plugins/builtin/ipo-calendar/model.ts +84 -36
  431. package/src/plugins/builtin/ipo-calendar/pane.tsx +20 -8
  432. package/src/plugins/builtin/iv-history/headless.ts +2 -0
  433. package/src/plugins/builtin/jobs/headless.ts +1 -0
  434. package/src/plugins/builtin/jobs/index.tsx +1 -0
  435. package/src/plugins/builtin/jodi/headless.ts +2 -0
  436. package/src/plugins/builtin/kelly-sizer/pane.tsx +1 -1
  437. package/src/plugins/builtin/kelly-sizer/portfolio.ts +1 -1
  438. package/src/plugins/builtin/market-heatmap/headless.ts +1 -0
  439. package/src/plugins/builtin/market-heatmap/portfolio.ts +3 -1
  440. package/src/plugins/builtin/market-valuation/pane.tsx +1 -1
  441. package/src/plugins/builtin/market-valuation/zone-scale/desktop.tsx +31 -57
  442. package/src/plugins/builtin/mna/distress/headless.ts +2 -1
  443. package/src/plugins/builtin/mna/headless.ts +14 -2
  444. package/src/plugins/builtin/mna/index.tsx +1 -0
  445. package/src/plugins/builtin/news/headless.ts +4 -0
  446. package/src/plugins/builtin/news/wire/news/footer.ts +5 -3
  447. package/src/plugins/builtin/news/wire/news/table.tsx +57 -11
  448. package/src/plugins/builtin/notes/cli.ts +8 -4
  449. package/src/plugins/builtin/notes/files.ts +66 -20
  450. package/src/plugins/builtin/notes/migration.ts +18 -6
  451. package/src/plugins/builtin/notes/owner.tsx +3 -2
  452. package/src/plugins/builtin/notes/quick-notes-pane.tsx +3 -2
  453. package/src/plugins/builtin/options-scenario/client.ts +7 -4
  454. package/src/plugins/builtin/options-scenario/headless.ts +5 -3
  455. package/src/plugins/builtin/pe-band/index.tsx +1 -1
  456. package/src/plugins/builtin/pe-band/model.ts +1 -15
  457. package/src/plugins/builtin/perps/headless.ts +30 -13
  458. package/src/plugins/builtin/perps/model.ts +45 -3
  459. package/src/plugins/builtin/perps/pane.tsx +7 -7
  460. package/src/plugins/builtin/portfolio-list/cell-version.ts +10 -4
  461. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +128 -14
  462. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +108 -46
  463. package/src/plugins/builtin/portfolio-list/cli/render.ts +368 -45
  464. package/src/plugins/builtin/portfolio-list/cli/shared.ts +8 -2
  465. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +24 -34
  466. package/src/plugins/builtin/portfolio-list/grid.tsx +3 -1
  467. package/src/plugins/builtin/portfolio-list/headless.ts +151 -29
  468. package/src/plugins/builtin/portfolio-list/income.ts +296 -0
  469. package/src/plugins/builtin/portfolio-list/metrics.ts +2 -2
  470. package/src/plugins/builtin/portfolio-list/pane/futures-terms.ts +58 -0
  471. package/src/plugins/builtin/portfolio-list/pane/index.tsx +27 -10
  472. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +47 -28
  473. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +3 -2
  474. package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +10 -3
  475. package/src/plugins/builtin/portfolio-list/summary/index.tsx +26 -4
  476. package/src/plugins/builtin/portfolio-list/summary/totals.ts +31 -3
  477. package/src/plugins/builtin/portfolio-list/table.tsx +25 -5
  478. package/src/plugins/builtin/power/prices-headless.ts +2 -1
  479. package/src/plugins/builtin/realized-vol/chart-model.ts +29 -5
  480. package/src/plugins/builtin/realized-vol/charts.tsx +14 -8
  481. package/src/plugins/builtin/realized-vol/evidence.ts +2 -0
  482. package/src/plugins/builtin/realized-vol/headless.ts +6 -4
  483. package/src/plugins/builtin/realized-vol/model.ts +5 -1
  484. package/src/plugins/builtin/realized-vol/pane.tsx +31 -11
  485. package/src/plugins/builtin/realized-vol/settings.ts +1 -1
  486. package/src/plugins/builtin/research/analyst-headless.ts +4 -0
  487. package/src/plugins/builtin/research/corporate-actions-pane.tsx +2 -0
  488. package/src/plugins/builtin/research/event-model.ts +22 -2
  489. package/src/plugins/builtin/research/headless-schema.ts +1 -0
  490. package/src/plugins/builtin/research/headless.ts +3 -0
  491. package/src/plugins/builtin/research/index.tsx +3 -0
  492. package/src/plugins/builtin/research/relative-valuation-columns.ts +27 -5
  493. package/src/plugins/builtin/research/relative-valuation-headless.ts +2 -0
  494. package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
  495. package/src/plugins/builtin/reverse-dcf/headless.ts +9 -6
  496. package/src/plugins/builtin/reverse-dcf/index.tsx +2 -2
  497. package/src/plugins/builtin/reverse-dcf/model.ts +51 -4
  498. package/src/plugins/builtin/reverse-dcf/pane.tsx +23 -10
  499. package/src/plugins/builtin/risk-factors/headless.ts +7 -0
  500. package/src/plugins/builtin/risk-factors/index.tsx +1 -0
  501. package/src/plugins/builtin/scanner/feed.ts +5 -3
  502. package/src/plugins/builtin/scanner/headless.ts +9 -57
  503. package/src/plugins/builtin/scanner/index.ts +1 -2
  504. package/src/plugins/builtin/sec/forms.ts +2 -6
  505. package/src/plugins/builtin/sec/fund-facts-view.tsx +53 -0
  506. package/src/plugins/builtin/sec/fund-facts.ts +328 -0
  507. package/src/plugins/builtin/sec/headless.ts +140 -44
  508. package/src/plugins/builtin/sec/index.tsx +95 -30
  509. package/src/plugins/builtin/sec/model.ts +2 -44
  510. package/src/plugins/builtin/shared/headless-options.ts +10 -0
  511. package/src/plugins/builtin/shared/locked-rows.tsx +3 -1
  512. package/src/plugins/builtin/shared/move-rank.ts +108 -0
  513. package/src/plugins/builtin/shared/report-freshness.ts +25 -9
  514. package/src/plugins/builtin/shared/scanner-capture.ts +95 -0
  515. package/src/plugins/builtin/shared/treasury-cutoffs.ts +15 -0
  516. package/src/plugins/builtin/shared/use-quote-board.ts +1 -0
  517. package/src/plugins/builtin/shared/volatility/live-session.ts +34 -0
  518. package/src/plugins/builtin/shared/volatility-indices.ts +32 -0
  519. package/src/plugins/builtin/short-interest/headless.ts +3 -0
  520. package/src/plugins/builtin/short-interest/watch-model.ts +2 -2
  521. package/src/plugins/builtin/social-mentions/client.ts +8 -1
  522. package/src/plugins/builtin/social-mentions/pane.tsx +8 -6
  523. package/src/plugins/builtin/supply-chain/client.ts +12 -3
  524. package/src/plugins/builtin/supply-chain/disclosure-quote.tsx +9 -5
  525. package/src/plugins/builtin/supply-chain/evidence.ts +3 -1
  526. package/src/plugins/builtin/supply-chain/flow-layout.ts +2 -1
  527. package/src/plugins/builtin/supply-chain/flow.tsx +23 -16
  528. package/src/plugins/builtin/supply-chain/graph-client.ts +8 -5
  529. package/src/plugins/builtin/supply-chain/graph-evidence.ts +1 -1
  530. package/src/plugins/builtin/supply-chain/graph-model.ts +10 -2
  531. package/src/plugins/builtin/supply-chain/graph-pane.tsx +9 -7
  532. package/src/plugins/builtin/supply-chain/graph.tsx +8 -6
  533. package/src/plugins/builtin/supply-chain/headless.ts +69 -27
  534. package/src/plugins/builtin/supply-chain/index.tsx +1 -1
  535. package/src/plugins/builtin/supply-chain/model.ts +76 -15
  536. package/src/plugins/builtin/supply-chain/pane.tsx +29 -15
  537. package/src/plugins/builtin/supply-chain/row-evidence.tsx +5 -4
  538. package/src/plugins/builtin/themes/model.ts +2 -5
  539. package/src/plugins/builtin/thirteenf/api.ts +50 -2
  540. package/src/plugins/builtin/thirteenf/data.ts +250 -11
  541. package/src/plugins/builtin/thirteenf/headless.ts +311 -28
  542. package/src/plugins/builtin/thirteenf/index.tsx +4 -1
  543. package/src/plugins/builtin/thirteenf/model.ts +244 -19
  544. package/src/plugins/builtin/thirteenf/overlap-pane.tsx +133 -33
  545. package/src/plugins/builtin/thirteenf/overlap.ts +1 -1
  546. package/src/plugins/builtin/thirteenf/pane.tsx +24 -5
  547. package/src/plugins/builtin/thirteenf/report-notes.ts +78 -0
  548. package/src/plugins/builtin/thirteenf/types.ts +49 -0
  549. package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +22 -8
  550. package/src/plugins/builtin/ticker-detail/data-panes/history-bars.ts +17 -1
  551. package/src/plugins/builtin/ticker-detail/financials/model.ts +2 -42
  552. package/src/plugins/builtin/ticker-detail/financials/tab.tsx +1 -1
  553. package/src/plugins/builtin/ticker-detail/headless.ts +23 -10
  554. package/src/plugins/builtin/ticker-detail/overview/components.tsx +27 -3
  555. package/src/plugins/builtin/ticker-detail/overview/dividend.ts +60 -0
  556. package/src/plugins/builtin/ticker-detail/overview/model.ts +46 -9
  557. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +3 -0
  558. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +36 -3
  559. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +18 -19
  560. package/src/plugins/builtin/time-sales/client.ts +7 -4
  561. package/src/plugins/builtin/time-sales/headless.ts +71 -22
  562. package/src/plugins/builtin/time-sales/model.ts +12 -0
  563. package/src/plugins/builtin/time-sales/pane.tsx +31 -7
  564. package/src/plugins/builtin/time-sales/window.ts +128 -0
  565. package/src/plugins/builtin/trace-bonds/client.ts +351 -33
  566. package/src/plugins/builtin/trace-bonds/headless.ts +60 -22
  567. package/src/plugins/builtin/trace-bonds/index.tsx +4 -2
  568. package/src/plugins/builtin/trace-bonds/model.ts +27 -25
  569. package/src/plugins/builtin/trace-bonds/pane.tsx +63 -45
  570. package/src/plugins/builtin/treasury-auctions/cache.ts +61 -15
  571. package/src/plugins/builtin/treasury-auctions/client.ts +45 -10
  572. package/src/plugins/builtin/treasury-auctions/headless.ts +35 -13
  573. package/src/plugins/builtin/treasury-auctions/index.tsx +5 -2
  574. package/src/plugins/builtin/treasury-auctions/model.ts +20 -16
  575. package/src/plugins/builtin/treasury-auctions/pane.tsx +29 -12
  576. package/src/plugins/builtin/vol-surface/charts.tsx +2 -1
  577. package/src/plugins/builtin/vol-surface/headless.ts +3 -2
  578. package/src/plugins/builtin/vol-surface/pane.tsx +2 -1
  579. package/src/plugins/builtin/vol-surface/stored.ts +4 -7
  580. package/src/plugins/builtin/volatility/chart-model.ts +16 -15
  581. package/src/plugins/builtin/volatility/charts.tsx +5 -5
  582. package/src/plugins/builtin/volatility/client.ts +73 -2
  583. package/src/plugins/builtin/volatility/evidence.ts +13 -14
  584. package/src/plugins/builtin/volatility/headless.ts +13 -7
  585. package/src/plugins/builtin/volatility/index.tsx +1 -1
  586. package/src/plugins/builtin/volatility/model.ts +104 -38
  587. package/src/plugins/builtin/volatility/pane.tsx +42 -24
  588. package/src/plugins/builtin/volatility/series.ts +22 -13
  589. package/src/plugins/builtin/world-venue-map/geo-series.ts +9 -0
  590. package/src/plugins/builtin/world-venue-map/headless.ts +8 -5
  591. package/src/plugins/builtin/world-venue-map/index.ts +16 -2
  592. package/src/plugins/builtin/world-venue-map/map.tsx +13 -17
  593. package/src/plugins/builtin/yield-curve/curves.ts +29 -5
  594. package/src/plugins/builtin/yield-curve/headless.ts +41 -8
  595. package/src/plugins/builtin/yield-curve/history.ts +5 -5
  596. package/src/plugins/builtin/yield-curve/index.tsx +30 -13
  597. package/src/plugins/compat.ts +3 -1
  598. package/src/plugins/dependencies.ts +8 -2
  599. package/src/plugins/host-link.ts +12 -5
  600. package/src/plugins/installer.ts +16 -7
  601. package/src/plugins/loader.ts +9 -2
  602. package/src/plugins/marketplace/activation.ts +10 -4
  603. package/src/plugins/registry/host-actions.ts +3 -0
  604. package/src/plugins/registry/index.ts +3 -1
  605. package/src/{plugins/builtin/portfolio-list → portfolio}/allocation.ts +74 -12
  606. package/src/{plugins/builtin/portfolio-list → portfolio}/column-values.ts +140 -53
  607. package/src/portfolio/futures-positions.ts +213 -0
  608. package/src/portfolio/futures-terms.ts +75 -0
  609. package/src/portfolio/manual-lots.ts +78 -0
  610. package/src/portfolio/mutations.ts +54 -10
  611. package/src/portfolio/position-metrics.ts +44 -10
  612. package/src/portfolio/valuation-basis.ts +31 -4
  613. package/src/public/__snapshots__/public-api.test.ts.snap +4 -0
  614. package/src/public/time-series.ts +2 -1
  615. package/src/remote/confirm-change.tsx +2 -1
  616. package/src/remote/server.ts +1 -1
  617. package/src/remote/watchlist.ts +9 -1
  618. package/src/renderers/dom/data-table/row.tsx +1 -1
  619. package/src/renderers/dom/desktop/audio-player.tsx +312 -0
  620. package/src/renderers/dom/desktop/control-styles.ts +17 -82
  621. package/src/renderers/dom/desktop/controls.tsx +39 -63
  622. package/src/renderers/dom/desktop/dialog-actions.tsx +13 -53
  623. package/src/renderers/dom/desktop/icons.tsx +8 -0
  624. package/src/renderers/dom/desktop/list-view.tsx +6 -6
  625. package/src/renderers/dom/desktop/popover.tsx +0 -3
  626. package/src/renderers/dom/desktop/query-bar.tsx +6 -4
  627. package/src/renderers/dom/desktop/select-field.tsx +9 -8
  628. package/src/renderers/dom/desktop/stack-header.ts +3 -0
  629. package/src/renderers/dom/dom-ui-host.tsx +3 -2
  630. package/src/renderers/dom/host/chart-surface.tsx +3 -3
  631. package/src/renderers/dom/host/size-observer.ts +33 -4
  632. package/src/renderers/dom/host/surface-3d.tsx +3 -2
  633. package/src/renderers/dom/host/surface-fit.ts +4 -1
  634. package/src/renderers/dom/host/tabs.tsx +22 -132
  635. package/src/renderers/dom/styles.css +358 -160
  636. package/src/renderers/electrobun/bun/core-capabilities.ts +1 -1
  637. package/src/renderers/electrobun/bun/desktop/backend.ts +1 -1
  638. package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
  639. package/src/renderers/electrobun/bun/desktop/state-broadcaster.ts +43 -1
  640. package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +5 -1
  641. package/src/renderers/electrobun/shared/rpc-codec.ts +7 -0
  642. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +21 -17
  643. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +3 -3
  644. package/src/renderers/electrobun/view/desktop/window/bridge.ts +6 -8
  645. package/src/renderers/electrobun/view/desktop/window/snapshot.ts +18 -0
  646. package/src/series/capability.ts +1 -0
  647. package/src/series/files.ts +9 -3
  648. package/src/series/registry.ts +40 -14
  649. package/src/series/resolve.ts +121 -18
  650. package/src/series/standalone.ts +3 -2
  651. package/src/series/types.ts +55 -1
  652. package/src/series/validate.ts +39 -0
  653. package/src/shares/api.ts +26 -7
  654. package/src/shares/bug-report-dialog.tsx +2 -2
  655. package/src/shares/bug-report-flow.tsx +4 -7
  656. package/src/shares/capture-flow.ts +5 -4
  657. package/src/shares/capture-preview.tsx +2 -2
  658. package/src/shares/chat.ts +7 -27
  659. package/src/shares/flow.tsx +86 -40
  660. package/src/shares/location.ts +1 -3
  661. package/src/shares/pane-image.ts +11 -9
  662. package/src/shares/pane.ts +5 -2
  663. package/src/shares/payload.ts +1 -1
  664. package/src/shares/personal-pane.ts +3 -3
  665. package/src/shares/portable-layout.ts +9 -2
  666. package/src/shares/ready.ts +42 -0
  667. package/src/shares/test-harness.ts +62 -0
  668. package/src/sources/gloomberb-cloud/batched-lookups.ts +73 -0
  669. package/src/sources/gloomberb-cloud/index.ts +64 -12
  670. package/src/sources/gloomberb-cloud/normalizers.ts +31 -2
  671. package/src/sources/gloomberb-cloud/perpetuals.ts +20 -1
  672. package/src/sources/history-omitted.ts +34 -0
  673. package/src/sources/history-result.ts +3 -0
  674. package/src/sources/history-retention.ts +1 -1
  675. package/src/sources/provider-errors.ts +43 -1
  676. package/src/sources/provider-router/batches.ts +3 -2
  677. package/src/sources/provider-router/cache.ts +2 -1
  678. package/src/sources/provider-router/cached-routes.ts +9 -3
  679. package/src/sources/provider-router/history.ts +9 -8
  680. package/src/sources/provider-router/index.ts +18 -3
  681. package/src/sources/provider-router/primary.ts +5 -4
  682. package/src/sources/provider-router/quote-route.ts +3 -1
  683. package/src/sources/provider-router/routing.ts +2 -1
  684. package/src/sources/provider-router/search.ts +47 -13
  685. package/src/sources/provider-router/streaming.ts +7 -4
  686. package/src/sources/sec-edgar.ts +1 -3
  687. package/src/state/app/context/index.tsx +9 -13
  688. package/src/state/app/tab-cursor.ts +149 -12
  689. package/src/state/hooks/quote-streaming.ts +3 -2
  690. package/src/state/hooks/session-snapshot.ts +3 -2
  691. package/src/state/persist-scheduler.ts +12 -4
  692. package/src/sync/controller.ts +22 -1
  693. package/src/sync/core-contributors.ts +58 -15
  694. package/src/team/collections-sync.ts +14 -4
  695. package/src/team/collections.ts +40 -11
  696. package/src/team/store.ts +5 -4
  697. package/src/telemetry/attention-counts.ts +8 -2
  698. package/src/telemetry/crash-reports-dom.ts +3 -0
  699. package/src/telemetry/crash-reports-node.ts +7 -4
  700. package/src/telemetry/crash-reports.ts +11 -11
  701. package/src/telemetry/usage-counts.ts +16 -12
  702. package/src/theme/colors.ts +2 -0
  703. package/src/theme/font-scale.ts +2 -0
  704. package/src/theme/ui-tokens.ts +71 -0
  705. package/src/tickers/batched-lookups.ts +186 -0
  706. package/src/tickers/company-name-listing.ts +97 -0
  707. package/src/tickers/company-name.ts +13 -0
  708. package/src/tickers/instrument-coverage.ts +112 -0
  709. package/src/tickers/listing-fate.ts +49 -9
  710. package/src/tickers/listing-venues.ts +24 -5
  711. package/src/tickers/open-target.ts +13 -5
  712. package/src/tickers/search/index.ts +112 -35
  713. package/src/tickers/search/ranking.ts +49 -1
  714. package/src/tickers/terminal-codes.ts +79 -0
  715. package/src/tickers/ticker-changes.ts +74 -3
  716. package/src/tickers/us-listing.ts +2 -1
  717. package/src/time-series/chart-data.ts +79 -8
  718. package/src/time-series/fundamentals.ts +55 -7
  719. package/src/time-series/ice-credit.ts +17 -2
  720. package/src/time-series/live-bars.ts +21 -8
  721. package/src/time-series/live-quotes.ts +2 -3
  722. package/src/time-series/price-comparison.ts +6 -1
  723. package/src/time-series/resolve.ts +65 -10
  724. package/src/time-series/spec.ts +2 -1
  725. package/src/time-series/studies.ts +3 -3
  726. package/src/time-series/types.ts +22 -0
  727. package/src/time-series/use-chart-resolution.ts +2 -1
  728. package/src/types/config.ts +7 -0
  729. package/src/types/data-provider.ts +20 -0
  730. package/src/types/headless.ts +142 -1
  731. package/src/types/instrument.ts +6 -0
  732. package/src/types/plugin.ts +32 -9
  733. package/src/types/price-history.ts +5 -0
  734. package/src/types/ticker-changes.ts +19 -0
  735. package/src/types/ticker.ts +10 -2
  736. package/src/ui/context-menu.tsx +2 -0
  737. package/src/ui/host.tsx +40 -4
  738. package/src/ui/measured-cells.ts +13 -7
  739. package/src/ui/qr.ts +7 -5
  740. package/src/updater/index.ts +5 -5
  741. package/src/utils/calendar-date.ts +86 -27
  742. package/src/utils/currency-units.ts +17 -0
  743. package/src/utils/debug-log.ts +1 -1
  744. package/src/utils/dividend-cash.ts +48 -0
  745. package/src/utils/dom-screenshot-rasters.ts +3 -1
  746. package/src/utils/dom-screenshot.ts +14 -10
  747. package/src/utils/exchange-rate-snapshot.ts +9 -4
  748. package/src/utils/external-url.ts +1 -0
  749. package/src/utils/fiscal-period.ts +47 -0
  750. package/src/utils/format.ts +5 -2
  751. package/src/utils/forward-dividend.ts +160 -11
  752. package/src/utils/futures-generic.ts +34 -8
  753. package/src/utils/http-proxy-response.ts +2 -1
  754. package/src/utils/local-utc-offset.ts +2 -0
  755. package/src/utils/log-failure.ts +31 -0
  756. package/src/utils/option-expiry.ts +12 -12
  757. package/src/utils/price-history-integrity.ts +56 -0
  758. package/src/utils/price-history.ts +13 -1
  759. package/src/utils/sec-filings.ts +245 -0
  760. package/src/utils/selection-clipboard.ts +5 -2
  761. package/src/utils/throttled-fetch.ts +1 -0
  762. package/src/{plugins/builtin/dividend-yield/trailing-cash.ts → utils/trailing-dividend.ts} +55 -8
  763. package/src/utils/url.ts +1 -0
  764. package/src/utils/utc-time.ts +11 -0
  765. package/src/plugins/builtin/chat/share/targets.ts +0 -27
  766. package/src/renderers/dom/host/top-surface.ts +0 -119
  767. package/src/shares/dialog.tsx +0 -221
  768. package/src/shares/live.ts +0 -19
@@ -1,9 +1,20 @@
1
+ import type { PaneTemplateCreateOptions, PaneTemplateInstanceConfig } from "../../../types/plugin";
1
2
  import type { PluginModule } from "../plugin-module";
2
3
  import { fixedIncomeShortcut } from "../fixed-income/shortcut";
3
4
  import { cdxBoardCache, sovrBoardCache } from "./client";
4
5
  import { cdxHeadless, sovrHeadless } from "./headless";
5
6
  import { CREDIT_BOARD_SERIES } from "./series";
6
7
 
8
+ /**
9
+ * What `CDX HY` or `SOVR Brazil` asks the board to open on. Always named, empty for the bare command, so a
10
+ * pane the command reuses is not asked again for what an earlier command named.
11
+ */
12
+ function openingOn(param: string) {
13
+ return (_context: unknown, options?: PaneTemplateCreateOptions): PaneTemplateInstanceConfig => (
14
+ { placement: "floating", params: { [param]: options?.arg?.trim() ?? "" } }
15
+ );
16
+ }
17
+
7
18
  export const creditBoardsModule: PluginModule = {
8
19
  series: CREDIT_BOARD_SERIES,
9
20
  paneTemplates: [
@@ -14,9 +25,9 @@ export const creditBoardsModule: PluginModule = {
14
25
  label: "Index CDS",
15
26
  description: "CDX IG, HY, EM, iTraxx Main and Crossover on the run from DTCC public dissemination: level, 1D and 1W moves, 1Y rank. Sovereign CDS is the other tab.",
16
27
  keywords: ["cdx", "itraxx", "crossover", "xover", "index", "cds", "credit", "ig", "hy", "em", "spread", "dtcc"],
17
- shortcut: { prefix: "CDX" },
28
+ shortcut: { prefix: "CDX", argKind: "text", argOptional: true, argPlaceholder: "index" },
18
29
  headless: cdxHeadless,
19
- createInstance: () => ({ placement: "floating" }),
30
+ createInstance: openingOn("index"),
20
31
  }, "credit", "index"),
21
32
  },
22
33
  {
@@ -26,9 +37,9 @@ export const creditBoardsModule: PluginModule = {
26
37
  label: "Sovereign CDS",
27
38
  description: "The CDS pane on Sovereign: 5Y CDS from DTCC public dissemination, ranked by the month's move, beside each local currency's month.",
28
39
  keywords: ["sovr", "wcds", "sovereign", "country", "cds", "credit", "em", "emerging", "spread", "dtcc"],
29
- shortcut: { prefix: "SOVR", aliases: ["WCDS"] },
40
+ shortcut: { prefix: "SOVR", aliases: ["WCDS"], argKind: "text", argOptional: true, argPlaceholder: "country" },
30
41
  headless: sovrHeadless,
31
- createInstance: () => ({ placement: "floating" }),
42
+ createInstance: openingOn("country"),
32
43
  }, "credit", "sovereign"),
33
44
  },
34
45
  ],
@@ -26,6 +26,83 @@ export function quoteUnits(quote: CreditIndexQuote): { level: "bp" | "price"; mo
26
26
  return quote === "spread" ? { level: "bp", move: "bp" } : { level: "price", move: "pts" };
27
27
  }
28
28
 
29
+ /** Today's trade date in New York, the date DTCC's index prints are dated by. */
30
+ const NEW_YORK_DATE = new Intl.DateTimeFormat("en-CA", { timeZone: "America/New_York", year: "numeric", month: "2-digit", day: "2-digit" });
31
+
32
+ function newYorkTradeDate(now: number): string {
33
+ return NEW_YORK_DATE.format(new Date(now));
34
+ }
35
+
36
+ function addDays(date: string, days: number): string {
37
+ return new Date(Date.parse(`${date}T00:00:00Z`) + days * 86_400_000).toISOString().slice(0, 10);
38
+ }
39
+
40
+ /** Where an index's latest day stands, and its moves between complete days. */
41
+ export interface CdxDay {
42
+ /** The latest day is today's New York trade date, still trading: its level and prints are so far. */
43
+ partial: boolean;
44
+ /** When the latest day's last print was executed, ISO UTC, when the server says. */
45
+ lastPrintAt: string | null;
46
+ /** The last complete day, which the moves run to. */
47
+ changeDate: string | null;
48
+ change1D: number | null;
49
+ change1W: number | null;
50
+ change1M: number | null;
51
+ }
52
+
53
+ /**
54
+ * An index's latest day and the moves the board shows: always between
55
+ * complete days, so a morning's few prints never make a 1D. A server that
56
+ * says (`partial`) has already measured them that way, across a roll on one
57
+ * contract. An older one dates them from the latest day; when that day is
58
+ * today's New York trade date or later (Asia's prints) the moves are measured
59
+ * again here from the complete days before it, on the same contract only
60
+ * (none across a roll).
61
+ */
62
+ export function cdxDay(index: CdxBoardIndex, now = Date.now()): CdxDay {
63
+ const served = { change1D: index.change1D, change1W: index.change1W, change1M: index.change1M ?? null };
64
+ if (typeof index.partial === "boolean") {
65
+ return {
66
+ partial: index.partial, lastPrintAt: index.lastPrintAt ?? null,
67
+ changeDate: index.changeDate !== undefined ? index.changeDate : index.partial ? null : index.date, ...served,
68
+ };
69
+ }
70
+ // Asia-session prints are dated the next local day, so from about 00:00 to 04:00 UTC (and from
71
+ // Sunday evening in New York) the latest day can be New York's tomorrow: still trading too.
72
+ if (!index.date || index.date < newYorkTradeDate(now)) return { partial: false, lastPrintAt: null, changeDate: index.date, ...served };
73
+ const complete = index.points.filter((point) => point.date < index.date!);
74
+ const anchor = complete.at(-1) ?? null;
75
+ const move = (base: string, maxLagDays: number): number | null => {
76
+ const baseline = complete.findLast((point) => point.date <= base);
77
+ if (!anchor || !baseline || baseline.maturity !== anchor.maturity || daysBetween(baseline.date, base) > maxLagDays) return null;
78
+ return Math.round((anchor.level - baseline.level) * 1e6) / 1e6;
79
+ };
80
+ return {
81
+ partial: true,
82
+ lastPrintAt: null,
83
+ changeDate: anchor?.date ?? null,
84
+ change1D: anchor ? move(addDays(anchor.date, -1), 5) : null,
85
+ change1W: anchor ? move(addDays(anchor.date, -7), 5) : null,
86
+ change1M: anchor ? move(monthBefore(anchor.date), 7) : null,
87
+ };
88
+ }
89
+
90
+ /** `08:09`: a print's time of day in UTC. */
91
+ function utcClock(instant: string): string | null {
92
+ const time = Date.parse(instant);
93
+ return Number.isFinite(time) ? new Date(time).toISOString().slice(11, 16) : null;
94
+ }
95
+
96
+ /**
97
+ * What a day still trading rests on: `so far, 38 prints, last 08:09 UTC`.
98
+ * The print time is left out when the server does not say it.
99
+ */
100
+ export function partialDayText(prints: number | null, lastPrintAt: string | null): string {
101
+ const clock = lastPrintAt ? utcClock(lastPrintAt) : null;
102
+ return ["so far", ...(prints == null ? [] : [`${prints} ${prints === 1 ? "print" : "prints"}`]),
103
+ ...(clock ? [`last ${clock} UTC`] : [])].join(", ");
104
+ }
105
+
29
106
  /** Spreads in bp with a decimal; prices as quoted, to the cent. */
30
107
  export function formatLevel(quote: CreditIndexQuote, value: number | null): string {
31
108
  if (value == null || !Number.isFinite(value)) return "--";
@@ -93,33 +170,55 @@ export function formatContract(maturity: string | null): string {
93
170
  : date.toLocaleDateString("en-US", { month: "short", year: "numeric", timeZone: "UTC" });
94
171
  }
95
172
 
173
+ const boardKey = (text: string) => text.toLowerCase().replace(/[^a-z0-9]/g, "");
174
+
175
+ /**
176
+ * `IG`, `cdx hy`, `itraxx main`, `crossover`: an index by its code, its name or the name's last word. `fn CDX`
177
+ * and the board's own selection (`CDX HY` opens on it) read the argument through this.
178
+ */
179
+ export function findIndex<T extends { id: string; name: string }>(indexes: readonly T[], query: string): T | null {
180
+ const wanted = boardKey(query) === "crossover" ? "xover" : boardKey(query);
181
+ return indexes.find((index) => [index.id, index.name, index.name.split(" ").at(-1) ?? ""]
182
+ .some((name) => boardKey(name) === wanted)) ?? null;
183
+ }
184
+
185
+ /** `Brazil`, `br`, `ivory coast`: a sovereign by its name or its country code, in any case. */
186
+ export function findSovereign<T extends { id: string; name: string }>(sovereigns: readonly T[], query: string): T | null {
187
+ const wanted = boardKey(query);
188
+ return wanted ? sovereigns.find((sovereign) => [sovereign.id, sovereign.name].some((name) => boardKey(name) === wanted)) ?? null : null;
189
+ }
190
+
96
191
  export interface CdxRow extends MarketBoardRow {
97
192
  index: CdxBoardIndex;
98
193
  year: YearStatistics;
194
+ /** The latest day's standing and the moves between complete days. */
195
+ day: CdxDay;
99
196
  /** The 1W and 1M moves as shown. */
100
197
  week: number | null;
101
198
  month: number | null;
102
199
  }
103
200
 
104
- export function cdxRows(indexes: readonly CdxBoardIndex[], asOf: string | null): CdxRow[] {
201
+ export function cdxRows(indexes: readonly CdxBoardIndex[], asOf: string | null, now = Date.now()): CdxRow[] {
105
202
  return indexes.map((index) => {
106
203
  const year = yearStatistics(index.points, index.level, index.date);
204
+ const day = cdxDay(index, now);
107
205
  return {
108
206
  id: index.id,
109
207
  label: index.name,
110
208
  value: index.level,
111
209
  valueText: formatLevel(index.quote, index.level),
112
- change: shown(index.quote, index.change1D),
113
- changeText: formatMove(index.quote, index.change1D),
210
+ change: shown(index.quote, day.change1D),
211
+ changeText: formatMove(index.quote, day.change1D),
114
212
  percentile: year.percentile,
115
213
  asOf: index.date,
116
214
  history: pointHistory(index.points),
117
- status: index.level == null ? "unavailable" : stale(index.date, asOf) ? "stale" : "available",
215
+ status: index.level == null ? "unavailable" : stale(index.date, asOf) ? "stale" : day.partial ? "partial" : "available",
118
216
  adverseMove: adverseMove(index.quote),
119
217
  index,
120
218
  year,
121
- week: shown(index.quote, index.change1W),
122
- month: shown(index.quote, index.change1M ?? null),
219
+ day,
220
+ week: shown(index.quote, day.change1W),
221
+ month: shown(index.quote, day.change1M),
123
222
  };
124
223
  });
125
224
  }
@@ -21,8 +21,11 @@ import type { PaneProps } from "../../../types/plugin";
21
21
  import { formatPercentileRank } from "../../../utils/format";
22
22
  import { useAssetData, usePluginPaneState } from "../../runtime";
23
23
  import { formatAsOf } from "../cds/model";
24
+ import { FIXED_INCOME_PANE_ID } from "../fixed-income/model";
25
+ import { useCommandValue } from "../shared/command-tab";
24
26
  import { getCachedSovrBoard, loadCurrencyMoves, loadSovrBoard } from "./client";
25
27
  import {
28
+ findSovereign,
26
29
  formatContract,
27
30
  formatCurrencyMove,
28
31
  formatLevel,
@@ -82,7 +85,13 @@ export function SovrPane({ focused, width, height }: PaneProps) {
82
85
  const resource = useAsyncResource(loadSovrBoard, { initialData: getCachedSovrBoard });
83
86
  const { loading, load: refresh, reload } = resource;
84
87
  const payload = resource.data?.payload ?? null;
85
- const [selectedId, setSelectedId] = usePluginPaneState<string | null>("sovr:selected", null);
88
+ // `SOVR Brazil` opens on that country, named as `fn SOVR Brazil` names it; a later `SOVR Chile` replaces it.
89
+ const [selectedId, setSelectedId] = useCommandValue<string | null>(
90
+ FIXED_INCOME_PANE_ID,
91
+ "sovr:selected",
92
+ (params) => params.view === "sovereign" && params.country ? params.country : null,
93
+ null,
94
+ );
86
95
  const [openId, setOpenId] = usePluginPaneState<string | null>("sovr:open", null);
87
96
  useAutoRefresh(resource.updatedAt, refresh);
88
97
 
@@ -131,12 +140,14 @@ export function SovrPane({ focused, width, height }: PaneProps) {
131
140
  );
132
141
  }
133
142
 
134
- const selected = rows.find((row) => row.id === selectedId) ?? rows[0];
143
+ // A country the command named that the board does not have leaves the board on its first.
144
+ const named = selectedId ? findSovereign(payload?.sovereigns ?? [], selectedId) : null;
145
+ const selected = rows.find((row) => row.id === selectedId) ?? rows.find((row) => row.id === named?.id) ?? rows[0];
135
146
  return (
136
147
  <MarketBoardStack rows={rows} width={width} height={height} focused={focused}
137
148
  rootBefore={({ columns }) => <ChartTableHeader width={width} height={height} tableRows={rows.length}
138
149
  tableColumns={columns} chart={selected ? historyChart(selected) : null} />}
139
- selectedId={selectedId} onSelectedIdChange={setSelectedId} openId={openId} onOpenIdChange={setOpenId}
150
+ selectedId={selected?.id ?? null} onSelectedIdChange={setSelectedId} openId={openId} onOpenIdChange={setOpenId}
140
151
  labelHeader="SOVEREIGN" labelWidth={18} valueLabel="5Y" valueWidth={9} changeLabel="1M" signedChange
141
152
  extraColumns={extraColumns}
142
153
  renderDetail={(row) => <SovereignDetail row={row} width={width} height={Math.max(5, height - 2)} focused={focused} />} />
@@ -4,6 +4,7 @@ import { Button, ChartTableHeader, DataTableStackView, DetailScrollBody, Externa
4
4
  import { useAsyncResource, usePluginPaneState } from "../../../public/react";
5
5
  import { useThemeColors } from "../../../theme/theme-context";
6
6
  import { Box, Text, TextAttributes, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
7
+ import { quoteBlockStyle } from "../../../components/ui/quote";
7
8
  import { fetchCreditInstrument } from "./client";
8
9
  import { comparatorSymbol, covenantNumber, covenantTerms, creditPercent, factColumns, factValue, fieldLabel, hasAmendments, headroomTone, NO_VALUE, sentence, structuredFields } from "./model";
9
10
 
@@ -14,7 +15,7 @@ const MATCH = { exact: "Exact", whitespace: "Whitespace normalized", nfkc_whites
14
15
  function Quote({ text, width }: { text: string; width: number }) {
15
16
  const colors = useThemeColors(), desktop = useUiCapabilities().nativePaneChrome === true;
16
17
  return <Box paddingLeft={1} border={desktop ? undefined : ["left"]} borderColor={colors.borderFocused}
17
- style={desktop ? { borderLeft: `2px solid ${colors.borderFocused}`, paddingLeft: "calc(1.5 * var(--cell-w))" } : undefined} data-gloom-role="credit-quote">
18
+ style={desktop ? quoteBlockStyle() : undefined} data-gloom-role="credit-quote">
18
19
  <Text width={Math.max(1, width - 2)} wrapMode="word" wrapText fg={colors.textBright}>{text}</Text>
19
20
  </Box>;
20
21
  }
@@ -1,6 +1,7 @@
1
1
  import type { PluginModule } from "../plugin-module";
2
2
  import { createTickerSurfacePaneTemplate } from "../shared/ticker-surface";
3
3
  import { fixedIncomeShortcut } from "../fixed-income/shortcut";
4
+ import { SEC_FILINGS_VIEW } from "../shared/report-freshness";
4
5
  import { creditCache } from "./client";
5
6
  import { creditHeadless, covenantsHeadless } from "./headless";
6
7
 
@@ -18,6 +19,7 @@ export const creditDocumentsModule: PluginModule = {
18
19
  shortcut: "CRDOC",
19
20
  }),
20
21
  headless: creditHeadless,
22
+ reportFreshness: SEC_FILINGS_VIEW,
21
23
  }, "issuer-debt", "documents"),
22
24
  fixedIncomeShortcut({
23
25
  ...createTickerSurfacePaneTemplate({
@@ -31,6 +33,7 @@ export const creditDocumentsModule: PluginModule = {
31
33
  settings: () => ({ tab: "covenants" }),
32
34
  }),
33
35
  headless: covenantsHeadless,
36
+ reportFreshness: SEC_FILINGS_VIEW,
34
37
  }, "issuer-debt", "documents"),
35
38
  ],
36
39
  };
@@ -1,7 +1,7 @@
1
1
  import type { CreditDocumentsPayload, CreditFact, CreditHeadroom, CreditInstrument, CreditMaturityBucket, CreditScreenRow, CreditValue } from "../../../api-client/credit-documents";
2
2
  import type { DataTableColumn, StatItem } from "../../../components";
3
3
  import { scalarPoint, staticSeries } from "../../../components/chart/static/series";
4
- import { getTableWidth } from "../../../components/ui/table-layout";
4
+ import { dropColumnsToFit } from "../../../components/ui/table-layout";
5
5
  import type { ResolvedSeries } from "../../../time-series/types";
6
6
  import { displayWidth } from "../../../utils/format";
7
7
 
@@ -199,16 +199,9 @@ export function capitalFigures(data: CreditDocumentsPayload): StatItem[] {
199
199
  }
200
200
 
201
201
  type Column<Id extends string> = DataTableColumn & { id: Id };
202
- /** The table's width with its gaps and padding, plus the vertical scrollbar's cell. */
203
- const fits = (columns: readonly DataTableColumn[], width: number) => getTableWidth(columns) + 1 <= width;
204
- /** Narrow panes drop whole columns, least important first, instead of scrolling sideways. */
202
+ /** Narrow panes drop whole columns, least important first, instead of scrolling sideways; the scrollbar keeps its cell. */
205
203
  function fitColumns<Id extends string>(columns: readonly Column<Id>[], width: number, dropOrder: readonly Id[]): Column<Id>[] {
206
- let shown = [...columns];
207
- for (const id of dropOrder) {
208
- if (fits(shown, width)) break;
209
- shown = shown.filter((column) => column.id !== id);
210
- }
211
- return shown;
204
+ return dropColumnsToFit(columns, width - 1, dropOrder);
212
205
  }
213
206
 
214
207
  type CapitalColumnId = "name" | "facility" | "coupon" | "maturity" | "principal" | "currency" | "ranking" | "control";
@@ -1,6 +1,11 @@
1
1
  import { apiClient } from "../../../api-client";
2
2
  import { ApiRequestError } from "../../../api-client/errors";
3
- import type { CryptoMarketAsset, CryptoMarketsPayload } from "../../../api-client/crypto-markets";
3
+ import type {
4
+ CryptoMarketAsset,
5
+ CryptoMarketsPayload,
6
+ StablecoinSupplyHistoryPayload,
7
+ StablecoinSupplyPayload,
8
+ } from "../../../api-client/crypto-markets";
4
9
  import { createPluginCache } from "../../../data/plugin-cache";
5
10
  import { cachedCloudResource, loadCloudResource, unavailableOnServer } from "../shared/cloud-resource";
6
11
  import { isFiniteNumber } from "../../../utils/guards";
@@ -58,6 +63,27 @@ function validAsset(asset: CryptoMarketAsset): boolean {
58
63
  );
59
64
  }
60
65
 
66
+ const validPeg = (peg: CryptoMarketAsset["peg"]) =>
67
+ !!peg
68
+ && typeof peg.currency === "string"
69
+ && /^[A-Z]{3}$/.test(peg.currency)
70
+ && typeof peg.accrues === "boolean"
71
+ && (peg.price === null || (isFiniteNumber(peg.price) && peg.price > 0))
72
+ && nullableInstant(peg.asOf);
73
+
74
+ const validRange = (range: CryptoMarketAsset["range24h"]) =>
75
+ !!range
76
+ && [range.low, range.high].every((value) => isFiniteNumber(value) && value > 0)
77
+ && [range.lowAt, range.highAt, range.start, range.end].every(instant);
78
+
79
+ /** A malformed peg or 24h range is dropped from its coin alone; the coin and the rest of the board stay. */
80
+ function withValidStablecoinFields(asset: CryptoMarketAsset): CryptoMarketAsset {
81
+ const peg = asset.peg != null && !validPeg(asset.peg);
82
+ const range = asset.range24h != null && !validRange(asset.range24h);
83
+ if (!peg && !range) return asset;
84
+ return { ...asset, ...(peg ? { peg: null } : {}), ...(range ? { range24h: null } : {}) };
85
+ }
86
+
61
87
  export function validateCryptoMarkets(data: CryptoMarketsPayload): CryptoMarketsPayload {
62
88
  if (
63
89
  !data
@@ -77,7 +103,8 @@ export function validateCryptoMarkets(data: CryptoMarketsPayload): CryptoMarkets
77
103
  ) {
78
104
  throw new Error("The server returned an invalid crypto board");
79
105
  }
80
- return data;
106
+ const assets = data.assets.map(withValidStablecoinFields);
107
+ return assets.every((asset, index) => asset === data.assets[index]) ? data : { ...data, assets };
81
108
  }
82
109
 
83
110
  export async function fetchCryptoMarkets(
@@ -100,3 +127,126 @@ export function cachedCryptoMarkets() {
100
127
  export function loadCryptoMarkets(force = false) {
101
128
  return loadCloudResource(cryptoMarketsCache, "usd", () => fetchCryptoMarkets(), { force, validate: validateCryptoMarkets });
102
129
  }
130
+
131
+ // Stablecoin supply ------------------------------------------------------------
132
+
133
+ const stablecoinSupplyCache = createPluginCache<StablecoinSupplyPayload>({
134
+ kind: "stablecoin-supply",
135
+ source: "gloom-cloud",
136
+ schemaVersion: 1,
137
+ // The server reads the source once a UTC day; a month-old copy still dates itself.
138
+ policy: { staleMs: 30 * 60_000, expireMs: 30 * 86_400_000 },
139
+ });
140
+
141
+ const stablecoinSupplyHistoryCache = createPluginCache<StablecoinSupplyHistoryPayload>({
142
+ kind: "stablecoin-supply-history",
143
+ source: "gloom-cloud",
144
+ schemaVersion: 1,
145
+ policy: { staleMs: 30 * 60_000, expireMs: 30 * 86_400_000 },
146
+ });
147
+
148
+ export const STABLECOIN_SUPPLY_CACHES = [stablecoinSupplyCache, stablecoinSupplyHistoryCache] as const;
149
+
150
+ const MAX_SUPPLY_DAYS = 20_000;
151
+ const supplyValues = (values: unknown) =>
152
+ Array.isArray(values) && values.length <= MAX_SUPPLY_DAYS && values.every((value) => value === null || (isFiniteNumber(value) && value >= 0));
153
+ const nullableString = (value: unknown) => value === null || typeof value === "string";
154
+ const supplyStatus = (value: unknown) => value === "available" || value === "stale" || value === "unavailable";
155
+
156
+ export function validateStablecoinSupply(data: StablecoinSupplyPayload): StablecoinSupplyPayload {
157
+ const history = data?.history;
158
+ if (
159
+ !data
160
+ || data.version !== 1
161
+ || !instant(data.generatedAt)
162
+ || !nullableInstant(data.fetchedAt)
163
+ || !(data.asOf === null || date(data.asOf))
164
+ || !supplyStatus(data.status)
165
+ || (data.total !== null && (
166
+ !data.total
167
+ || !isFiniteNumber(data.total.supply)
168
+ || ![data.total.change7d, data.total.change7dPercent, data.total.change30d, data.total.change30dPercent].every(nullableNumber)
169
+ ))
170
+ || !Array.isArray(data.coins)
171
+ || data.coins.length > 500
172
+ || !data.coins.every((coin) => !!coin
173
+ && typeof coin.symbol === "string"
174
+ && coin.symbol.length > 0
175
+ && typeof coin.name === "string"
176
+ && typeof coin.pegType === "string"
177
+ && nullableString(coin.pegMechanism)
178
+ && isFiniteNumber(coin.supply)
179
+ && coin.supply >= 0
180
+ && [coin.price, coin.change7d, coin.change7dPercent, coin.change30d, coin.change30dPercent, coin.share].every(nullableNumber))
181
+ || (history !== null && (
182
+ !history
183
+ || !date(history.start)
184
+ || !supplyValues(history.total)
185
+ || !Array.isArray(history.coins)
186
+ || history.coins.length > 20
187
+ || !history.coins.every((coin) => !!coin
188
+ && typeof coin.symbol === "string"
189
+ && typeof coin.name === "string"
190
+ && supplyValues(coin.values)
191
+ && coin.values.length === history.total.length)
192
+ ))
193
+ || !Array.isArray(data.warnings)
194
+ || data.warnings.some((warning) => typeof warning !== "string")
195
+ ) {
196
+ throw new Error("The server returned invalid stablecoin supply");
197
+ }
198
+ return data;
199
+ }
200
+
201
+ function validateStablecoinSupplyHistory(data: StablecoinSupplyHistoryPayload): StablecoinSupplyHistoryPayload {
202
+ if (
203
+ !data
204
+ || data.version !== 1
205
+ || !instant(data.generatedAt)
206
+ || !(data.asOf === null || date(data.asOf))
207
+ || !supplyStatus(data.status)
208
+ || typeof data.symbol !== "string"
209
+ || typeof data.name !== "string"
210
+ || (data.history !== null && (!data.history || !date(data.history.start) || !supplyValues(data.history.values)))
211
+ || !Array.isArray(data.warnings)
212
+ ) {
213
+ throw new Error("The server returned invalid stablecoin supply history");
214
+ }
215
+ return data;
216
+ }
217
+
218
+ function supplyError(error: unknown, what: string): unknown {
219
+ if (error instanceof ApiRequestError && error.status === 503) return new Error(`${what} is temporarily unavailable`);
220
+ return unavailableOnServer(error, `${what} is not available yet.`);
221
+ }
222
+
223
+ export async function fetchStablecoinSupply(
224
+ client: Pick<typeof apiClient, "getCloudStablecoinSupply"> = apiClient,
225
+ ): Promise<StablecoinSupplyPayload> {
226
+ try {
227
+ return validateStablecoinSupply(await client.getCloudStablecoinSupply());
228
+ } catch (error) {
229
+ throw supplyError(error, "Stablecoin supply");
230
+ }
231
+ }
232
+
233
+ export function cachedStablecoinSupply() {
234
+ return cachedCloudResource(stablecoinSupplyCache, "all", validateStablecoinSupply);
235
+ }
236
+
237
+ export function loadStablecoinSupply(force = false) {
238
+ return loadCloudResource(stablecoinSupplyCache, "all", () => fetchStablecoinSupply(), { force, validate: validateStablecoinSupply });
239
+ }
240
+
241
+ /** One listed stablecoin's daily supply, by its symbol (USDT). */
242
+ export function loadStablecoinSupplyHistory(symbol: string) {
243
+ const key = symbol.trim().toUpperCase();
244
+ return loadCloudResource(stablecoinSupplyHistoryCache, key, async () => {
245
+ try {
246
+ return validateStablecoinSupplyHistory(await apiClient.getCloudStablecoinSupplyHistory(key));
247
+ } catch (error) {
248
+ if (error instanceof ApiRequestError && error.status === 404) throw new Error(`No stablecoin supply series for ${key}: it is not among the stablecoins CRYP lists.`);
249
+ throw supplyError(error, `${key} supply history`);
250
+ }
251
+ }, { validate: validateStablecoinSupplyHistory });
252
+ }