zframes 0.5.2 → 0.6.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 (126) hide show
  1. package/NOTICE +6 -2
  2. package/dist/index.js +614 -10
  3. package/package.json +2 -2
  4. package/runtime/assets/{bitcoin-dominance-CtnczH5N.js → bitcoin-dominance-CweHlZx7.js} +1 -1
  5. package/runtime/assets/{breakeven-zbCEQ5ag.js → breakeven-CG9rKwgE.js} +1 -1
  6. package/runtime/assets/{breathing-6Wmy_hqF.js → breathing-cDundHq6.js} +1 -1
  7. package/runtime/assets/{btc-blocks-D1xOLm2L.js → btc-blocks-Do_nySHd.js} +1 -1
  8. package/runtime/assets/{btc-difficulty-BTbKIqrl.js → btc-difficulty-vNbz5uRo.js} +1 -1
  9. package/runtime/assets/{btc-fees-5Geh2TSa.js → btc-fees-BmADLsmK.js} +1 -1
  10. package/runtime/assets/{btc-hashrate-DZfnxUsi.js → btc-hashrate-Wx2RAG-5.js} +1 -1
  11. package/runtime/assets/{btc-mempool-8oOMDiaW.js → btc-mempool-CTwbkMUR.js} +1 -1
  12. package/runtime/assets/{calculator-D91iI7KM.js → calculator-mvv6XpQC.js} +1 -1
  13. package/runtime/assets/{checklist-DNrOJw0w.js → checklist-CuEw3GpE.js} +1 -1
  14. package/runtime/assets/{clock-BzAIAbhU.js → clock-Cjnwi03W.js} +1 -1
  15. package/runtime/assets/{coin-movers-99W2EABZ.js → coin-movers-Bcx1XR0F.js} +1 -1
  16. package/runtime/assets/{countdown-ZAJmbykg.js → countdown-Cdi5gSSu.js} +1 -1
  17. package/runtime/assets/cycle-shared-BOGcJDzT.js +1 -0
  18. package/runtime/assets/cycle-signals-CS629ZDc.js +1 -0
  19. package/runtime/assets/{daily-analysis-CS5MqofA.js → daily-analysis-DX8bVq85.js} +1 -1
  20. package/runtime/assets/{day-meter-DzBvLcpd.js → day-meter-DDfTuhms.js} +1 -1
  21. package/runtime/assets/defi-revenue-CpeAGwhb.js +1 -0
  22. package/runtime/assets/{dex-volume-chart-BfnczfAT.js → dex-volume-chart-sHIuJACJ.js} +1 -1
  23. package/runtime/assets/{dex-volume-treemap-CLyIrkgU.js → dex-volume-treemap-rSTrzz7O.js} +1 -1
  24. package/runtime/assets/{dice-CAvRf0md.js → dice-BrFORdjN.js} +1 -1
  25. package/runtime/assets/{dino-game-gsyCpJ-0.js → dino-game-BOV8mV1d.js} +1 -1
  26. package/runtime/assets/{divider-DCTu-qNh.js → divider-C33tH1RU.js} +1 -1
  27. package/runtime/assets/{drawdy-CZWCFtog.js → drawdy-BIb36JN9.js} +1 -1
  28. package/runtime/assets/dxy-CRifEdp_.js +1 -0
  29. package/runtime/assets/editor-CZoWRTJC.css +1 -0
  30. package/runtime/assets/editor-Dnp1eXvY.js +68 -0
  31. package/runtime/assets/etf-flows-BV10E2R-.js +1 -0
  32. package/runtime/assets/etf-flows-chart-DHu8mkXm.js +1 -0
  33. package/runtime/assets/eth-staking-BqWeJq6F.js +1 -0
  34. package/runtime/assets/eth-supply-CF-MgHjn.js +1 -0
  35. package/runtime/assets/{fear-greed-DOcPswrx.js → fear-greed-DuDR56h2.js} +1 -1
  36. package/runtime/assets/{filings-feed-Cs--DpYl.js → filings-feed-BpfO2yF6.js} +1 -1
  37. package/runtime/assets/{financial-stress-BqnxLk2O.js → financial-stress-BfYJdlry.js} +1 -1
  38. package/runtime/assets/{flappy-bird-DaasqVGg.js → flappy-bird-Dbb2UQBv.js} +1 -1
  39. package/runtime/assets/{fundamentals-GseULnsD.js → fundamentals-CUnqjF--.js} +1 -1
  40. package/runtime/assets/funding-comparison-CMKxW1n-.js +1 -0
  41. package/runtime/assets/{funding-heatmap-2RvVLTPN.js → funding-heatmap-CZWnYF8Y.js} +1 -1
  42. package/runtime/assets/{funding-rate-chart-DCRKHp6g.js → funding-rate-chart-C-tpwid_.js} +1 -1
  43. package/runtime/assets/{fx-board-CVW6VmbY.js → fx-board-YAy44m5d.js} +1 -1
  44. package/runtime/assets/{heading-BaRMJq2t.js → heading-uIVBEE7K.js} +1 -1
  45. package/runtime/assets/{holiday-calendar-2OBfwbh-.js → holiday-calendar-DCj83hi2.js} +1 -1
  46. package/runtime/assets/{image-CuTXEV7Q.js → image-CITPAmp0.js} +1 -1
  47. package/runtime/assets/index-Bx7RmzY8.js +1 -0
  48. package/runtime/assets/index-CrmTiZaB.css +1 -0
  49. package/runtime/assets/index-DyvZokhk.js +1097 -0
  50. package/runtime/assets/indicators-CogwjDn9.js +1 -0
  51. package/runtime/assets/{inflation-pulse-B8E9uzQB.js → inflation-pulse-Bqa3-cuC.js} +1 -1
  52. package/runtime/assets/{journal-log-7APM_99k.js → journal-log-Bgjia8cQ.js} +1 -1
  53. package/runtime/assets/{journal-open-CcdGuysA.js → journal-open-Bm5gwWXz.js} +1 -1
  54. package/runtime/assets/{journal-results-CUTn4-kq.js → journal-results-cEWe2pbe.js} +1 -1
  55. package/runtime/assets/{journal-score-C31dg2yL.js → journal-score-vmfF-9bK.js} +1 -1
  56. package/runtime/assets/{journal-ui-C5ueSjZx.js → journal-ui-ApBNIq5_.js} +1 -1
  57. package/runtime/assets/{labor-market-DgvDQtFo.js → labor-market-azDXD-dR.js} +1 -1
  58. package/runtime/assets/{lightning-stats-CiUlm-e_.js → lightning-stats-nkyh2dOX.js} +1 -1
  59. package/runtime/assets/{link-grid-DlsY59eq.js → link-grid-BEo4b54T.js} +1 -1
  60. package/runtime/assets/ma-multiplier-BllDQMF5.js +1 -0
  61. package/runtime/assets/macro-calendar-Ck0dJk4p.js +1 -0
  62. package/runtime/assets/{market-cap-treemap-6vqLUgVk.js → market-cap-treemap-AxE2EYPO.js} +1 -1
  63. package/runtime/assets/{market-hours-BArlXOQB.js → market-hours-BSwXtU8c.js} +1 -1
  64. package/runtime/assets/{marquee-2Di2SqI2.js → marquee-1Zr5qDJP.js} +1 -1
  65. package/runtime/assets/mayer-multiple-DpBJNd4d.js +1 -0
  66. package/runtime/assets/{mining-pools-Bg02wm2V.js → mining-pools-B-jxdTot.js} +1 -1
  67. package/runtime/assets/{mover-row-C8040L85.js → mover-row-Dg96EIqq.js} +1 -1
  68. package/runtime/assets/mvrv-Dx_S0TwE.js +1 -0
  69. package/runtime/assets/{national-debt-BS57WjA3.js → national-debt-BKVBHaqm.js} +1 -1
  70. package/runtime/assets/{news-feed-oBCTiuoo.js → news-feed-C9itZmyp.js} +1 -1
  71. package/runtime/assets/{note-BLWlz52v.js → note-BtCnmuMo.js} +1 -1
  72. package/runtime/assets/nupl-aIjkc57m.js +1 -0
  73. package/runtime/assets/{open-interest-DxMqZcmu.js → open-interest-C0ulogv6.js} +1 -1
  74. package/runtime/assets/{options-iv-CgIIFdpN.js → options-iv-CdUder3x.js} +1 -1
  75. package/runtime/assets/{options-oi-strike-blRp4kmB.js → options-oi-strike-CvCZnMCR.js} +1 -1
  76. package/runtime/assets/{options-put-call-CyOwXBVQ.js → options-put-call-FuaDHJ-S.js} +1 -1
  77. package/runtime/assets/pi-cycle-BuCnLnIJ.js +1 -0
  78. package/runtime/assets/{pomodoro-BKJlh-bz.js → pomodoro-DDBVVcSR.js} +1 -1
  79. package/runtime/assets/{portfolio-allocation-Cat1vq2_.js → portfolio-allocation-DAnQk_h_.js} +1 -1
  80. package/runtime/assets/{portfolio-common-DeyRfuNV.js → portfolio-common-Bi16i0aA.js} +1 -1
  81. package/runtime/assets/{portfolio-holdings-DDDhMMFL.js → portfolio-holdings-MyAinCzt.js} +1 -1
  82. package/runtime/assets/{portfolio-value-D9qrGeZp.js → portfolio-value-BPURwKf8.js} +1 -1
  83. package/runtime/assets/prediction-markets-Bzy51qnV.js +1 -0
  84. package/runtime/assets/{price-chart-CQJNOBtu.js → price-chart-BOCD8ka3.js} +1 -1
  85. package/runtime/assets/{price-compare-DqBiHd7S.js → price-compare-DZlF-qhZ.js} +1 -1
  86. package/runtime/assets/{price-liveline-BlVGC2-R.js → price-liveline-Bl7qCd5-.js} +1 -1
  87. package/runtime/assets/{price-ticker-QdVoVaQh.js → price-ticker-D2W4T02y.js} +1 -1
  88. package/runtime/assets/{protocol-fees-treemap-39F-aE33.js → protocol-fees-treemap-DiIt4bfo.js} +1 -1
  89. package/runtime/assets/{protocol-tvl-chart-DZOgbMZu.js → protocol-tvl-chart-CmzANiR7.js} +1 -1
  90. package/runtime/assets/{protocol-tvl-treemap-DusQ6xL2.js → protocol-tvl-treemap-BjNPrrtL.js} +1 -1
  91. package/runtime/assets/puell-multiple-BGrJX43r.js +1 -0
  92. package/runtime/assets/{quote-Di049ggj.js → quote-CRM3bfI7.js} +1 -1
  93. package/runtime/assets/{rates-board-Dm3tb6-P.js → rates-board-Cb9rV0_-.js} +1 -1
  94. package/runtime/assets/realized-price-CYlrFa0m.js +1 -0
  95. package/runtime/assets/reserve-risk-Be98XUsD.js +1 -0
  96. package/runtime/assets/{returns-projector-BiMx_kSw.js → returns-projector-D67a_yvC.js} +1 -1
  97. package/runtime/assets/{risk-reward-1Q_Kt75s.js → risk-reward-C7WMz2od.js} +1 -1
  98. package/runtime/assets/rsi-momentum-IglnulkJ.js +1 -0
  99. package/runtime/assets/{rules-card-BkAX9PEq.js → rules-card-DJs3fDVN.js} +1 -1
  100. package/runtime/assets/scene-uwfOGek1.js +1 -0
  101. package/runtime/assets/sector-performance-DVMaleLY.js +1 -0
  102. package/runtime/assets/sector-treemap-B681nSi6.js +1 -0
  103. package/runtime/assets/{session-progress-D_1dzPzM.js → session-progress-CZO3LqUi.js} +1 -1
  104. package/runtime/assets/{short-volume-U-uFonb2.js → short-volume-l8_9Yoh3.js} +1 -1
  105. package/runtime/assets/{snake-Dp4E3Dcv.js → snake-CifbTGlZ.js} +1 -1
  106. package/runtime/assets/sopr-Dw_oz-mC.js +1 -0
  107. package/runtime/assets/{spotify-embed-Cw95WZjV.js → spotify-embed-BA0m1IRb.js} +1 -1
  108. package/runtime/assets/stablecoin-chains-Dd2LqqqY.js +1 -0
  109. package/runtime/assets/stablecoin-supply-DM4ogL4V.js +1 -0
  110. package/runtime/assets/{stopwatch-B2_iDkKK.js → stopwatch-Co72v-7u.js} +1 -1
  111. package/runtime/assets/{top-movers--vCUiTII.js → top-movers-CLmC2TNu.js} +1 -1
  112. package/runtime/assets/{treasury-auctions-BpzYivLg.js → treasury-auctions-Dl9fiRgf.js} +1 -1
  113. package/runtime/assets/{treemap-leaf-DNIoJEK-.js → treemap-leaf-Dn31k9S9.js} +1 -1
  114. package/runtime/assets/trending-coins-Cpx9T6cG.js +1 -0
  115. package/runtime/assets/{tvl-treemap-BYgD9bNy.js → tvl-treemap-e610jE8k.js} +1 -1
  116. package/runtime/assets/{video-D-nBm697.js → video-CeKjM-cE.js} +1 -1
  117. package/runtime/assets/volume-profile-CiMFsIBu.js +1 -0
  118. package/runtime/assets/{yield-curve-8IsrMS_9.js → yield-curve-DkB0u2_Q.js} +1 -1
  119. package/runtime/assets/yield-scanner-BP90untT.js +1 -0
  120. package/runtime/index.html +2 -2
  121. package/runtime/assets/editor-BMMobjrE.css +0 -1
  122. package/runtime/assets/editor-Ckt9OQ98.js +0 -68
  123. package/runtime/assets/index-BqHx9BjX.css +0 -1
  124. package/runtime/assets/index-CH54P4Cn.js +0 -936
  125. package/runtime/assets/index-DK7jWlTL.js +0 -1
  126. package/runtime/assets/unicorn-scene-DcohHRPZ.js +0 -1
package/dist/index.js CHANGED
@@ -192,13 +192,17 @@ var DashboardSpecSchema = z2.preprocess(
192
192
  ),
193
193
  gap: z2.number().min(0).default(12).describe(
194
194
  "Pixels of space between frames (the grid gutter). 0 makes the cards flush; the editor's Layout rail exposes this as a slider."
195
+ ),
196
+ paddingX: z2.number().min(0).default(0).describe(
197
+ "Horizontal padding (px) inside the dashboard grid \u2014 the left/right gutter between the frames and the viewport edges (the x-axis inset). 0 (default) keeps the board flush to the edges; the editor's Layout rail exposes this as a slider."
195
198
  )
196
199
  }).default({
197
200
  mode: "flow-vertical",
198
201
  columns: 12,
199
202
  rowHeight: 96,
200
203
  rows: 6,
201
- gap: 12
204
+ gap: 12,
205
+ paddingX: 0
202
206
  }),
203
207
  background: BackgroundSchema.default({
204
208
  type: "none",
@@ -426,7 +430,12 @@ var SOURCES = {
426
430
  mempool: { name: "mempool.space", url: "https://mempool.space" },
427
431
  deribit: { name: "Deribit", url: "https://www.deribit.com" },
428
432
  coinpaprika: { name: "Coinpaprika", url: "https://coinpaprika.com" },
429
- frankfurter: { name: "Frankfurter (ECB)", url: "https://frankfurter.dev" }
433
+ frankfurter: { name: "Frankfurter (ECB)", url: "https://frankfurter.dev" },
434
+ coinMetrics: { name: "Coin Metrics", url: "https://coinmetrics.io" },
435
+ bitcoinData: { name: "bitcoin-data.com", url: "https://bitcoin-data.com" },
436
+ ultrasound: { name: "ultrasound.money", url: "https://ultrasound.money" },
437
+ polymarket: { name: "Polymarket", url: "https://polymarket.com" },
438
+ sosovalue: { name: "SoSoValue", url: "https://sosovalue.com" }
430
439
  };
431
440
  var clockMeta = defineFrameMeta({
432
441
  name: "clock",
@@ -772,7 +781,7 @@ var fundamentalsMeta = defineFrameMeta({
772
781
  label: "Fundamentals",
773
782
  category: "equities",
774
783
  iconUrl: widgetIcon("fundamentals"),
775
- layout: { w: 4, h: 3, minW: 3, minH: 3 },
784
+ layout: { w: 4, h: 4, minW: 3, minH: 3 },
776
785
  description: "Headline financials for one US-listed company from SEC EDGAR XBRL company facts \u2014 revenue, net income, total assets, shareholders' equity, diluted EPS, and shares outstanding, each labelled with its fiscal period. Income-statement figures are the latest full fiscal year; balance-sheet figures are the latest reported quarter. Keyless official data that updates only when the company files (annual/quarterly), not a live feed. Requires the zframes runtime's data proxy (it ships with `zframes serve` / `vite dev`); resolve by ticker (bundled top-500 map) or raw SEC CIK.",
777
786
  capabilities: ["fundamentals"],
778
787
  source: SOURCES.secEdgar,
@@ -916,7 +925,7 @@ var journalScoreMeta = defineFrameMeta({
916
925
  label: "Journal \xB7 Scoreboard",
917
926
  category: "journal",
918
927
  iconUrl: widgetIcon("journal-score"),
919
- layout: { w: 4, h: 2, minW: 3, minH: 2 },
928
+ layout: { w: 4, h: 3, minW: 3, minH: 3 },
920
929
  description: "The decision-journal scoreboard \u2014 a story, not a spreadsheet: where your judgment has an edge, where it leaks, and how calibrated your confidence is, plus a one-line read from zAI. Aggregates the calls logged via Journal \xB7 Log.",
921
930
  capabilities: [],
922
931
  schema: z3.object({})
@@ -1503,7 +1512,7 @@ var btcFeesMeta = defineFrameMeta({
1503
1512
  label: "BTC Fees",
1504
1513
  category: "bitcoin",
1505
1514
  iconUrl: widgetIcon("btc-fees"),
1506
- layout: { w: 3, h: 2, minW: 2, minH: 2 },
1515
+ layout: { w: 3, h: 3, minW: 2, minH: 3 },
1507
1516
  description: "Recommended Bitcoin on-chain fee rates (sat/vB) from mempool.space \u2014 the next-block ('fastest'), ~30-minute, ~1-hour, economy, and minimum tiers, as a compact gauge. Live mempool data, keyless; updates every ~30s.",
1508
1517
  capabilities: ["btc-fees"],
1509
1518
  source: SOURCES.mempool,
@@ -1667,6 +1676,377 @@ var coinMoversMeta = defineFrameMeta({
1667
1676
  )
1668
1677
  })
1669
1678
  });
1679
+ var mvrvMeta = defineFrameMeta({
1680
+ name: "mvrv",
1681
+ label: "MVRV Ratio",
1682
+ category: "onchain",
1683
+ iconUrl: widgetIcon("mvrv"),
1684
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1685
+ description: "Bitcoin MVRV ratio \u2014 market cap \xF7 realized cap. Above ~3 historically marks cycle tops (overvalued); below ~1 marks deep value near bottoms. Shows the current ratio, its valuation zone, the MVRV Z-score, and a history sparkline. Keyless on-chain data from Coin Metrics.",
1686
+ capabilities: ["onchain-valuation"],
1687
+ source: SOURCES.coinMetrics,
1688
+ schema: z3.object({
1689
+ window: z3.enum(["1Y", "2Y", "4Y", "all"]).default("all").describe("How much history the sparkline shows.")
1690
+ })
1691
+ });
1692
+ var nuplMeta = defineFrameMeta({
1693
+ name: "nupl",
1694
+ label: "NUPL",
1695
+ category: "onchain",
1696
+ iconUrl: widgetIcon("nupl"),
1697
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1698
+ description: "Net Unrealized Profit/Loss \u2014 the share of Bitcoin's market cap held in unrealized profit. Maps to cycle sentiment phases: Capitulation (<0), Hope/Fear (0\u201325%), Optimism (25\u201350%), Belief (50\u201375%), Euphoria/Greed (>75%). Derived from MVRV; keyless Coin Metrics data.",
1699
+ capabilities: ["onchain-valuation"],
1700
+ source: SOURCES.coinMetrics,
1701
+ schema: z3.object({
1702
+ window: z3.enum(["1Y", "2Y", "4Y", "all"]).default("all").describe("How much history the sparkline shows.")
1703
+ })
1704
+ });
1705
+ var soprMeta = defineFrameMeta({
1706
+ name: "sopr",
1707
+ label: "SOPR",
1708
+ category: "onchain",
1709
+ iconUrl: widgetIcon("sopr"),
1710
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1711
+ description: "Spent Output Profit Ratio \u2014 whether coins moving on-chain are, on average, being sold in profit (>1) or loss (<1). Sustained dips below 1 mark capitulation; resets to ~1 in bull markets are healthy. Keyless full-history data from bitcoin-data.com (polled once daily).",
1712
+ capabilities: ["onchain-cycle-extras"],
1713
+ source: SOURCES.bitcoinData,
1714
+ schema: z3.object({
1715
+ window: z3.enum(["90D", "180D", "1Y"]).default("1Y").describe("How much history the sparkline shows.")
1716
+ })
1717
+ });
1718
+ var puellMultipleMeta = defineFrameMeta({
1719
+ name: "puell-multiple",
1720
+ label: "Puell Multiple",
1721
+ category: "onchain",
1722
+ iconUrl: widgetIcon("puell-multiple"),
1723
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1724
+ description: "Puell Multiple \u2014 daily miner issuance in USD \xF7 its 365-day average. High values (>4) mark cycle tops where miner revenue is stretched; low values (\u22640.5) mark miner capitulation near bottoms. Keyless data from bitcoin-data.com (polled once daily).",
1725
+ capabilities: ["onchain-cycle-extras"],
1726
+ source: SOURCES.bitcoinData,
1727
+ schema: z3.object({
1728
+ window: z3.enum(["90D", "180D", "1Y"]).default("1Y").describe("How much history the sparkline shows.")
1729
+ })
1730
+ });
1731
+ var mayerMultipleMeta = defineFrameMeta({
1732
+ name: "mayer-multiple",
1733
+ label: "Mayer Multiple",
1734
+ category: "onchain",
1735
+ iconUrl: widgetIcon("mayer-multiple"),
1736
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1737
+ description: "Mayer Multiple \u2014 BTC price \xF7 its 200-day moving average. Above ~2.4 has historically been overheated; below ~0.8 marks value zones. Computed in-browser from a keyless long daily price series (Coin Metrics).",
1738
+ capabilities: ["price-history-daily"],
1739
+ source: SOURCES.coinMetrics,
1740
+ schema: z3.object({
1741
+ window: z3.enum(["1Y", "2Y", "4Y", "all"]).default("2Y").describe("How much history the sparkline shows.")
1742
+ })
1743
+ });
1744
+ var piCycleMeta = defineFrameMeta({
1745
+ name: "pi-cycle",
1746
+ label: "Pi Cycle Top",
1747
+ category: "onchain",
1748
+ iconUrl: widgetIcon("pi-cycle"),
1749
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1750
+ description: "Pi Cycle Top indicator \u2014 the ratio of the 111-day MA to 2\xD7 the 350-day MA. When it crosses 1 (the 111DMA overtakes 2\xD7350DMA) it has historically pinpointed cycle tops within days. Computed in-browser from a keyless long daily price series (Coin Metrics).",
1751
+ capabilities: ["price-history-daily"],
1752
+ source: SOURCES.coinMetrics,
1753
+ schema: z3.object({
1754
+ window: z3.enum(["1Y", "2Y", "4Y", "all"]).default("2Y").describe("How much history the sparkline shows.")
1755
+ })
1756
+ });
1757
+ var maMultiplierMeta = defineFrameMeta({
1758
+ name: "ma-multiplier",
1759
+ label: "MA Multiplier",
1760
+ category: "onchain",
1761
+ iconUrl: widgetIcon("ma-multiplier"),
1762
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1763
+ description: "Long moving-average multiplier \u2014 BTC price \xF7 its multi-year moving average (2-year or 4-year). The 2Y band flags a buy zone below \xF71.5 and sell tiers at \xD72\u2013\xD75; the 4Y multiple marks tops above ~3.5\xD7. Computed in-browser from a keyless long daily price series (Coin Metrics).",
1764
+ capabilities: ["price-history-daily"],
1765
+ source: SOURCES.coinMetrics,
1766
+ schema: z3.object({
1767
+ years: z3.enum(["2", "4"]).default("2").describe("Moving-average window in years."),
1768
+ window: z3.enum(["2Y", "4Y", "all"]).default("all").describe("How much history the sparkline shows.")
1769
+ })
1770
+ });
1771
+ var rsiMomentumMeta = defineFrameMeta({
1772
+ name: "rsi-momentum",
1773
+ label: "RSI Momentum",
1774
+ category: "markets",
1775
+ iconUrl: widgetIcon("rsi-momentum"),
1776
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1777
+ description: "Wilder RSI on BTC daily closes with a 55/45 momentum regime: above 55 = risk-on, below 45 = risk-off, in between = neutral. Also flags classic overbought (\u226580) / oversold (\u226430) extremes. Computed in-browser from a keyless long daily price series (Coin Metrics).",
1778
+ capabilities: ["price-history-daily"],
1779
+ source: SOURCES.coinMetrics,
1780
+ schema: z3.object({
1781
+ period: z3.number().int().min(2).max(50).default(14).describe("RSI lookback period in days."),
1782
+ window: z3.enum(["90D", "180D", "1Y", "2Y"]).default("180D").describe("How much history the sparkline shows.")
1783
+ })
1784
+ });
1785
+ var volumeProfileMeta = defineFrameMeta({
1786
+ name: "volume-profile",
1787
+ label: "Volume Profile",
1788
+ category: "markets",
1789
+ iconUrl: widgetIcon("volume-profile"),
1790
+ layout: { w: 4, h: 4, minW: 3, minH: 3 },
1791
+ description: "Volume-by-price histogram over a lookback window \u2014 the Point of Control (POC, highest-volume price) and the 70% Value Area (VAH/VAL) that frame support/resistance. Computed in-browser from OHLCV candles. Pass any tradable symbol (crypto or a HIP-3 equity like 'xyz:TSLA').",
1792
+ capabilities: ["ohlcv"],
1793
+ source: SOURCES.hyperliquid,
1794
+ schema: z3.object({
1795
+ symbol: z3.string().default("BTC").describe(
1796
+ "Symbol to profile, e.g. 'BTC', 'ETH', or a HIP-3 equity 'xyz:TSLA'."
1797
+ ),
1798
+ interval: z3.enum(["1h", "4h", "1d"]).default("1d").describe("Candle interval."),
1799
+ lookbackDays: z3.number().int().min(7).max(365).default(90).describe("How many days of candles to build the profile from."),
1800
+ bins: z3.number().int().min(8).max(48).default(24).describe("Number of price buckets in the histogram.")
1801
+ })
1802
+ });
1803
+ var dxyMeta = defineFrameMeta({
1804
+ name: "dxy",
1805
+ label: "Dollar Index (DXY)",
1806
+ category: "macro",
1807
+ iconUrl: widgetIcon("dxy"),
1808
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1809
+ description: "US Dollar Index (DXY) \u2014 the dollar's strength vs a basket of six major currencies. A rising DXY is a macro headwind for risk assets (incl. BTC); a falling DXY a tailwind. Computed as the ICE-weighted geometric mean of keyless ECB reference rates (daily granularity).",
1810
+ capabilities: ["dollar-index"],
1811
+ source: SOURCES.frankfurter,
1812
+ schema: z3.object({})
1813
+ });
1814
+ var cycleSignalsMeta = defineFrameMeta({
1815
+ name: "cycle-signals",
1816
+ label: "Cycle Signals",
1817
+ category: "onchain",
1818
+ iconUrl: widgetIcon("cycle-signals"),
1819
+ layout: { w: 4, h: 5, minW: 3, minH: 3 },
1820
+ description: "A cycle top- or bottom-signal checklist \u2014 MVRV, MVRV Z-score, NUPL, Mayer Multiple, Puell, RSI, and Pi Cycle each checked against its historical extreme, with a live 'X of N firing' tally. A capstone that aggregates the on-chain and cycle metrics into one 'how late in the cycle are we' read. Keyless (Coin Metrics + bitcoin-data.com).",
1821
+ capabilities: [
1822
+ "onchain-valuation",
1823
+ "onchain-cycle-extras",
1824
+ "price-history-daily"
1825
+ ],
1826
+ source: [SOURCES.coinMetrics, SOURCES.bitcoinData],
1827
+ schema: z3.object({
1828
+ mode: z3.enum(["peak", "bottom"]).default("peak").describe(
1829
+ "Which checklist to show: cycle-top ('peak') or cycle-bottom ('bottom') signals."
1830
+ )
1831
+ })
1832
+ });
1833
+ var stablecoinSupplyMeta = defineFrameMeta({
1834
+ name: "stablecoin-supply",
1835
+ label: "Stablecoin Supply",
1836
+ category: "crypto",
1837
+ iconUrl: widgetIcon("stablecoin-supply"),
1838
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1839
+ description: "Total USD-stablecoin circulating supply \u2014 a market-wide liquidity gauge. Rising supply = fresh capital entering crypto (risk-on dry powder); contraction = risk-off. Shows the total, 1d/7d/30d change, and the largest chains. Keyless (DeFiLlama).",
1840
+ capabilities: ["stablecoins"],
1841
+ source: SOURCES.defillama,
1842
+ schema: z3.object({})
1843
+ });
1844
+ var yieldScannerMeta = defineFrameMeta({
1845
+ name: "yield-scanner",
1846
+ label: "Yield Scanner",
1847
+ category: "crypto",
1848
+ iconUrl: widgetIcon("yield-scanner"),
1849
+ layout: { w: 5, h: 4, minW: 3, minH: 3 },
1850
+ description: "Top DeFi yield pools ranked by APY, across every chain and protocol \u2014 the 'where's the yield' board. Filter to stablecoin pools or a TVL floor. Shows APY (base + reward), TVL, chain, and IL risk. Keyless (DeFiLlama yields).",
1851
+ capabilities: ["yields"],
1852
+ source: SOURCES.defillama,
1853
+ schema: z3.object({
1854
+ limit: z3.number().int().min(3).max(20).default(8).describe("How many pools to list."),
1855
+ stablecoinOnly: z3.boolean().default(false).describe("Only show stablecoin pools (lower impermanent-loss risk)."),
1856
+ minTvlUsd: z3.number().min(0).default(1e6).describe("Minimum pool TVL in USD \u2014 a liquidity floor to hide dust.")
1857
+ })
1858
+ });
1859
+ var defiRevenueMeta = defineFrameMeta({
1860
+ name: "defi-revenue",
1861
+ label: "DeFi Fees & Revenue",
1862
+ category: "crypto",
1863
+ iconUrl: widgetIcon("defi-revenue"),
1864
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1865
+ description: "Aggregate DeFi protocol fees across all of crypto \u2014 trailing-24h total with a daily trend. A read on real on-chain economic activity. Keyless (DeFiLlama).",
1866
+ capabilities: ["fees-overview"],
1867
+ source: SOURCES.defillama,
1868
+ schema: z3.object({})
1869
+ });
1870
+ var fundingComparisonMeta = defineFrameMeta({
1871
+ name: "funding-comparison",
1872
+ label: "Cross-Venue Funding",
1873
+ category: "derivatives",
1874
+ iconUrl: widgetIcon("funding-comparison"),
1875
+ layout: { w: 5, h: 4, minW: 3, minH: 3 },
1876
+ description: "Predicted perpetual funding rates compared across venues (Hyperliquid vs Binance vs Bybit), annualized, per coin \u2014 ranked by the cross-venue spread. A large spread flags a funding-arbitrage or crowded-positioning signal. Keyless (Hyperliquid predicted fundings).",
1877
+ capabilities: ["funding-comparison"],
1878
+ source: SOURCES.hyperliquid,
1879
+ schema: z3.object({
1880
+ limit: z3.number().int().min(3).max(20).default(8).describe("How many coins (by funding spread) to show.")
1881
+ })
1882
+ });
1883
+ var ethSupplyMeta = defineFrameMeta({
1884
+ name: "eth-supply",
1885
+ label: "ETH Ultrasound",
1886
+ category: "crypto",
1887
+ iconUrl: widgetIcon("eth-supply"),
1888
+ layout: { w: 4, h: 3, minW: 2, minH: 2 },
1889
+ description: "Ethereum supply economics \u2014 EIP-1559 burn vs PoS issuance and the resulting net annual supply growth. Negative growth = deflationary ('ultrasound money'). Shows the net rate, burn/issuance, and vs the counterfactual PoW issuance. Keyless (ultrasound.money).",
1890
+ capabilities: ["eth-supply"],
1891
+ source: SOURCES.ultrasound,
1892
+ schema: z3.object({})
1893
+ });
1894
+ var ethStakingMeta = defineFrameMeta({
1895
+ name: "eth-staking",
1896
+ label: "ETH Staking APR",
1897
+ category: "crypto",
1898
+ iconUrl: widgetIcon("eth-staking"),
1899
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
1900
+ description: "Ethereum staking yield \u2014 total validator APR broken into consensus issuance, MEV, and priority tips. The 'risk-free' ETH rate. Keyless (ultrasound.money).",
1901
+ capabilities: ["eth-supply"],
1902
+ source: SOURCES.ultrasound,
1903
+ schema: z3.object({})
1904
+ });
1905
+ var predictionMarketsMeta = defineFrameMeta({
1906
+ name: "prediction-markets",
1907
+ label: "Prediction Markets",
1908
+ category: "sentiment",
1909
+ iconUrl: widgetIcon("prediction-markets"),
1910
+ layout: { w: 4, h: 4, minW: 3, minH: 3 },
1911
+ description: "Live Polymarket odds \u2014 the highest-volume open prediction markets with their market-implied probabilities (macro, rates, crypto, politics). A real-money sentiment gauge. Keyless (Polymarket Gamma API).",
1912
+ capabilities: ["prediction-markets"],
1913
+ source: SOURCES.polymarket,
1914
+ schema: z3.object({
1915
+ limit: z3.number().int().min(3).max(20).default(6).describe("How many markets (by volume) to show.")
1916
+ })
1917
+ });
1918
+ var etfFlowsMeta = defineFrameMeta({
1919
+ name: "etf-flows",
1920
+ label: "Spot ETF Flows",
1921
+ category: "crypto",
1922
+ iconUrl: widgetIcon("etf-flows"),
1923
+ layout: { w: 4, h: 4, minW: 3, minH: 3 },
1924
+ description: "Spot Bitcoin or Ethereum ETF daily net flows \u2014 per-issuer (IBIT, FBTC, GBTC, \u2026) plus the total, with a recent trend. The biggest institutional-demand signal. Keyless (SoSoValue); best-effort, may show empty if the source is unavailable.",
1925
+ capabilities: ["etf-flows"],
1926
+ source: SOURCES.sosovalue,
1927
+ schema: z3.object({
1928
+ asset: z3.enum(["btc", "eth"]).default("btc").describe("Which spot-ETF complex to show."),
1929
+ limit: z3.number().int().min(3).max(15).default(8).describe("How many issuers to list.")
1930
+ })
1931
+ });
1932
+ var trendingCoinsMeta = defineFrameMeta({
1933
+ name: "trending-coins",
1934
+ label: "Trending Coins",
1935
+ category: "crypto",
1936
+ iconUrl: widgetIcon("trending-coins"),
1937
+ layout: { w: 3, h: 4, minW: 2, minH: 3 },
1938
+ description: "The coins with the most search interest right now on CoinGecko \u2014 a retail-attention gauge. Shows rank, price, and 24h change. Keyless (CoinGecko).",
1939
+ capabilities: ["trending-coins"],
1940
+ source: SOURCES.coingecko,
1941
+ schema: z3.object({
1942
+ limit: z3.number().int().min(3).max(15).default(7).describe("How many trending coins to show.")
1943
+ })
1944
+ });
1945
+ var sectorPerformanceMeta = defineFrameMeta({
1946
+ name: "sector-performance",
1947
+ label: "Sector Performance",
1948
+ category: "crypto",
1949
+ iconUrl: widgetIcon("sector-performance"),
1950
+ layout: { w: 4, h: 4, minW: 3, minH: 3 },
1951
+ description: "Crypto sector rotation \u2014 market categories (L1s, DeFi, AI, memes, RWA, \u2026) ranked by 24h market-cap change. Shows where capital is rotating. Keyless (CoinGecko categories).",
1952
+ capabilities: ["sector-performance"],
1953
+ source: SOURCES.coingecko,
1954
+ schema: z3.object({
1955
+ limit: z3.number().int().min(4).max(30).default(10).describe("How many sectors to show.")
1956
+ })
1957
+ });
1958
+ var macroCalendarMeta = defineFrameMeta({
1959
+ name: "macro-calendar",
1960
+ label: "Macro Calendar",
1961
+ category: "macro",
1962
+ iconUrl: widgetIcon("macro-calendar"),
1963
+ layout: { w: 4, h: 4, minW: 3, minH: 2 },
1964
+ description: "Countdown to upcoming scheduled macro events \u2014 defaults to the 2026 FOMC rate decisions, fully editable. No data feed; the dates are known in advance.",
1965
+ capabilities: [],
1966
+ schema: z3.object({
1967
+ limit: z3.number().int().min(1).max(12).default(5).describe("How many upcoming events to show."),
1968
+ events: z3.array(
1969
+ z3.object({
1970
+ date: z3.string().describe("Event date, ISO YYYY-MM-DD."),
1971
+ label: z3.string().describe("Event name, e.g. 'FOMC decision'.")
1972
+ })
1973
+ ).default([
1974
+ { date: "2026-07-29", label: "FOMC decision" },
1975
+ { date: "2026-09-16", label: "FOMC decision" },
1976
+ { date: "2026-10-28", label: "FOMC decision" },
1977
+ { date: "2026-12-09", label: "FOMC decision" },
1978
+ { date: "2027-01-27", label: "FOMC decision" }
1979
+ ]).describe(
1980
+ "Scheduled events (date + label). Defaults to the 2026 FOMC meetings; edit to add CPI/NFP/earnings dates."
1981
+ )
1982
+ })
1983
+ });
1984
+ var stablecoinChainsMeta = defineFrameMeta({
1985
+ name: "stablecoin-chains",
1986
+ label: "Stablecoin Chains",
1987
+ category: "crypto",
1988
+ iconUrl: widgetIcon("stablecoin-chains"),
1989
+ layout: { w: 5, h: 4, minW: 4, minH: 3 },
1990
+ description: "Where stablecoin liquidity sits \u2014 a treemap of the largest chains by stablecoin circulating supply. Complements the Stablecoin Supply total with the cross-chain distribution. Keyless (DeFiLlama).",
1991
+ capabilities: ["stablecoins"],
1992
+ source: SOURCES.defillama,
1993
+ schema: z3.object({
1994
+ limit: z3.number().int().min(4).max(16).default(12).describe("How many chains to show in the treemap.")
1995
+ })
1996
+ });
1997
+ var sectorTreemapMeta = defineFrameMeta({
1998
+ name: "sector-treemap",
1999
+ label: "Sector Treemap",
2000
+ category: "crypto",
2001
+ iconUrl: widgetIcon("sector-treemap"),
2002
+ layout: { w: 6, h: 4, minW: 4, minH: 3 },
2003
+ description: "Crypto sector rotation as a treemap \u2014 each category sized by market cap and colored by 24h change (green up / red down). The at-a-glance view of where capital is flowing. Keyless (CoinGecko categories).",
2004
+ capabilities: ["sector-performance"],
2005
+ source: SOURCES.coingecko,
2006
+ schema: z3.object({
2007
+ limit: z3.number().int().min(6).max(30).default(16).describe("How many sectors to show.")
2008
+ })
2009
+ });
2010
+ var etfFlowsChartMeta = defineFrameMeta({
2011
+ name: "etf-flows-chart",
2012
+ label: "ETF Flows Chart",
2013
+ category: "crypto",
2014
+ iconUrl: widgetIcon("etf-flows-chart"),
2015
+ layout: { w: 6, h: 3, minW: 3, minH: 3 },
2016
+ description: "Spot BTC or ETH ETF daily net flows over time \u2014 the inflow/outflow trend as a line, complementing the per-issuer snapshot. Keyless (SoSoValue); best-effort, may be empty if the source is unavailable.",
2017
+ capabilities: ["etf-flows"],
2018
+ source: SOURCES.sosovalue,
2019
+ schema: z3.object({
2020
+ asset: z3.enum(["btc", "eth"]).default("btc").describe("Which spot-ETF complex to chart."),
2021
+ lookback: z3.enum(["1M", "3M", "6M"]).default("3M").describe("History window for the flow chart.")
2022
+ })
2023
+ });
2024
+ var realizedPriceMeta = defineFrameMeta({
2025
+ name: "realized-price",
2026
+ label: "Realized Price",
2027
+ category: "onchain",
2028
+ iconUrl: widgetIcon("realized-price"),
2029
+ layout: { w: 6, h: 3, minW: 4, minH: 3 },
2030
+ description: "Bitcoin market price vs realized price \u2014 the on-chain cost basis of all coins. Market above realized = aggregate profit; crossing below realized has marked cycle bottoms. Keyless (Coin Metrics).",
2031
+ capabilities: ["onchain-valuation"],
2032
+ source: SOURCES.coinMetrics,
2033
+ schema: z3.object({
2034
+ window: z3.enum(["1Y", "2Y", "4Y", "all"]).default("2Y").describe("How much history the chart shows.")
2035
+ })
2036
+ });
2037
+ var reserveRiskMeta = defineFrameMeta({
2038
+ name: "reserve-risk",
2039
+ label: "Reserve Risk",
2040
+ category: "onchain",
2041
+ iconUrl: widgetIcon("reserve-risk"),
2042
+ layout: { w: 3, h: 3, minW: 2, minH: 2 },
2043
+ description: "Reserve Risk \u2014 long-term-holder conviction relative to price. Low values = strong conviction at a low price (attractive risk/reward, cycle-bottom territory); high values = conviction spent into a high price. Keyless (bitcoin-data.com).",
2044
+ capabilities: ["onchain-cycle-extras"],
2045
+ source: SOURCES.bitcoinData,
2046
+ schema: z3.object({
2047
+ window: z3.enum(["90D", "180D", "1Y"]).default("1Y").describe("How much history the sparkline shows.")
2048
+ })
2049
+ });
1670
2050
  var frameMetas = [
1671
2051
  newsFeedMeta,
1672
2052
  portfolioValueMeta,
@@ -1726,7 +2106,34 @@ var frameMetas = [
1726
2106
  optionsPutCallMeta,
1727
2107
  optionsIvMeta,
1728
2108
  optionsOiStrikeMeta,
1729
- coinMoversMeta
2109
+ coinMoversMeta,
2110
+ mvrvMeta,
2111
+ nuplMeta,
2112
+ soprMeta,
2113
+ puellMultipleMeta,
2114
+ mayerMultipleMeta,
2115
+ piCycleMeta,
2116
+ maMultiplierMeta,
2117
+ rsiMomentumMeta,
2118
+ volumeProfileMeta,
2119
+ dxyMeta,
2120
+ cycleSignalsMeta,
2121
+ stablecoinSupplyMeta,
2122
+ yieldScannerMeta,
2123
+ defiRevenueMeta,
2124
+ fundingComparisonMeta,
2125
+ ethSupplyMeta,
2126
+ ethStakingMeta,
2127
+ predictionMarketsMeta,
2128
+ etfFlowsMeta,
2129
+ trendingCoinsMeta,
2130
+ sectorPerformanceMeta,
2131
+ macroCalendarMeta,
2132
+ stablecoinChainsMeta,
2133
+ sectorTreemapMeta,
2134
+ etfFlowsChartMeta,
2135
+ realizedPriceMeta,
2136
+ reserveRiskMeta
1730
2137
  ];
1731
2138
  var allFrameMetas = [
1732
2139
  ...frameMetas,
@@ -1803,6 +2210,11 @@ function use(args) {
1803
2210
  // src/init.ts
1804
2211
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
1805
2212
  import { dirname, resolve as resolve2 } from "path";
2213
+
2214
+ // ../spec/src/presets.ts
2215
+ var SCENE_DEFAULT_PROJECT_ID = "YrTzGatwjK7EoFpCSfgZ";
2216
+
2217
+ // src/init.ts
1806
2218
  function parseArgs(args) {
1807
2219
  let target = "dashboard.json";
1808
2220
  let title = "my dashboard";
@@ -1847,7 +2259,7 @@ function skeleton(title, author) {
1847
2259
  grid: { columns: 12, rowHeight: 96, gap: 12 },
1848
2260
  background: {
1849
2261
  type: "unicorn",
1850
- projectId: "YrTzGatwjK7EoFpCSfgZ",
2262
+ projectId: SCENE_DEFAULT_PROJECT_ID,
1851
2263
  opacity: 1
1852
2264
  },
1853
2265
  theme: {
@@ -3115,6 +3527,8 @@ var AlternativeMeProvider = class {
3115
3527
  // ../provider-coingecko/src/index.ts
3116
3528
  var GLOBAL_URL = "https://api.coingecko.com/api/v3/global";
3117
3529
  var MARKETS_URL = "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50&page=1&sparkline=false&price_change_percentage=24h";
3530
+ var TRENDING_URL = "https://api.coingecko.com/api/v3/search/trending";
3531
+ var CATEGORIES_URL = "https://api.coingecko.com/api/v3/coins/categories";
3118
3532
  var globalCache = new TtlCache({
3119
3533
  namespace: "zframes:coingecko:global",
3120
3534
  ttlMs: 12 * 6e4,
@@ -3125,12 +3539,55 @@ var marketsCache = new TtlCache({
3125
3539
  ttlMs: 10 * 6e4,
3126
3540
  persist: true
3127
3541
  });
3542
+ var trendingCache = new TtlCache({
3543
+ namespace: "zframes:coingecko:trending",
3544
+ ttlMs: 10 * 6e4,
3545
+ persist: true
3546
+ });
3547
+ var categoriesCache = new TtlCache({
3548
+ namespace: "zframes:coingecko:categories",
3549
+ ttlMs: 12 * 6e4,
3550
+ persist: true
3551
+ });
3128
3552
  var CoinGeckoProvider = class {
3129
3553
  name = "coingecko";
3130
3554
  capabilities = [
3131
3555
  "global-market",
3132
- "coin-markets"
3556
+ "coin-markets",
3557
+ "trending-coins",
3558
+ "sector-performance"
3133
3559
  ];
3560
+ async getTrendingCoins() {
3561
+ return trendingCache.get("trending", async () => {
3562
+ const body = await fetchJson(TRENDING_URL);
3563
+ if (!Array.isArray(body?.coins))
3564
+ throw new Error("coingecko trending: unexpected response shape");
3565
+ return body.coins.map(({ item }) => {
3566
+ const price = Number(item.data?.price);
3567
+ const chg = Number(item.data?.price_change_percentage_24h?.usd);
3568
+ return {
3569
+ id: item.id,
3570
+ name: item.name,
3571
+ symbol: (item.symbol ?? "").toUpperCase(),
3572
+ rank: Number.isFinite(item.market_cap_rank) ? item.market_cap_rank : null,
3573
+ price: Number.isFinite(price) ? price : null,
3574
+ changePct24h: Number.isFinite(chg) ? chg : null
3575
+ };
3576
+ });
3577
+ });
3578
+ }
3579
+ async getSectorPerformance() {
3580
+ return categoriesCache.get("categories", async () => {
3581
+ const body = await fetchJson(CATEGORIES_URL);
3582
+ if (!Array.isArray(body))
3583
+ throw new Error("coingecko categories: unexpected response shape");
3584
+ return body.filter((c) => Number.isFinite(c.market_cap) && (c.market_cap ?? 0) > 0).map((c) => ({
3585
+ name: c.name,
3586
+ marketCap: c.market_cap,
3587
+ changePct24h: Number.isFinite(c.market_cap_change_24h) ? c.market_cap_change_24h : 0
3588
+ })).sort((a, b) => b.marketCap - a.marketCap).slice(0, 30);
3589
+ });
3590
+ }
3134
3591
  async getGlobalMarket() {
3135
3592
  return globalCache.get("global", async () => {
3136
3593
  const body = await fetchJson(GLOBAL_URL);
@@ -3164,6 +3621,9 @@ var CHAINS_URL = "https://api.llama.fi/v2/chains";
3164
3621
  var DEXS_URL = "https://api.llama.fi/overview/dexs";
3165
3622
  var FEES_URL = "https://api.llama.fi/overview/fees";
3166
3623
  var PROTOCOLS_URL = "https://api.llama.fi/protocols";
3624
+ var STABLES_URL = "https://stablecoins.llama.fi/stablecoins?includePrices=true";
3625
+ var STABLECHAINS_URL = "https://stablecoins.llama.fi/stablecoinchains";
3626
+ var YIELDS_URL = "https://yields.llama.fi/pools";
3167
3627
  var SNAPSHOT_TTL_MS = 8 * 6e4;
3168
3628
  var HISTORY_TTL_MS = 30 * 6e4;
3169
3629
  var tvlCache = new TtlCache({
@@ -3190,6 +3650,19 @@ var protocolHistoryCache = new TtlCache({
3190
3650
  namespace: "zframes:defillama:protocol-history",
3191
3651
  ttlMs: HISTORY_TTL_MS
3192
3652
  });
3653
+ var stablecoinsCache = new TtlCache({
3654
+ namespace: "zframes:defillama:stablecoins",
3655
+ ttlMs: 30 * 6e4,
3656
+ persist: true
3657
+ });
3658
+ var yieldsCache = new TtlCache({
3659
+ namespace: "zframes:defillama:yields",
3660
+ ttlMs: 12 * 6e4
3661
+ });
3662
+ var feesOverviewCache = new TtlCache({
3663
+ namespace: "zframes:defillama:fees-overview",
3664
+ ttlMs: SNAPSHOT_TTL_MS
3665
+ });
3193
3666
  var slugKey = (slugs) => [...slugs].sort().join(",");
3194
3667
  function toSeries(chart) {
3195
3668
  if (!Array.isArray(chart)) return [];
@@ -3202,7 +3675,10 @@ var DefiLlamaProvider = class {
3202
3675
  "tvl",
3203
3676
  "dex-volume",
3204
3677
  "protocol-tvl",
3205
- "protocol-fees"
3678
+ "protocol-fees",
3679
+ "stablecoins",
3680
+ "yields",
3681
+ "fees-overview"
3206
3682
  ];
3207
3683
  async getTvlByChain() {
3208
3684
  return tvlCache.get("chains", async () => {
@@ -3287,11 +3763,95 @@ var DefiLlamaProvider = class {
3287
3763
  })).sort((a, b) => b.fees24h - a.fees24h);
3288
3764
  });
3289
3765
  }
3766
+ async getStablecoinSupply() {
3767
+ return stablecoinsCache.get("supply", async () => {
3768
+ const [assetsBody, chains] = await Promise.all([
3769
+ fetchJson(STABLES_URL),
3770
+ fetchJson(STABLECHAINS_URL).catch(() => [])
3771
+ ]);
3772
+ const assets = assetsBody?.peggedAssets;
3773
+ if (!Array.isArray(assets))
3774
+ throw new Error("defillama stablecoins: unexpected response shape");
3775
+ let now = 0;
3776
+ let d1 = 0;
3777
+ let d7 = 0;
3778
+ let d30 = 0;
3779
+ for (const a of assets) {
3780
+ if (a.pegType && a.pegType !== "peggedUSD") continue;
3781
+ now += a.circulating?.peggedUSD ?? 0;
3782
+ d1 += a.circulatingPrevDay?.peggedUSD ?? 0;
3783
+ d7 += a.circulatingPrevWeek?.peggedUSD ?? 0;
3784
+ d30 += a.circulatingPrevMonth?.peggedUSD ?? 0;
3785
+ }
3786
+ if (now <= 0) throw new Error("defillama stablecoins: empty aggregate");
3787
+ const pct = (prev) => prev > 0 ? (now - prev) / prev * 100 : 0;
3788
+ const nowMs = Date.now();
3789
+ const history = [
3790
+ { time: nowMs - 30 * 864e5, value: d30 },
3791
+ { time: nowMs - 7 * 864e5, value: d7 },
3792
+ { time: nowMs - 864e5, value: d1 },
3793
+ { time: nowMs, value: now }
3794
+ ].filter((p) => p.value > 0);
3795
+ const topChains = (Array.isArray(chains) ? chains : []).map((c) => ({
3796
+ name: c.name,
3797
+ usd: c.totalCirculatingUSD?.peggedUSD ?? 0
3798
+ })).filter((c) => c.usd > 0).sort((a, b) => b.usd - a.usd).slice(0, 12);
3799
+ return {
3800
+ totalUsd: now,
3801
+ changePct1d: pct(d1),
3802
+ changePct7d: pct(d7),
3803
+ changePct30d: pct(d30),
3804
+ history,
3805
+ topChains
3806
+ };
3807
+ });
3808
+ }
3809
+ async getYieldPools() {
3810
+ return yieldsCache.get("pools", async () => {
3811
+ const body = await fetchJson(YIELDS_URL);
3812
+ const data = body?.data;
3813
+ if (!Array.isArray(data))
3814
+ throw new Error("defillama yields: unexpected response shape");
3815
+ return data.filter(
3816
+ (p) => Number.isFinite(p.tvlUsd) && (p.tvlUsd ?? 0) > 0 && Number.isFinite(p.apy)
3817
+ ).map((p) => ({
3818
+ pool: p.pool,
3819
+ chain: p.chain,
3820
+ project: p.project,
3821
+ symbol: p.symbol,
3822
+ tvlUsd: p.tvlUsd,
3823
+ apy: p.apy,
3824
+ apyBase: Number.isFinite(p.apyBase) ? p.apyBase : null,
3825
+ apyReward: Number.isFinite(p.apyReward) ? p.apyReward : null,
3826
+ apyPct7D: Number.isFinite(p.apyPct7D) ? p.apyPct7D : null,
3827
+ stablecoin: !!p.stablecoin,
3828
+ ilRisk: p.ilRisk ?? "unknown"
3829
+ })).sort((a, b) => b.tvlUsd - a.tvlUsd).slice(0, 250);
3830
+ });
3831
+ }
3832
+ async getFeesOverview() {
3833
+ return feesOverviewCache.get("overview", async () => {
3834
+ const body = await fetchJson(FEES_URL);
3835
+ if (!body || !Number.isFinite(body.total24h))
3836
+ throw new Error("defillama fees-overview: unexpected response shape");
3837
+ return {
3838
+ total24h: body.total24h,
3839
+ total7d: Number.isFinite(body.total7d) ? body.total7d : null,
3840
+ changePct: Number.isFinite(body.change_1d) ? body.change_1d : null,
3841
+ history: toSeries(body.totalDataChart)
3842
+ };
3843
+ });
3844
+ }
3290
3845
  };
3291
3846
 
3292
3847
  // ../provider-hyperliquid/src/index.ts
3293
3848
  var WS_URL = "wss://api.hyperliquid.xyz/ws";
3294
3849
  var INFO_URL = "https://api.hyperliquid.xyz/info";
3850
+ var VENUE_LABELS = {
3851
+ HlPerp: "Hyperliquid",
3852
+ BinPerp: "Binance",
3853
+ BybitPerp: "Bybit"
3854
+ };
3295
3855
  var dexOf = (symbol) => symbol.includes(":") ? symbol.split(":")[0] : "";
3296
3856
  async function info(body) {
3297
3857
  return fetchJson(INFO_URL, void 0, {
@@ -3320,6 +3880,10 @@ var fundingCache = new TtlCache({
3320
3880
  ttlMs: 4.5 * 6e4,
3321
3881
  persist: true
3322
3882
  });
3883
+ var fundingComparisonCache = new TtlCache({
3884
+ namespace: "zframes:hyperliquid:funding-comparison",
3885
+ ttlMs: 5 * 6e4
3886
+ });
3323
3887
  var sortedKey = (symbols) => symbols ? [...symbols].sort().join(",") : "*";
3324
3888
  var HyperliquidProvider = class {
3325
3889
  name = "hyperliquid";
@@ -3328,8 +3892,48 @@ var HyperliquidProvider = class {
3328
3892
  "day-stats",
3329
3893
  "funding-history",
3330
3894
  "ohlcv",
3331
- "open-interest"
3895
+ "open-interest",
3896
+ "funding-comparison"
3332
3897
  ];
3898
+ async getFundingComparison() {
3899
+ return fundingComparisonCache.get("all", async () => {
3900
+ const resp = await info({
3901
+ type: "predictedFundings"
3902
+ });
3903
+ if (!Array.isArray(resp))
3904
+ throw new Error("hyperliquid predictedFundings: unexpected shape");
3905
+ const out = [];
3906
+ for (const entry of resp) {
3907
+ if (!Array.isArray(entry) || entry.length < 2) continue;
3908
+ const [coin, venueList] = entry;
3909
+ if (typeof coin !== "string" || !Array.isArray(venueList)) continue;
3910
+ const venues = [];
3911
+ for (const vEntry of venueList) {
3912
+ if (!Array.isArray(vEntry) || vEntry.length < 2) continue;
3913
+ const [venue, meta] = vEntry;
3914
+ if (!meta) continue;
3915
+ const rawRate = parseFloat(meta.fundingRate);
3916
+ if (!Number.isFinite(rawRate)) continue;
3917
+ const reported = Number(meta.fundingIntervalHours);
3918
+ const intervalHours = Number.isFinite(reported) && reported > 0 ? reported : venue === "HlPerp" ? 1 : 8;
3919
+ venues.push({
3920
+ venue: VENUE_LABELS[venue] ?? venue,
3921
+ rawRate,
3922
+ intervalHours,
3923
+ annualizedPct: rawRate * (8760 / intervalHours) * 100
3924
+ });
3925
+ }
3926
+ if (venues.length < 2) continue;
3927
+ const rates = venues.map((v) => v.annualizedPct);
3928
+ out.push({
3929
+ coin,
3930
+ venues,
3931
+ spreadPct: Math.max(...rates) - Math.min(...rates)
3932
+ });
3933
+ }
3934
+ return out.sort((a, b) => Math.abs(b.spreadPct) - Math.abs(a.spreadPct)).slice(0, 80);
3935
+ });
3936
+ }
3333
3937
  ws = null;
3334
3938
  listeners = /* @__PURE__ */ new Set();
3335
3939
  reconnectTimer = null;