@oracle-agent/oracle 0.14.1 → 0.16.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 (450) hide show
  1. package/README.md +2 -2
  2. package/SETUP.md +4 -4
  3. package/dist/action-receipts.mjs +1 -0
  4. package/dist/action-semantics.mjs +1 -0
  5. package/dist/address-book.mjs +2 -0
  6. package/dist/bin/desk-server.mjs +60 -0
  7. package/dist/bin/oracle-data-mcp.mjs +9 -0
  8. package/dist/bin/oracle-equities.mjs +20 -0
  9. package/dist/bin/oracle-init.mjs +24 -0
  10. package/dist/bin/oracle-public-server.mjs +5 -0
  11. package/dist/bin/oracle-route.mjs +22 -0
  12. package/dist/bin/oracle-scan.mjs +18 -0
  13. package/dist/bin/oracle-upgrade.mjs +21 -0
  14. package/dist/bin/oracle.mjs +63 -0
  15. package/dist/chains.mjs +1 -0
  16. package/dist/cli/commands/auth.mjs +16 -0
  17. package/dist/cli/commands/bootstrap.mjs +18 -0
  18. package/dist/cli/commands/chain.mjs +21 -0
  19. package/dist/cli/commands/chat.mjs +45 -0
  20. package/dist/cli/commands/credential.mjs +1 -0
  21. package/dist/cli/commands/data-mcp.mjs +2 -0
  22. package/dist/cli/commands/data.mjs +12 -0
  23. package/dist/cli/commands/doctor.mjs +5 -0
  24. package/dist/cli/commands/equities.mjs +15 -0
  25. package/dist/cli/commands/farm.mjs +59 -0
  26. package/dist/cli/commands/fees.mjs +10 -0
  27. package/dist/cli/commands/follow.mjs +28 -0
  28. package/dist/cli/commands/harness.mjs +15 -0
  29. package/dist/cli/commands/help.mjs +1 -0
  30. package/dist/cli/commands/init.mjs +3 -0
  31. package/dist/cli/commands/mcp.mjs +36 -0
  32. package/dist/cli/commands/model.mjs +54 -0
  33. package/dist/cli/commands/plugins.mjs +43 -0
  34. package/dist/cli/commands/prepare.mjs +2 -0
  35. package/dist/cli/commands/public.mjs +3 -0
  36. package/dist/cli/commands/resolve.mjs +23 -0
  37. package/dist/cli/commands/route.mjs +2 -0
  38. package/dist/cli/commands/runner.mjs +1 -0
  39. package/dist/cli/commands/scan.mjs +2 -0
  40. package/dist/cli/commands/setup.mjs +34 -0
  41. package/dist/cli/commands/sign.mjs +4 -0
  42. package/dist/cli/commands/signer.mjs +1 -0
  43. package/dist/cli/commands/strategy.mjs +18 -0
  44. package/dist/cli/commands/swap.mjs +36 -0
  45. package/dist/cli/commands/upgrade.mjs +2 -0
  46. package/dist/cli/commands/vault.mjs +1 -0
  47. package/dist/cli/commands/version.mjs +2 -0
  48. package/dist/data/desk-data.mjs +55 -0
  49. package/dist/data/names.mjs +2 -0
  50. package/dist/data/providers/farming.mjs +2 -0
  51. package/dist/equities/index.mjs +1 -0
  52. package/dist/index.mjs +60 -0
  53. package/dist/nft-gas-war-guard.mjs +1 -0
  54. package/dist/onboarding/harness-configs.mjs +4 -0
  55. package/dist/portfolio-risk.mjs +1 -0
  56. package/dist/prepare-envelope.mjs +1 -0
  57. package/dist/public-api/agent-grants.mjs +3 -0
  58. package/dist/public-control/policy-schema.mjs +1 -0
  59. package/dist/router/index.mjs +2 -0
  60. package/dist/scanner/index.mjs +4 -0
  61. package/dist/signals/index.mjs +1 -0
  62. package/dist/strategy/index.mjs +3 -0
  63. package/dist/watch-preferences.mjs +1 -0
  64. package/package.json +33 -78
  65. package/public/oracle-splash/_variants/ice.html +5 -18
  66. package/public/oracle-splash/_variants/ivory.html +5 -18
  67. package/public/oracle-splash/downloads/index.html +4 -4
  68. package/public/oracle-splash/index.html +113 -34
  69. package/CONTRIBUTING.md +0 -99
  70. package/bin/desk-server.mjs +0 -473
  71. package/bin/oracle-data-mcp.mjs +0 -1252
  72. package/bin/oracle-equities.mjs +0 -168
  73. package/bin/oracle-init.mjs +0 -525
  74. package/bin/oracle-public-server.mjs +0 -36
  75. package/bin/oracle-route.mjs +0 -254
  76. package/bin/oracle-scan.mjs +0 -192
  77. package/bin/oracle-upgrade.mjs +0 -42
  78. package/bin/oracle.mjs +0 -34
  79. package/docs/adding-a-chain.md +0 -229
  80. package/docs/architecture.md +0 -139
  81. package/docs/buzz-integration.md +0 -115
  82. package/docs/cli.md +0 -143
  83. package/docs/connectors.md +0 -13
  84. package/docs/hyperliquid-builder-code.md +0 -50
  85. package/docs/locals-only-fee-waiver.md +0 -34
  86. package/docs/oracle-pack-standard.md +0 -29
  87. package/docs/profiles.md +0 -151
  88. package/docs/public-surface.md +0 -206
  89. package/examples/add-a-chain.mjs +0 -65
  90. package/examples/oracle-pack-template.mjs +0 -38
  91. package/examples/research-a-token.mjs +0 -70
  92. package/plugins/oracle-owner-gate/__init__.py +0 -288
  93. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  94. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  95. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  96. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  97. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  98. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  99. package/scripts/adversarial-bench.mjs +0 -114
  100. package/scripts/build-dist.mjs +0 -119
  101. package/scripts/build-inscription.py +0 -230
  102. package/scripts/check-doc-drift.mjs +0 -123
  103. package/scripts/check-test-count.mjs +0 -105
  104. package/scripts/e2e-hl-markets.mjs +0 -21
  105. package/scripts/e2e-hl-perps.mjs +0 -48
  106. package/scripts/e2e-hypercore-staking.mjs +0 -128
  107. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  108. package/scripts/guard-publish.mjs +0 -22
  109. package/scripts/protocol-template-gate.mjs +0 -15
  110. package/scripts/public-api-scan.mjs +0 -23
  111. package/scripts/publish-dist.mjs +0 -67
  112. package/scripts/record-hero-cli.sh +0 -80
  113. package/scripts/secret-scan.mjs +0 -169
  114. package/scripts/smoke-dist-bins.mjs +0 -89
  115. package/scripts/verify-dist.mjs +0 -29
  116. package/scripts/verify-v3-venues.mjs +0 -233
  117. package/skins/oracle.yaml +0 -56
  118. package/src/action-receipts.mjs +0 -265
  119. package/src/action-semantics.mjs +0 -62
  120. package/src/address-book.mjs +0 -208
  121. package/src/agent-auth.mjs +0 -206
  122. package/src/approval-guard.mjs +0 -282
  123. package/src/attestation-secret.mjs +0 -94
  124. package/src/audit-log.mjs +0 -196
  125. package/src/auth/oauth.mjs +0 -672
  126. package/src/auto-slippage.mjs +0 -378
  127. package/src/capability-posture.mjs +0 -125
  128. package/src/cards.mjs +0 -422
  129. package/src/chains.mjs +0 -62
  130. package/src/cli/chain-catalog.mjs +0 -215
  131. package/src/cli/chain-state.mjs +0 -74
  132. package/src/cli/commands/auth.mjs +0 -193
  133. package/src/cli/commands/bootstrap.mjs +0 -87
  134. package/src/cli/commands/chain.mjs +0 -143
  135. package/src/cli/commands/chat.mjs +0 -465
  136. package/src/cli/commands/credential.mjs +0 -9
  137. package/src/cli/commands/data-mcp.mjs +0 -18
  138. package/src/cli/commands/data.mjs +0 -75
  139. package/src/cli/commands/doctor.mjs +0 -136
  140. package/src/cli/commands/equities.mjs +0 -41
  141. package/src/cli/commands/farm.mjs +0 -129
  142. package/src/cli/commands/fees.mjs +0 -109
  143. package/src/cli/commands/follow.mjs +0 -130
  144. package/src/cli/commands/harness.mjs +0 -63
  145. package/src/cli/commands/help.mjs +0 -7
  146. package/src/cli/commands/init.mjs +0 -27
  147. package/src/cli/commands/mcp.mjs +0 -154
  148. package/src/cli/commands/model.mjs +0 -106
  149. package/src/cli/commands/plugins.mjs +0 -275
  150. package/src/cli/commands/prepare.mjs +0 -12
  151. package/src/cli/commands/public.mjs +0 -20
  152. package/src/cli/commands/resolve.mjs +0 -64
  153. package/src/cli/commands/route.mjs +0 -12
  154. package/src/cli/commands/runner.mjs +0 -9
  155. package/src/cli/commands/scan.mjs +0 -12
  156. package/src/cli/commands/setup.mjs +0 -294
  157. package/src/cli/commands/sign.mjs +0 -21
  158. package/src/cli/commands/signer.mjs +0 -9
  159. package/src/cli/commands/swap.mjs +0 -102
  160. package/src/cli/commands/upgrade.mjs +0 -12
  161. package/src/cli/commands/vault.mjs +0 -9
  162. package/src/cli/commands/version.mjs +0 -22
  163. package/src/cli/first-run.mjs +0 -23
  164. package/src/cli/kernel.mjs +0 -262
  165. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  166. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  167. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  168. package/src/cli/mcp-targets/codex.mjs +0 -41
  169. package/src/cli/mcp-targets/cursor.mjs +0 -32
  170. package/src/cli/mcp-targets/shared.mjs +0 -71
  171. package/src/cli/mcp-targets/vscode.mjs +0 -39
  172. package/src/cli/messaging-platforms.mjs +0 -217
  173. package/src/cli/model-config.mjs +0 -78
  174. package/src/cli/operator-dispatch.mjs +0 -194
  175. package/src/cli/oracle-harness.py +0 -415
  176. package/src/cli/paths.mjs +0 -107
  177. package/src/cli/runtime.mjs +0 -351
  178. package/src/cli/setup-state.mjs +0 -168
  179. package/src/cli/spawn-child.mjs +0 -43
  180. package/src/data/catalog.mjs +0 -858
  181. package/src/data/desk-data.mjs +0 -877
  182. package/src/data/http.mjs +0 -253
  183. package/src/data/names.mjs +0 -188
  184. package/src/data/provider-endpoint.mjs +0 -94
  185. package/src/data/providers/aave-v3.mjs +0 -139
  186. package/src/data/providers/across-bridge.mjs +0 -41
  187. package/src/data/providers/aerodrome.mjs +0 -245
  188. package/src/data/providers/aevo.mjs +0 -33
  189. package/src/data/providers/approval-indexer.mjs +0 -133
  190. package/src/data/providers/approvals.mjs +0 -594
  191. package/src/data/providers/babylon-staking.mjs +0 -149
  192. package/src/data/providers/balancer.mjs +0 -209
  193. package/src/data/providers/beefy-yields.mjs +0 -45
  194. package/src/data/providers/birdeye-tokens.mjs +0 -33
  195. package/src/data/providers/bisq-markets.mjs +0 -145
  196. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  197. package/src/data/providers/bitcoin-meta.mjs +0 -378
  198. package/src/data/providers/blockscout.mjs +0 -14
  199. package/src/data/providers/bob-rootstock.mjs +0 -198
  200. package/src/data/providers/braiins-insights.mjs +0 -103
  201. package/src/data/providers/bridge-aggregator.mjs +0 -259
  202. package/src/data/providers/bridges.mjs +0 -242
  203. package/src/data/providers/bungee.mjs +0 -29
  204. package/src/data/providers/celestia-da.mjs +0 -38
  205. package/src/data/providers/changenow.mjs +0 -135
  206. package/src/data/providers/compound.mjs +0 -32
  207. package/src/data/providers/connext.mjs +0 -28
  208. package/src/data/providers/convex.mjs +0 -30
  209. package/src/data/providers/cow-protocol.mjs +0 -110
  210. package/src/data/providers/cowswap.mjs +0 -415
  211. package/src/data/providers/curve.mjs +0 -201
  212. package/src/data/providers/das-assets.mjs +0 -59
  213. package/src/data/providers/debridge.mjs +0 -109
  214. package/src/data/providers/defillama.mjs +0 -88
  215. package/src/data/providers/dexscreener.mjs +0 -43
  216. package/src/data/providers/drift.mjs +0 -32
  217. package/src/data/providers/dydx.mjs +0 -41
  218. package/src/data/providers/evm-rpc.mjs +0 -225
  219. package/src/data/providers/farming.mjs +0 -291
  220. package/src/data/providers/geckoterminal.mjs +0 -34
  221. package/src/data/providers/gmx.mjs +0 -496
  222. package/src/data/providers/hiro-stacks.mjs +0 -150
  223. package/src/data/providers/hl-assets.mjs +0 -165
  224. package/src/data/providers/hl-info.mjs +0 -108
  225. package/src/data/providers/hl-markets.mjs +0 -210
  226. package/src/data/providers/hl-outcome.mjs +0 -61
  227. package/src/data/providers/hl-perps.mjs +0 -419
  228. package/src/data/providers/hl-staking.mjs +0 -353
  229. package/src/data/providers/hl-ws.mjs +0 -119
  230. package/src/data/providers/hyperevm-dex.mjs +0 -49
  231. package/src/data/providers/jito-mev.mjs +0 -117
  232. package/src/data/providers/jupiter-venues.mjs +0 -119
  233. package/src/data/providers/jupiter.mjs +0 -315
  234. package/src/data/providers/kamino-strategies.mjs +0 -143
  235. package/src/data/providers/l2beat-tvl.mjs +0 -42
  236. package/src/data/providers/lifi.mjs +0 -166
  237. package/src/data/providers/liquid-esplora.mjs +0 -152
  238. package/src/data/providers/magiceden-ordinals.mjs +0 -141
  239. package/src/data/providers/magiceden-sol.mjs +0 -406
  240. package/src/data/providers/mempool-lightning.mjs +0 -144
  241. package/src/data/providers/mempool-mining.mjs +0 -142
  242. package/src/data/providers/meteora-dlmm.mjs +0 -168
  243. package/src/data/providers/morpho.mjs +0 -177
  244. package/src/data/providers/nft-gallery.mjs +0 -163
  245. package/src/data/providers/nft-portfolio.mjs +0 -494
  246. package/src/data/providers/odos.mjs +0 -156
  247. package/src/data/providers/ondo.mjs +0 -31
  248. package/src/data/providers/oneinch.mjs +0 -174
  249. package/src/data/providers/opensea-multichain.mjs +0 -136
  250. package/src/data/providers/opensea-nft.mjs +0 -371
  251. package/src/data/providers/orca.mjs +0 -29
  252. package/src/data/providers/ordinals-runes.mjs +0 -180
  253. package/src/data/providers/pancakeswap.mjs +0 -28
  254. package/src/data/providers/paraswap.mjs +0 -125
  255. package/src/data/providers/pendle.mjs +0 -188
  256. package/src/data/providers/poly-clob.mjs +0 -283
  257. package/src/data/providers/poly-public.mjs +0 -96
  258. package/src/data/providers/poly-ws.mjs +0 -103
  259. package/src/data/providers/polygon-staking.mjs +0 -227
  260. package/src/data/providers/portfolio-history.mjs +0 -394
  261. package/src/data/providers/portfolio.mjs +0 -600
  262. package/src/data/providers/pyth-price-feeds.mjs +0 -172
  263. package/src/data/providers/raydium.mjs +0 -35
  264. package/src/data/providers/relayscan-mev.mjs +0 -72
  265. package/src/data/providers/rfq.mjs +0 -15
  266. package/src/data/providers/rh-agent.mjs +0 -59
  267. package/src/data/providers/sanctum-lst.mjs +0 -180
  268. package/src/data/providers/satflow.mjs +0 -341
  269. package/src/data/providers/signed-material-guard.mjs +0 -108
  270. package/src/data/providers/solana-rpc.mjs +0 -197
  271. package/src/data/providers/solend-lending.mjs +0 -166
  272. package/src/data/providers/spark-lend.mjs +0 -42
  273. package/src/data/providers/squid-router.mjs +0 -29
  274. package/src/data/providers/stargate.mjs +0 -29
  275. package/src/data/providers/sushiswap.mjs +0 -30
  276. package/src/data/providers/symbiotic-restaking.mjs +0 -41
  277. package/src/data/providers/thorchain.mjs +0 -36
  278. package/src/data/providers/traderjoe.mjs +0 -28
  279. package/src/data/providers/twap.mjs +0 -152
  280. package/src/data/providers/uniswap-v3.mjs +0 -457
  281. package/src/data/providers/uniswap-v4.mjs +0 -414
  282. package/src/data/providers/vertex.mjs +0 -41
  283. package/src/data/providers/wallet-watch.mjs +0 -264
  284. package/src/data/providers/wormhole.mjs +0 -28
  285. package/src/data/providers/yearn.mjs +0 -31
  286. package/src/data/providers/zerox.mjs +0 -167
  287. package/src/data/public-api-scan.mjs +0 -61
  288. package/src/data/quote-placeholder.mjs +0 -31
  289. package/src/desk/swap-prepare.mjs +0 -194
  290. package/src/equities/bridge.mjs +0 -388
  291. package/src/equities/fixtures/bridge_routes.json +0 -159
  292. package/src/equities/fixtures/dst_transitions.json +0 -29
  293. package/src/equities/fixtures/equity_dex_pools.json +0 -154
  294. package/src/equities/fixtures/hip3_l2books.json +0 -2711
  295. package/src/equities/fixtures/nyse_holidays.json +0 -1
  296. package/src/equities/fixtures/oracles.json +0 -100
  297. package/src/equities/fixtures/rh_pool_state.json +0 -244
  298. package/src/equities/fixtures/solana_xstocks.json +0 -704
  299. package/src/equities/fixtures/ton_xstocks.json +0 -35
  300. package/src/equities/fixtures/universe.json +0 -411
  301. package/src/equities/fixtures/venues.json +0 -3542
  302. package/src/equities/fixtures.mjs +0 -405
  303. package/src/equities/funding.mjs +0 -142
  304. package/src/equities/index.mjs +0 -166
  305. package/src/equities/liveness.mjs +0 -148
  306. package/src/equities/marketHours.mjs +0 -249
  307. package/src/equities/normalize.mjs +0 -295
  308. package/src/equities/num.mjs +0 -146
  309. package/src/equities/prepare.mjs +0 -95
  310. package/src/equities/rank.mjs +0 -260
  311. package/src/equities/sourceNum.mjs +0 -69
  312. package/src/equities/types.mjs +0 -220
  313. package/src/equities/venues/arcus-perp.mjs +0 -84
  314. package/src/equities/venues/arcus-spot.mjs +0 -105
  315. package/src/equities/venues/hyperliquid-hip3.mjs +0 -224
  316. package/src/equities/venues/rh-uniswap.mjs +0 -216
  317. package/src/equities/venues/solana-xstocks.mjs +0 -139
  318. package/src/equities/venues/ton-stonfi.mjs +0 -139
  319. package/src/exact-integer.mjs +0 -72
  320. package/src/exec-policy.mjs +0 -419
  321. package/src/flags.mjs +0 -15
  322. package/src/fresh-window.mjs +0 -76
  323. package/src/gmx-attestation.mjs +0 -176
  324. package/src/index.mjs +0 -107
  325. package/src/licensing/locals-only.mjs +0 -25
  326. package/src/nft-gas-war-guard.mjs +0 -139
  327. package/src/onboarding/agent-keys.mjs +0 -161
  328. package/src/onboarding/harness-configs.mjs +0 -102
  329. package/src/onboarding/index.mjs +0 -18
  330. package/src/onboarding/tiers.mjs +0 -139
  331. package/src/oracle-env.mjs +0 -55
  332. package/src/package-manifest.mjs +0 -42
  333. package/src/plugins/agent-plugin-loader.mjs +0 -225
  334. package/src/portfolio-risk.mjs +0 -170
  335. package/src/prepare-envelope.mjs +0 -204
  336. package/src/profile-upgrade.mjs +0 -277
  337. package/src/protocol-execution.mjs +0 -84
  338. package/src/protocol-templates/gate.mjs +0 -179
  339. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  340. package/src/public-api/agent-grants.mjs +0 -57
  341. package/src/public-api/buzz-integration.mjs +0 -267
  342. package/src/public-api/connect-agent.mjs +0 -424
  343. package/src/public-api/grants.mjs +0 -142
  344. package/src/public-api/http.mjs +0 -707
  345. package/src/public-api/metering.mjs +0 -111
  346. package/src/public-control/aa-adapter.mjs +0 -402
  347. package/src/public-control/build-registry.mjs +0 -227
  348. package/src/public-control/bundler-client.mjs +0 -357
  349. package/src/public-control/grant-indexer.mjs +0 -296
  350. package/src/public-control/policy-render.mjs +0 -69
  351. package/src/public-control/policy-schema.mjs +0 -322
  352. package/src/public-control/runtime-config.mjs +0 -275
  353. package/src/public-control/session-key-model.mjs +0 -379
  354. package/src/public-control/session-orchestrator.mjs +0 -418
  355. package/src/rfq/intent.mjs +0 -180
  356. package/src/rfq/sources.mjs +0 -181
  357. package/src/route-attestation.mjs +0 -132
  358. package/src/router/best-execution.mjs +0 -326
  359. package/src/router/index.mjs +0 -250
  360. package/src/router/integrator-fee.mjs +0 -135
  361. package/src/router/prepare-bridge.mjs +0 -293
  362. package/src/router/prepare-route.mjs +0 -398
  363. package/src/router/proposal.mjs +0 -311
  364. package/src/router/risk-classifier.mjs +0 -119
  365. package/src/router/route-sources.mjs +0 -364
  366. package/src/scanner/chains.config.mjs +0 -543
  367. package/src/scanner/contract.mjs +0 -270
  368. package/src/scanner/evm-scanner.mjs +0 -394
  369. package/src/scanner/index.mjs +0 -9
  370. package/src/scanner/v2-venue.mjs +0 -351
  371. package/src/scanner/v3-venue.mjs +0 -308
  372. package/src/scopes.mjs +0 -44
  373. package/src/sell-simulation.mjs +0 -167
  374. package/src/signals/engine.mjs +0 -146
  375. package/src/signals/index.mjs +0 -1
  376. package/src/token-transfer-guard.mjs +0 -188
  377. package/src/tui/app.mjs +0 -438
  378. package/src/tui/backend.mjs +0 -215
  379. package/src/tui/format.mjs +0 -272
  380. package/src/tui/gateway-client.mjs +0 -177
  381. package/src/tui/input.mjs +0 -501
  382. package/src/tui/memory.mjs +0 -105
  383. package/src/tui/meta-learn.mjs +0 -85
  384. package/src/tui/renderer.mjs +0 -443
  385. package/src/tui/scheduler.mjs +0 -205
  386. package/src/tui/skills-loader.mjs +0 -140
  387. package/src/tui/standalone-client.mjs +0 -752
  388. package/src/tui/theme.mjs +0 -81
  389. package/src/vault-attestation.mjs +0 -146
  390. package/src/venues.mjs +0 -206
  391. package/src/watch-preferences.mjs +0 -85
  392. /package/{profiles → dist/assets/profiles}/_template/SOUL.md +0 -0
  393. /package/{profiles → dist/assets/profiles}/_template/profile.json +0 -0
  394. /package/{profiles → dist/assets/profiles}/bitcoin-agent/SOUL.md +0 -0
  395. /package/{profiles → dist/assets/profiles}/bitcoin-agent/profile.json +0 -0
  396. /package/{profiles → dist/assets/profiles}/hyperliquid-agent/SOUL.md +0 -0
  397. /package/{profiles → dist/assets/profiles}/hyperliquid-agent/profile.json +0 -0
  398. /package/{profiles → dist/assets/profiles}/oracle/SOUL.md +0 -0
  399. /package/{profiles → dist/assets/profiles}/oracle/profile.json +0 -0
  400. /package/{profiles → dist/assets/profiles}/polymarket-agent/SOUL.md +0 -0
  401. /package/{profiles → dist/assets/profiles}/polymarket-agent/profile.json +0 -0
  402. /package/{profiles → dist/assets/profiles}/profile.schema.json +0 -0
  403. /package/{profiles → dist/assets/profiles}/protocol-builder/SOUL.md +0 -0
  404. /package/{profiles → dist/assets/profiles}/protocol-builder/profile.json +0 -0
  405. /package/{profiles → dist/assets/profiles}/robinhood-agent/SOUL.md +0 -0
  406. /package/{profiles → dist/assets/profiles}/robinhood-agent/profile.json +0 -0
  407. /package/{profiles → dist/assets/profiles}/solana-agent/SOUL.md +0 -0
  408. /package/{profiles → dist/assets/profiles}/solana-agent/profile.json +0 -0
  409. /package/{profiles → dist/assets/profiles}/stable-agent/SOUL.md +0 -0
  410. /package/{profiles → dist/assets/profiles}/stable-agent/profile.json +0 -0
  411. /package/{skills → dist/assets/skills}/balance/SKILL.md +0 -0
  412. /package/{skills → dist/assets/skills}/bitcoin-l1.md +0 -0
  413. /package/{skills → dist/assets/skills}/chain-defi-ecosystem-profiling.md +0 -0
  414. /package/{skills → dist/assets/skills}/evm-contract-research.md +0 -0
  415. /package/{skills → dist/assets/skills}/hyperliquid.md +0 -0
  416. /package/{skills → dist/assets/skills}/multichain-exec-desk.md +0 -0
  417. /package/{skills → dist/assets/skills}/oracle-action-semantics/SKILL.md +0 -0
  418. /package/{skills → dist/assets/skills}/oracle-best-execution/SKILL.md +0 -0
  419. /package/{skills → dist/assets/skills}/oracle-best-execution.md +0 -0
  420. /package/{skills → dist/assets/skills}/oracle-bitcoin/SKILL.md +0 -0
  421. /package/{skills → dist/assets/skills}/oracle-chain-graphs-telegram-cards/SKILL.md +0 -0
  422. /package/{skills → dist/assets/skills}/oracle-chat/SKILL.md +0 -0
  423. /package/{skills → dist/assets/skills}/oracle-chat/chain.SKILL.md +0 -0
  424. /package/{skills → dist/assets/skills}/oracle-chat/setup.SKILL.md +0 -0
  425. /package/{skills → dist/assets/skills}/oracle-circuit-breaker/SKILL.md +0 -0
  426. /package/{skills → dist/assets/skills}/oracle-contract-research/SKILL.md +0 -0
  427. /package/{skills → dist/assets/skills}/oracle-desk/SKILL.md +0 -0
  428. /package/{skills → dist/assets/skills}/oracle-desk.md +0 -0
  429. /package/{skills → dist/assets/skills}/oracle-dex-launch/SKILL.md +0 -0
  430. /package/{skills → dist/assets/skills}/oracle-equities/SKILL.md +0 -0
  431. /package/{skills → dist/assets/skills}/oracle-grants/SKILL.md +0 -0
  432. /package/{skills → dist/assets/skills}/oracle-hypercore-staking/SKILL.md +0 -0
  433. /package/{skills → dist/assets/skills}/oracle-hyperliquid/SKILL.md +0 -0
  434. /package/{skills → dist/assets/skills}/oracle-meme-token-sniper/SKILL.md +0 -0
  435. /package/{skills → dist/assets/skills}/oracle-multichain-nft-launch/SKILL.md +0 -0
  436. /package/{skills → dist/assets/skills}/oracle-multichain-token-launch/SKILL.md +0 -0
  437. /package/{skills → dist/assets/skills}/oracle-nft-gacha-launch/SKILL.md +0 -0
  438. /package/{skills → dist/assets/skills}/oracle-nft-mint-gas-war/SKILL.md +0 -0
  439. /package/{skills → dist/assets/skills}/oracle-polymarket/SKILL.md +0 -0
  440. /package/{skills → dist/assets/skills}/oracle-protocol-builder/SKILL.md +0 -0
  441. /package/{skills → dist/assets/skills}/oracle-protocol-security/SKILL.md +0 -0
  442. /package/{skills → dist/assets/skills}/oracle-public-product/SKILL.md +0 -0
  443. /package/{skills → dist/assets/skills}/oracle-receipts/SKILL.md +0 -0
  444. /package/{skills → dist/assets/skills}/oracle-receipts.md +0 -0
  445. /package/{skills → dist/assets/skills}/oracle-rfq-tokenized-assets/SKILL.md +0 -0
  446. /package/{skills → dist/assets/skills}/oracle-smart-wallet-scanner/SKILL.md +0 -0
  447. /package/{skills → dist/assets/skills}/oracle-solana/SKILL.md +0 -0
  448. /package/{skills → dist/assets/skills}/oracle-solana-nft/SKILL.md +0 -0
  449. /package/{skills → dist/assets/skills}/oracle-token-research/SKILL.md +0 -0
  450. /package/{skills → dist/assets/skills}/solana.md +0 -0
@@ -0,0 +1,3 @@
1
+ import{createHash as Ur}from"node:crypto";var Lt=1,Ze=/^[a-z0-9][a-z0-9._-]{0,63}$/,We=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,Cr=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),qr=new Set(["open","high","low","close","volume","fundingRate","openInterest"]),Br=new Set(["sma","ema","rsi","macd","bollinger","atr"]),Dr=new Set(["gt","gte","lt","lte","eq"]),zr=new Set(["and","or","not"]),Vr=new Set(["above","below"]),Jr=new Set(["line","signal","histogram"]),Kr=new Set(["upper","middle","lower"]),Xt=new Set(["compare","logic","cross"]),qe=new Set(["version","id","name","venue","market","parameters","nodes","rules","risk"]),Yr=new Set(["coin","interval"]),Be=new Set(["value","min","max","step"]),Zt=new Set(["entryLong","entryShort","exitLong","exitShort"]),De=new Set(["maxLeverage","maxNotionalUsd","positionSizePct","stopLossPct","takeProfitPct","cooldownBars","maxDailyLossPct","expiresAt"]),Gr=new Set(["id","type"]),ze={input:new Set(["id","type","field"]),constant:new Set(["id","type","value"]),indicator:new Set(["id","type","indicator","input","period","fastPeriod","slowPeriod","signalPeriod","stdDev","output"]),compare:new Set(["id","type","op","left","right"]),logic:new Set(["id","type","op","inputs"]),cross:new Set(["id","type","direction","left","right"])},Ve=16,Je=128,Ke=100,Ye=32,ut=class extends Error{constructor(e){let r=e.map(n=>`${n.path}: ${n.message}`);super(`invalid strategy (${e.length} error${e.length===1?"":"s"}): ${r.join("; ")}`),this.name="StrategyValidationError",this.errors=e}};function K(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function U(t){return typeof t=="number"&&Number.isFinite(t)}function Ge(t){return Number.isInteger(t)&&t>0}function Qt(t){if(t==null||typeof t!="object"||Object.isFrozen(t))return t;if(Array.isArray(t)){for(let e of t)Qt(e);return Object.freeze(t)}for(let e of Object.keys(t))Qt(t[e]);return Object.freeze(t)}function te(t){if(Array.isArray(t))return t.map(te);if(t!=null&&typeof t=="object"){let e={};for(let r of Object.keys(t).sort())e[r]=te(t[r]);return e}return t}function y(t,e,r){t.push({path:e,message:r})}function nt(t,e,r,n){for(let o of Object.keys(t))e.has(o)||y(n,r?`${r}.${o}`:o,"unknown field is not allowed")}function Qe(t,e,r,n){if(!U(t)||!U(e)||!U(r)||!U(n)||n<=0||t<e||t>r)return!1;let o=(t-e)/n;if(!Number.isFinite(o))return!1;let s=Math.round(o);return Math.abs(o-s)<=1e-9}function Wt(t,e,r,n){if(K(t)){if(nt(t,new Set(["param"]),e,n),typeof t.param!="string"||!t.param)return y(n,`${e}.param`,"must be a parameter name string"),null;if(!Object.prototype.hasOwnProperty.call(r,t.param))return y(n,`${e}.param`,`unknown parameter "${t.param}"`),null;let o=r[t.param];return!K(o)||![o.value,o.min,o.max,o.step].every(Ge)?(y(n,`${e}.param`,"referenced period parameter value min max and step must be positive integers"),null):{param:t.param}}return Ge(t)?t:(y(n,e,"must be a positive integer or {param}"),null)}function Xe(t,e,r,n){return K(t)?(nt(t,new Set(["param"]),e,n),typeof t.param!="string"||!t.param?(y(n,`${e}.param`,"must be a parameter name string"),null):Object.prototype.hasOwnProperty.call(r,t.param)?{param:t.param}:(y(n,`${e}.param`,`unknown parameter "${t.param}"`),null)):U(t)?t:(y(n,e,"must be a finite number or {param}"),null)}function Ft(t){switch(t.type){case"input":case"constant":return[];case"indicator":return t.input?[t.input]:[];case"compare":case"cross":return[t.left,t.right].filter(Boolean);case"logic":return Array.isArray(t.inputs)?[...t.inputs]:[];default:return[]}}function Xr(t){let e=new Map,r=n=>{let o=e.get(n)||0;if(o===1)return!0;if(o===2)return!1;e.set(n,1);let s=t.get(n);if(s){for(let a of Ft(s))if(t.has(a)&&r(a))return!0}return e.set(n,2),!1};for(let n of t.keys())if(r(n))return!0;return!1}function Zr(t,e){if(!K(t))return y(e,"parameters","must be a plain object"),null;let r=Object.keys(t);if(r.length>Ve)return y(e,"parameters",`too many parameters (max ${Ve})`),null;let n={};for(let o of r){if(!Ze.test(o)){y(e,`parameters.${o}`,"parameter name is malformed");continue}let s=t[o],a=`parameters.${o}`;if(!K(s)){y(e,a,"must be a plain object");continue}nt(s,Be,a,e);for(let c of Be)c in s||y(e,`${a}.${c}`,"required field is missing");let{value:i,min:l,max:f,step:u}=s;U(l)||y(e,`${a}.min`,"must be a finite number"),U(f)||y(e,`${a}.max`,"must be a finite number"),(!U(u)||u<=0)&&y(e,`${a}.step`,"must be a positive finite number"),U(i)||y(e,`${a}.value`,"must be a finite number"),U(l)&&U(f)&&l>f&&y(e,`${a}.min`,"min must be <= max"),U(i)&&U(l)&&U(f)&&U(u)&&u>0&&(Qe(i,l,f,u)||y(e,`${a}.value`,"value must lie on the declared min/max/step grid")),n[o]={value:i,min:l,max:f,step:u}}return n}function Wr(t,e,r,n){let o=`nodes.${e}`;if(!K(t))return y(n,o,"must be a plain object"),null;if(typeof t.type!="string"||!ze[t.type])return y(n,`${o}.type`,"unknown or missing node type"),nt(t,Gr,o,n),null;switch(nt(t,ze[t.type],o,n),(typeof t.id!="string"||!We.test(t.id))&&y(n,`${o}.id`,"must be a 1-64 char id starting with alphanumeric"),t.type){case"input":return(typeof t.field!="string"||!qr.has(t.field))&&y(n,`${o}.field`,"must be one of open|high|low|close|volume|fundingRate|openInterest"),{id:t.id,type:"input",field:t.field};case"constant":{let s=Xe(t.value,`${o}.value`,r,n);return{id:t.id,type:"constant",value:s}}case"indicator":{(typeof t.indicator!="string"||!Br.has(t.indicator))&&y(n,`${o}.indicator`,"must be one of sma|ema|rsi|macd|bollinger|atr");let s=t.indicator,a={id:t.id,type:"indicator",indicator:s};if(s==="atr"){"input"in t&&(typeof t.input!="string"||!t.input?y(n,`${o}.input`,"must be a node id string when provided"):a.input=t.input);let i=Wt(t.period,`${o}.period`,r,n);i!=null&&(a.period=i)}else typeof t.input!="string"||!t.input?y(n,`${o}.input`,"must be a node id string"):a.input=t.input;if((s==="sma"||s==="ema"||s==="rsi"||s==="bollinger"||s==="atr")&&("period"in t,s!=="macd"))if(!("period"in t))y(n,`${o}.period`,"required field is missing");else{let i=Wt(t.period,`${o}.period`,r,n);i!=null&&(a.period=i)}if(s==="macd"){for(let i of["fastPeriod","slowPeriod","signalPeriod"])if(!(i in t))y(n,`${o}.${i}`,"required field is missing");else{let l=Wt(t[i],`${o}.${i}`,r,n);l!=null&&(a[i]=l)}"output"in t?Jr.has(t.output)?a.output=t.output:y(n,`${o}.output`,"must be line|signal|histogram"):y(n,`${o}.output`,"required field is missing"),"period"in t&&y(n,`${o}.period`,"forbidden for macd"),"stdDev"in t&&y(n,`${o}.stdDev`,"forbidden for macd")}else if(s==="bollinger"){if(!("stdDev"in t))y(n,`${o}.stdDev`,"required field is missing");else{let i=Xe(t.stdDev,`${o}.stdDev`,r,n);i!=null&&(typeof i=="number"&&i<=0?y(n,`${o}.stdDev`,"must be > 0"):a.stdDev=i)}"output"in t?Kr.has(t.output)?a.output=t.output:y(n,`${o}.output`,"must be upper|middle|lower"):y(n,`${o}.output`,"required field is missing");for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in t&&y(n,`${o}.${i}`,`forbidden for ${s}`)}else{"output"in t&&y(n,`${o}.output`,`forbidden for ${s}`),"stdDev"in t&&s!=="bollinger"&&y(n,`${o}.stdDev`,`forbidden for ${s}`);for(let i of["fastPeriod","slowPeriod","signalPeriod"])i in t&&y(n,`${o}.${i}`,`forbidden for ${s}`)}return a}case"compare":return(typeof t.op!="string"||!Dr.has(t.op))&&y(n,`${o}.op`,"must be gt|gte|lt|lte|eq"),(typeof t.left!="string"||!t.left)&&y(n,`${o}.left`,"must be a node id"),(typeof t.right!="string"||!t.right)&&y(n,`${o}.right`,"must be a node id"),{id:t.id,type:"compare",op:t.op,left:t.left,right:t.right};case"logic":{if((typeof t.op!="string"||!zr.has(t.op))&&y(n,`${o}.op`,"must be and|or|not"),!Array.isArray(t.inputs))return y(n,`${o}.inputs`,"must be an array of node ids"),{id:t.id,type:"logic",op:t.op,inputs:[]};let s=[];for(let a=0;a<t.inputs.length;a++){let i=t.inputs[a];typeof i!="string"||!i?y(n,`${o}.inputs.${a}`,"must be a node id"):s.push(i)}return t.op==="not"?s.length!==1&&y(n,`${o}.inputs`,"not requires exactly one input"):(t.op==="and"||t.op==="or")&&s.length<2&&y(n,`${o}.inputs`,`${t.op} requires at least two inputs`),{id:t.id,type:"logic",op:t.op,inputs:s}}case"cross":return(typeof t.direction!="string"||!Vr.has(t.direction))&&y(n,`${o}.direction`,"must be above|below"),(typeof t.left!="string"||!t.left)&&y(n,`${o}.left`,"must be a node id"),(typeof t.right!="string"||!t.right)&&y(n,`${o}.right`,"must be a node id"),{id:t.id,type:"cross",direction:t.direction,left:t.left,right:t.right};default:return null}}function Qr(t,e,r){if(!K(t))return y(e,"risk","must be a plain object"),null;nt(t,De,"risk",e);for(let d of De)(!(d in t)||t[d]==null)&&y(e,`risk.${d}`,"required field is missing");let n={},o=t.maxLeverage;!U(o)||o<=0||o>50?y(e,"risk.maxLeverage","must be a number > 0 and <= 50"):n.maxLeverage=o;let s=t.maxNotionalUsd;!U(s)||s<=0?y(e,"risk.maxNotionalUsd","must be a number > 0"):n.maxNotionalUsd=s;let a=t.positionSizePct;!U(a)||a<=0||a>100?y(e,"risk.positionSizePct","must be a number > 0 and <= 100"):n.positionSizePct=a;let i=t.stopLossPct;!U(i)||i<=0||i>100?y(e,"risk.stopLossPct","must be a number > 0 and <= 100"):n.stopLossPct=i;let l=t.takeProfitPct;!U(l)||l<=0||l>1e3?y(e,"risk.takeProfitPct","must be a number > 0 and <= 1000"):n.takeProfitPct=l;let f=t.cooldownBars;!Number.isInteger(f)||f<0||f>1e5?y(e,"risk.cooldownBars","must be an integer >= 0 and <= 100000"):n.cooldownBars=f;let u=t.maxDailyLossPct;!U(u)||u<=0||u>100?y(e,"risk.maxDailyLossPct","must be a number > 0 and <= 100"):n.maxDailyLossPct=u;let c=t.expiresAt;return!Number.isInteger(c)||c<=0?y(e,"risk.expiresAt","must be an integer epoch milliseconds > 0"):(r.nowMs!==void 0&&(Number.isInteger(r.nowMs)?c<=r.nowMs&&y(e,"risk.expiresAt","must be strictly greater than nowMs"):y(e,"nowMs","must be an integer epoch milliseconds")),n.expiresAt=c),n}function Ht(t,e={}){let r=[];if(!K(t))return y(r,"","strategy must be a plain object"),{ok:!1,errors:r,strategy:null};nt(t,qe,"",r);for(let u of qe)(!(u in t)||t[u]==null)&&y(r,u,"required field is missing");t.version!==Lt&&y(r,"version",`must be ${Lt}`),(typeof t.id!="string"||!Ze.test(t.id))&&y(r,"id","must match /^[a-z0-9][a-z0-9._-]{0,63}$/"),(typeof t.name!="string"||t.name.length===0||t.name.length>Ke)&&y(r,"name",`must be a non-empty string max ${Ke}`),t.venue!=="hyperliquid"&&y(r,"venue",'must be "hyperliquid"');let n=null;K(t.market)?(nt(t.market,Yr,"market",r),(typeof t.market.coin!="string"||t.market.coin.length===0||t.market.coin.length>Ye)&&y(r,"market.coin",`must be a non-empty string max ${Ye}`),(typeof t.market.interval!="string"||!Cr.has(t.market.interval))&&y(r,"market.interval","must be a supported interval"),n={coin:t.market.coin,interval:t.market.interval}):y(r,"market","must be a plain object");let o=Zr(t.parameters,r),s=null,a=new Map;if(!Array.isArray(t.nodes))y(r,"nodes","must be an array");else if(t.nodes.length>Je)y(r,"nodes",`too many nodes (max ${Je})`);else{s=[];for(let u=0;u<t.nodes.length;u++){let c=Wr(t.nodes[u],u,o||{},r);c&&(typeof c.id=="string"&&We.test(c.id)&&(a.has(c.id)?y(r,`nodes.${u}.id`,`duplicate node id "${c.id}"`):a.set(c.id,c)),s.push(c))}for(let u=0;u<s.length;u++){let c=s[u],d=`nodes.${u}`;for(let m of Ft(c))a.has(m)||y(r,d,`unknown node ref "${m}"`);if(c.type==="indicator"||c.type==="compare"||c.type==="cross")for(let m of Ft(c)){let p=a.get(m);p&&Xt.has(p.type)&&y(r,d,`node ref "${m}" must be numeric`)}if(c.type==="logic")for(let m of Ft(c)){let p=a.get(m);p&&!Xt.has(p.type)&&y(r,d,`node ref "${m}" must be boolean`)}}Xr(a)&&y(r,"nodes","graph contains a cycle")}let i=null;if(!K(t.rules))y(r,"rules","must be a plain object");else{nt(t.rules,Zt,"rules",r);for(let u of Zt)u in t.rules||y(r,`rules.${u}`,"required field is missing");i={};for(let u of Zt){let c=t.rules[u];if(c===null){i[u]=null;continue}if(typeof c!="string"||!c){y(r,`rules.${u}`,"must be a node id or null"),i[u]=c;continue}if(!a.has(c)){y(r,`rules.${u}`,`unknown node ref "${c}"`),i[u]=c;continue}let d=a.get(c);Xt.has(d.type)||y(r,`rules.${u}`,`rule must reference a boolean node, not ${d.type}`),i[u]=c}}let l=Qr(t.risk,r,e);if(r.length)return{ok:!1,errors:r,strategy:null};let f=Qt({version:Lt,id:t.id,name:t.name,venue:"hyperliquid",market:n,parameters:o,nodes:s,rules:i,risk:l});return{ok:!0,errors:[],strategy:f}}function z(t,e={}){let r=Ht(t,e);if(!r.ok)throw new ut(r.errors);return r.strategy}function tr(t){let e=z(t);return JSON.stringify(te(e))}function ft(t){let e=tr(t);return Ur("sha256").update(e,"utf8").digest("hex")}function mt(t,e){if(!K(t))throw new ut([{path:"",message:"strategy must be a plain object"}]);if(!K(e))throw new ut([{path:"overrides",message:"must be a plain object"}]);let r=z(t),n={};for(let[s,a]of Object.entries(r.parameters))n[s]={value:a.value,min:a.min,max:a.max,step:a.step};let o=[];for(let[s,a]of Object.entries(e)){if(!Object.prototype.hasOwnProperty.call(n,s)){y(o,s,`unknown parameter "${s}"`);continue}let i=n[s];if(!U(a)){y(o,s,"override must be a finite number");continue}if(!Qe(a,i.min,i.max,i.step)){y(o,s,"override must lie on the declared min/max/step grid");continue}n[s]={...i,value:a}}if(o.length)throw new ut(o);return z({version:r.version,id:r.id,name:r.name,venue:r.venue,market:{coin:r.market.coin,interval:r.market.interval},parameters:n,nodes:r.nodes.map(s=>{let a={...s};return Array.isArray(s.inputs)&&(a.inputs=[...s.inputs]),a}),rules:{...r.rules},risk:{...r.risk}})}function Pt(t){if(!Array.isArray(t))throw new TypeError("values must be an array");for(let e=0;e<t.length;e++){let r=t[e];if(typeof r!="number"||!Number.isFinite(r))throw new TypeError(`values[${e}] must be a finite number`)}}function ct(t){if(!Number.isInteger(t)||t<=0)throw new TypeError("period must be a positive integer")}function tn(t){if(!Array.isArray(t))throw new TypeError("bars must be an array");for(let e=0;e<t.length;e++){let r=t[e];if(r==null||typeof r!="object")throw new TypeError(`bars[${e}] must be an object`);for(let n of["o","h","l","c"]){let o=r[n];if(typeof o!="number"||!Number.isFinite(o))throw new TypeError(`bars[${e}].${n} must be a finite number`)}if(r.h<r.l)throw new TypeError(`bars[${e}] high must be >= low`)}}function ee(t,e){Pt(t),ct(e);let r=new Array(t.length).fill(null);if(t.length<e)return r;let n=0;for(let o=0;o<t.length;o++)n+=t[o],o>=e&&(n-=t[o-e]),o>=e-1&&(r[o]=n/e);return r}function At(t,e){Pt(t),ct(e);let r=new Array(t.length).fill(null);if(t.length<e)return r;let n=0;for(let a=0;a<e;a++)n+=t[a];let o=n/e;r[e-1]=o;let s=2/(e+1);for(let a=e;a<t.length;a++)o=s*t[a]+(1-s)*o,r[a]=o;return r}function re(t,e){Pt(t),ct(e);let r=new Array(t.length).fill(null);if(t.length<=e)return r;let n=0,o=0;for(let i=1;i<=e;i++){let l=t[i]-t[i-1];l>=0?n+=l:o-=l}let s=n/e,a=o/e;r[e]=er(s,a);for(let i=e+1;i<t.length;i++){let l=t[i]-t[i-1],f=l>0?l:0,u=l<0?-l:0;s=(s*(e-1)+f)/e,a=(a*(e-1)+u)/e,r[i]=er(s,a)}return r}function er(t,e){return t===0&&e===0?50:e===0?100:t===0?0:100-100/(1+t/e)}function ne(t,e={}){Pt(t);let r=e.fastPeriod,n=e.slowPeriod,o=e.signalPeriod;if(ct(r),ct(n),ct(o),r>=n)throw new TypeError("fastPeriod must be < slowPeriod");let s=At(t,r),a=At(t,n),i=new Array(t.length).fill(null);for(let c=0;c<t.length;c++)s[c]!=null&&a[c]!=null&&(i[c]=s[c]-a[c]);let l=new Array(t.length).fill(null),f=new Array(t.length).fill(null),u=[];for(let c=0;c<i.length;c++)i[c]!=null&&u.push(c);if(u.length>=o){let c=0;for(let b=0;b<o;b++)c+=i[u[b]];let d=c/o,m=u[o-1];l[m]=d,f[m]=i[m]-d;let p=2/(o+1);for(let b=o;b<u.length;b++){let E=u[b];d=p*i[E]+(1-p)*d,l[E]=d,f[E]=i[E]-d}}return{line:i,signal:l,histogram:f}}function oe(t,e={}){Pt(t);let r=e.period,n=e.stdDev;if(ct(r),typeof n!="number"||!Number.isFinite(n)||n<=0)throw new TypeError("stdDev must be a finite number > 0");let o=new Array(t.length).fill(null),s=new Array(t.length).fill(null),a=new Array(t.length).fill(null);if(t.length<r)return{upper:s,middle:o,lower:a};let i=0,l=0;for(let f=0;f<t.length;f++){let u=t[f];if(i+=u,l+=u*u,f>=r){let c=t[f-r];i-=c,l-=c*c}if(f>=r-1){let c=i/r,d=l/r-c*c;d<0&&d>-1e-12&&(d=0);let m=Math.sqrt(d);o[f]=c,s[f]=c+n*m,a[f]=c-n*m}}return{upper:s,middle:o,lower:a}}function ie(t,e){tn(t),ct(e);let r=new Array(t.length).fill(null);if(t.length<e)return r;let n=new Array(t.length);for(let a=0;a<t.length;a++){let i=t[a];if(a===0)n[a]=i.h-i.l;else{let l=t[a-1].c;n[a]=Math.max(i.h-i.l,Math.abs(i.h-l),Math.abs(i.l-l))}}let o=0;for(let a=0;a<e;a++)o+=n[a];let s=o/e;r[e-1]=s;for(let a=e;a<t.length;a++)s=(s*(e-1)+n[a])/e,r[a]=s;return r}import{createHash as en}from"node:crypto";var rn=new Set([408,425,429,500,502,503,504]),rr=new Set(["GET","HEAD","OPTIONS","PUT","DELETE"]),nn=2,nr=4e3,ir=["authorization","x-api-key","x-tensor-api-key","0x-api-key","api-key","cookie","proxy-authorization"],on=new Set([301,302,303,307,308]),or=3;function sn(t){let e=String(t||"").toLowerCase();return ir.includes(e)||/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(e)}function an(t){let e={};for(let[r,n]of Object.entries(t||{}))sn(r)||(e[r]=n);return e}function cn(t,e){if(!t)throw new Error(`HTTP redirect from ${e} missing Location`);let r=new URL(String(t),String(e));if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`HTTP redirect from ${e} used unsupported protocol ${r.protocol}`);return r.toString()}function ln(t,e){return new URL(String(t)).origin===new URL(String(e)).origin}var se=new Map;function un(t,e,r){let n={};for(let[l,f]of Object.entries(r||{}))n[l.toLowerCase()]=f;let o=Object.keys(n).filter(l=>/(^|-)(api[-_]?key|key|token|secret|auth|authorization|session|cookie|signature|access)(-|$)/.test(l)),a=[...new Set([...ir,...o])].sort().map(l=>`${l}=${n[l]??""}`).join(`
2
+ `),i=en("sha256").update(a).digest("hex").slice(0,32);return`${t} ${e} ${i}`}function fn(t,e){let r=Number(e);return Number.isFinite(r)&&r>0?Math.min(r*1e3,nr):Math.min(250*2**t,nr)+Math.floor(Math.random()*100)}var dn=t=>new Promise(e=>setTimeout(e,t));async function pn(t,{fetchImpl:e,method:r,headers:n,body:o,timeoutMs:s}){let a=new AbortController,i=setTimeout(()=>a.abort(),s);try{let l=String(t),f={...n||{}};for(let u=0;u<=or;u+=1){let c=await e(l,{method:r,headers:f,body:o,signal:a.signal,redirect:"manual"}),d=await c.text(),m=null;if(d)try{m=JSON.parse(d)}catch{m=null}if(on.has(c.status)){if(r!=="GET"&&r!=="HEAD"){let b=new Error(`HTTP ${c.status} ${r} ${l} redirected non-idempotent request`);throw b.status=c.status,b.body=m??d.slice(0,300),b}if(u===or)throw new Error(`HTTP redirect loop for ${t}`);let p=cn(c.headers?.get?.("location"),l);ln(p,l)||(f=an(f)),l=p;continue}if(!c.ok){let p=new Error(`HTTP ${c.status} ${r} ${l}`);throw p.status=c.status,p.retryAfter=c.headers?.get?.("retry-after")??null,p.body=m??d.slice(0,300),p}return m??d}throw new Error(`HTTP redirect loop for ${t}`)}finally{clearTimeout(i)}}async function sr(t,e={}){let r=e.fetchImpl||globalThis.fetch;if(typeof r!="function")throw new Error("fetch unavailable \u2014 pass opts.fetchImpl");let n=e.timeoutMs??12e3,o=(e.method||"GET").toUpperCase(),s={Accept:"application/json",...e.headers||{}},a=e.body;a!=null&&typeof a!="string"&&(s["Content-Type"]=s["Content-Type"]||"application/json",a=JSON.stringify(a));let i=Number.isInteger(e.retries)?Math.max(e.retries,0):nn,l=async()=>{let m;for(let p=0;p<=i;p++)try{return await pn(t,{fetchImpl:r,method:o,headers:s,body:a,timeoutMs:n})}catch(b){m=b;let E=b?.status,k=b?.name==="AbortError",P=new Set([408,425,429]),T=E!=null?P.has(E)||rn.has(E)&&rr.has(o):!k&&rr.has(o);if(p===i||!T)throw b;await dn(fn(p,b?.retryAfter))}throw m};if(!(e.dedupe!==!1&&o==="GET"&&a==null))return l();let u=un(o,t,s),c=se.get(u);if(c)return c;let d=l().finally(()=>se.delete(u));return se.set(u,d),d}var mn="https://api.hyperliquid.xyz/info",hn="https://api.hyperliquid-testnet.xyz/info";function yn({testnet:t,baseUrl:e}={}){if(e)return e.replace(/\/$/,"").endsWith("/info")?e:`${e.replace(/\/$/,"")}/info`;if(process.env.HL_INFO_URL)return process.env.HL_INFO_URL;if(process.env.HL_API_URL){let r=process.env.HL_API_URL.replace(/\/$/,"");return r.endsWith("/info")?r:`${r}/info`}return t||process.env.HL_TESTNET==="1"?hn:mn}async function ar(t,e={}){if(!t||!t.type)throw new Error("hlInfo requires body.type");let r=yn(e);return sr(r,{method:"POST",body:t,fetchImpl:e.fetchImpl,timeoutMs:e.timeoutMs})}async function cr({coin:t,interval:e="1h",startTime:r,endTime:n},o={}){if(!t)throw new Error("hlCandleSnapshot requires coin");let s={type:"candleSnapshot",req:{coin:String(t),interval:e,startTime:r??Date.now()-24*3600*1e3,endTime:n??Date.now()}};return ar(s,o)}async function lr({coin:t,startTime:e,endTime:r},n={}){if(!t)throw new Error("hlFundingHistory requires coin");return ar({type:"fundingHistory",coin:String(t),startTime:e??Date.now()-24*3600*1e3,endTime:r??Date.now()},n)}var wn=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function ht(t,e){let r=Number(t);if(!Number.isFinite(r))throw new TypeError(`${e} must be finite`);return r}function yt(t,e){if(!Number.isSafeInteger(t)||t<0)throw new TypeError(`${e} must be a non-negative safe integer`);return t}function $t(t){if(Array.isArray(t))for(let e of t)$t(e);else if(t&&typeof t=="object")for(let e of Object.values(t))$t(e);return Object.freeze(t)}function ur(t){let e=wn[t];if(!e)throw new TypeError(`unsupported strategy interval: ${t}`);return e}function fr(t,{endTime:e=Number.MAX_SAFE_INTEGER}={}){if(!Array.isArray(t))throw new TypeError("Hyperliquid candles must be an array");yt(e,"endTime");let r=new Map;for(let n=0;n<t.length;n++){let o=t[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`candles[${n}] must be an object`);let s=yt(Number(o.t),`candles[${n}].t`);if(yt(Number(o.T),`candles[${n}].T`)>e)continue;let i={t:s,o:ht(o.o,`candles[${n}].o`),h:ht(o.h,`candles[${n}].h`),l:ht(o.l,`candles[${n}].l`),c:ht(o.c,`candles[${n}].c`),v:ht(o.v,`candles[${n}].v`)};if(i.h<Math.max(i.o,i.c,i.l))throw new TypeError(`candles[${n}].h is below another price`);if(i.l>Math.min(i.o,i.c,i.h))throw new TypeError(`candles[${n}].l is above another price`);if(i.v<0)throw new TypeError(`candles[${n}].v must be non-negative`);let l=r.get(s);if(l&&JSON.stringify(l)!==JSON.stringify(i))throw new TypeError(`conflicting duplicate candle at timestamp ${s}`);l||r.set(s,i)}return $t([...r.values()].sort((n,o)=>n.t-o.t))}function gn(t,e){if(!Array.isArray(t))throw new TypeError("Hyperliquid funding history must be an array");let r=new Map;for(let n=0;n<t.length;n++){let o=t[n];if(!o||typeof o!="object"||Array.isArray(o))throw new TypeError(`funding[${n}] must be an object`);let s=yt(Number(o.time),`funding[${n}].time`);s>e||r.set(s,{time:s,fundingRate:ht(o.fundingRate,`funding[${n}].fundingRate`)})}return[...r.values()].sort((n,o)=>n.time-o.time)}async function bn({coin:t,startTime:e,endTime:r},n){let o=[],s=Math.max(0,e-288e5),a=!1;for(let i=0;i<16&&s<=r;i++){let l=await lr({coin:t,startTime:s,endTime:r},n);if(!Array.isArray(l))throw new TypeError("Hyperliquid funding history must be an array");o.push(...l);let f=s;for(let u of l){let c=Number(u?.time);Number.isSafeInteger(c)&&c>f&&(f=c)}if(l.length<500||f>=r){a=!0;break}if(f<=s)throw new Error("Hyperliquid funding history pagination did not advance");s=f+1}if(!a)throw new Error("strategy history exceeds the bounded funding history limit");return gn(o,r)}function En(t,e,r){let n=0,o=null;return t.map(s=>{let a=s.t+r,i=0;for(;n<e.length&&e[n].time<a;){let l=e[n];o=l.fundingRate,l.time>=s.t&&(i+=l.fundingRate),n+=1}return o==null?{...s,fundingPaymentRate:i}:{...s,fundingRate:o,fundingPaymentRate:i}})}async function ae(t,e={}){if(!t||typeof t!="object"||Array.isArray(t))throw new TypeError("strategy history input must be an object");let r=String(t.coin||"").trim().toUpperCase();if(!/^[A-Z0-9][A-Z0-9._-]{0,11}$/.test(r))throw new TypeError("coin must be an uppercase Hyperliquid asset id");let n=String(t.interval||"15m"),o=ur(n);if(t.endTime==null)throw new TypeError("endTime is required for deterministic history");let s=yt(t.endTime,"endTime"),a=t.count==null?1500:t.count;if(!Number.isInteger(a)||a<20||a>5e3)throw new TypeError("count must be an integer from 20 to 5000");let i=t.startTime==null?Math.max(0,s-a*o):yt(t.startTime,"startTime");if(i>=s)throw new TypeError("startTime must be before endTime");let[l,f]=await Promise.all([cr({coin:r,interval:n,startTime:i,endTime:s},e),bn({coin:r,startTime:i,endTime:s},e)]),u=fr(l,{endTime:s}),c=$t(En(u,f,o));return $t({coin:r,interval:n,range:{startTime:i,endTime:s},bars:c})}import{createHash as xn}from"node:crypto";var ce=2,Sn="93f9c998260e73756c13871dc1a84dd6cdb26ec6113bd1941f023519939db440",kn="68f5b412a9975f04024cf9b9b6209b4bccedd52f176e95f34f786b3f53479c6a",An="d2d75085cb3ab02724cd173abfa2bcad99cd7966a69bcaf80312f13e5b7aaa50",dr=xn("sha256").update(JSON.stringify({version:ce,compilerSourceHash:Sn,indicatorsSourceHash:kn,schemaSourceHash:An})).digest("hex");var gt=ce,lt=dr,Pn=Object.freeze({open:"o",high:"h",low:"l",close:"c",volume:"v",fundingRate:"fundingRate",openInterest:"openInterest"}),$n=Object.freeze({"1m":6e4,"3m":18e4,"5m":3e5,"15m":9e5,"30m":18e5,"1h":36e5,"2h":72e5,"4h":144e5,"8h":288e5,"12h":432e5,"1d":864e5});function Y(t){return typeof t=="number"&&Number.isFinite(t)}function Tn(t){let e=new Map(t.map(i=>[i.id,i])),r=i=>{switch(i.type){case"indicator":return i.input?[i.input]:[];case"compare":case"cross":return[i.left,i.right];case"logic":return[...i.inputs];default:return[]}},n=new Map,o=new Map;for(let i of t)n.set(i.id,0),o.set(i.id,[]);for(let i of t)for(let l of r(i))e.has(l)&&(o.get(l).push(i.id),n.set(i.id,n.get(i.id)+1));let s=[];for(let[i,l]of n)l===0&&s.push(i);let a=[];for(;s.length;){let i=s.shift();a.push(i);for(let l of o.get(i))n.set(l,n.get(l)-1),n.get(l)===0&&s.push(l)}if(a.length!==t.length)throw new Error("strategy graph is cyclic");return a}function wt(t,e){return t!=null&&typeof t=="object"&&"param"in t?e[t.param].value:t}function _n(t,e,r){if(!Array.isArray(t)||t.length===0)throw new TypeError("bars must be a non-empty array");if(!Number.isInteger(e)||e<0||e>=t.length)throw new RangeError("index out of range");let n=null;for(let o=0;o<=e;o++){let s=t[o];if(s==null||typeof s!="object"||Array.isArray(s))throw new TypeError(`bars[${o}] must be an object`);let{t:a,o:i,h:l,l:f,c:u,v:c}=s;if(!Y(a)&&(typeof a=="number"&&Number.isFinite(a)),!Number.isFinite(a))throw new TypeError(`bars[${o}].t must be finite`);for(let[d,m]of[["o",i],["h",l],["l",f],["c",u],["v",c]])if(!Y(m))throw new TypeError(`bars[${o}].${d} must be a finite number`);for(let[d,m]of[["o",i],["h",l],["l",f],["c",u]])if(!(m>0))throw new TypeError(`bars[${o}].${d} price must be positive`);if(c<0)throw new TypeError(`bars[${o}].v volume must be non-negative`);if(l<Math.max(i,u,f))throw new TypeError(`bars[${o}] high must be >= max(open, close, low)`);if(f>Math.min(i,u,l))throw new TypeError(`bars[${o}] low must be <= min(open, close, high)`);if(n!=null){if(!(a>n))throw new TypeError("bars t must be strictly increasing");if(a-n!==$n[r])throw new TypeError(`bars t must match ${r} cadence`)}if(n=a,"fundingRate"in s&&s.fundingRate!=null&&!Y(s.fundingRate))throw new TypeError(`bars[${o}].fundingRate must be finite when present`);if("openInterest"in s&&s.openInterest!=null){if(!Y(s.openInterest))throw new TypeError(`bars[${o}].openInterest must be finite when present`);if(s.openInterest<0)throw new TypeError(`bars[${o}].openInterest must be non-negative`)}}}function dt(t,e,r,n,o,s){if(s.has(t))return s.get(t);let a=e.get(t),i;switch(a.type){case"input":{let l=Pn[a.field];i=new Array(o+1);for(let f=0;f<=o;f++){let u=n[f][l];i[f]=u===void 0?null:u}break}case"constant":{let l=wt(a.value,r);i=new Array(o+1).fill(l);break}case"indicator":{let l=a.period!=null?wt(a.period,r):void 0;if(a.indicator==="atr"){let c=[];for(let d=0;d<=o;d++){let m=n[d];c.push({o:m.o,h:m.h,l:m.l,c:m.c})}i=ie(c,l);break}let u=dt(a.input,e,r,n,o,s).map((c,d)=>{if(c==null||!Y(c))throw new TypeError(`indicator input ${a.input} has non-finite value at ${d}`);return c});if(a.indicator==="sma")i=ee(u,l);else if(a.indicator==="ema")i=At(u,l);else if(a.indicator==="rsi")i=re(u,l);else if(a.indicator==="macd")i=ne(u,{fastPeriod:wt(a.fastPeriod,r),slowPeriod:wt(a.slowPeriod,r),signalPeriod:wt(a.signalPeriod,r)})[a.output];else if(a.indicator==="bollinger")i=oe(u,{period:l,stdDev:wt(a.stdDev,r)})[a.output];else throw new Error(`unsupported indicator ${a.indicator}`);break}case"compare":{let l=dt(a.left,e,r,n,o,s),f=dt(a.right,e,r,n,o,s);i=new Array(o+1);for(let u=0;u<=o;u++){let c=l[u],d=f[u];if(c==null||d==null||!Y(c)||!Y(d)){i[u]=!1;continue}switch(a.op){case"gt":i[u]=c>d;break;case"gte":i[u]=c>=d;break;case"lt":i[u]=c<d;break;case"lte":i[u]=c<=d;break;case"eq":i[u]=c===d;break;default:i[u]=!1}}break}case"logic":{let l=a.inputs.map(f=>dt(f,e,r,n,o,s));i=new Array(o+1);for(let f=0;f<=o;f++)if(a.op==="not"){let u=l[0][f];i[f]=u===!0?!1:u===!1}else if(a.op==="and"){let u=!0;for(let c of l)if(c[f]!==!0){u=!1;break}i[f]=u}else if(a.op==="or"){let u=!1;for(let c of l)if(c[f]===!0){u=!0;break}i[f]=u}else i[f]=!1;break}case"cross":{let l=dt(a.left,e,r,n,o,s),f=dt(a.right,e,r,n,o,s);i=new Array(o+1),i[0]=!1;for(let u=1;u<=o;u++){let c=l[u-1],d=f[u-1],m=l[u],p=f[u];if(c==null||d==null||m==null||p==null||!Y(c)||!Y(d)||!Y(m)||!Y(p)){i[u]=!1;continue}a.direction==="above"?i[u]=c<=d&&m>p:i[u]=c>=d&&m<p}break}default:throw new Error(`unknown node type ${a.type}`)}return s.set(t,i),i}function V(t,e={}){let r=z(t);e&&Object.keys(e).length&&(r=mt(r,e));let n=new Map(r.nodes.map(m=>[m.id,m])),o=Object.freeze(Tn(r.nodes)),s=r.parameters,a=new Set(r.nodes.filter(m=>m.type==="input").map(m=>m.field));if(r.nodes.some(m=>m.type==="indicator"&&m.indicator==="atr"))for(let m of["open","high","low","close"])a.add(m);let i=Object.freeze([...a].sort()),l=ft(r);function f(m,p){let b={};for(let k of o){let P=m.get(k);b[k]=P[p]}let E=k=>k!=null&&b[k]===!0;return{values:b,signals:{entryLong:E(r.rules.entryLong),entryShort:E(r.rules.entryShort),exitLong:E(r.rules.exitLong),exitShort:E(r.rules.exitShort)}}}function u(m,p){_n(m,p,r.market.interval);let b=new Map;for(let E of o)dt(E,n,s,m,p,b);return b}function c(m,p){return f(u(m,p),p)}function d(m){if(!Array.isArray(m)||m.length===0)throw new TypeError("bars must be a non-empty array");let p=m.length-1,b=u(m,p);return Object.freeze(m.map((E,k)=>Object.freeze(f(b,k))))}return Object.freeze({strategy:r,strategyHash:l,compilerVersion:gt,compilerHash:lt,requiredSeries:i,nodeOrder:o,evaluate:c,evaluateAll:d})}import{createHash as In}from"node:crypto";var On=Object.freeze({initialEquityUsd:1e4,takerFeeBps:3.5,builderFeeBps:2,slippageBps:2,latencyBars:1,maxVolumeParticipationPct:100});function Nn(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function Q(t){return typeof t=="number"&&Number.isFinite(t)}function le(t){if(t==null||typeof t!="object"||Object.isFrozen(t))return t;if(Array.isArray(t)){for(let e of t)le(e);return Object.freeze(t)}for(let e of Object.keys(t))le(t[e]);return Object.freeze(t)}function jt(t){if(Array.isArray(t))return t.map(jt);if(t!=null&&typeof t=="object"){let e={};for(let r of Object.keys(t).sort())e[r]=jt(t[r]);return e}return t}function ue(t,e="result"){if(typeof t=="number"){if(!Number.isFinite(t))throw new Error(`non-finite backtest result at ${e}`);return}if(!(t==null||typeof t!="object")){if(Array.isArray(t)){t.forEach((r,n)=>ue(r,`${e}[${n}]`));return}for(let[r,n]of Object.entries(t))ue(n,`${e}.${r}`)}}function mr(t){if(!Array.isArray(t)||t.length===0)throw new TypeError("bars must be a non-empty array");let e=null;for(let r=0;r<t.length;r++){let n=t[r];if(n==null||typeof n!="object"||Array.isArray(n))throw new TypeError(`bars[${r}] must be an object`);let{t:o,o:s,h:a,l:i,c:l,v:f}=n;if(!Q(o))throw new TypeError(`bars[${r}].t must be finite`);for(let[u,c]of[["o",s],["h",a],["l",i],["c",l],["v",f]])if(!Q(c))throw new TypeError(`bars[${r}].${u} must be a finite number`);for(let[u,c]of[["o",s],["h",a],["l",i],["c",l]])if(!(c>0))throw new TypeError(`bars[${r}].${u} price must be positive`);if(f<0)throw new TypeError(`bars[${r}].v volume must be non-negative`);if(a<Math.max(s,l,i))throw new TypeError(`bars[${r}] high must be >= max(open, close, low)`);if(i>Math.min(s,l,a))throw new TypeError(`bars[${r}] low must be <= min(open, close, high)`);if(e!=null&&!(o>e))throw new TypeError("bars t must be strictly increasing");if(e=o,"fundingRate"in n&&n.fundingRate!=null&&!Q(n.fundingRate))throw new TypeError(`bars[${r}].fundingRate must be finite when present`);if("fundingPaymentRate"in n&&n.fundingPaymentRate!=null&&!Q(n.fundingPaymentRate))throw new TypeError(`bars[${r}].fundingPaymentRate must be finite when present`);if("openInterest"in n&&n.openInterest!=null&&!Q(n.openInterest))throw new TypeError(`bars[${r}].openInterest must be finite when present`)}}function Tt(t){if(!Array.isArray(t))throw new TypeError("bars must be an array");return t.length>0&&mr(t),In("sha256").update(JSON.stringify(jt(t)),"utf8").digest("hex")}function Rn(t){if(t==null&&(t={}),!Nn(t))throw new TypeError("options must be a plain object");let e={...On},r=new Set(["initialEquityUsd","takerFeeBps","builderFeeBps","slippageBps","latencyBars","maxVolumeParticipationPct","nowMs"]);for(let n of Object.keys(t))if(!r.has(n))throw new TypeError(`unknown option "${n}"`);if("initialEquityUsd"in t){if(!Q(t.initialEquityUsd)||t.initialEquityUsd<=0)throw new TypeError("initialEquityUsd must be a positive finite number");e.initialEquityUsd=t.initialEquityUsd}for(let n of["takerFeeBps","builderFeeBps","slippageBps"])if(n in t){let o=t[n];if(!Q(o)||o<0)throw new TypeError(`${n} must be a finite number >= 0`);if(n==="slippageBps"?o>=1e4:o>1e4)throw new TypeError(`${n} exceeds its safe basis-point bound`);e[n]=o}if("latencyBars"in t){let n=t.latencyBars;if(!Number.isInteger(n)||n<1)throw new TypeError("latencyBars must be an integer >= 1");e.latencyBars=n}if("maxVolumeParticipationPct"in t){let n=t.maxVolumeParticipationPct;if(!Q(n)||n<=0||n>100)throw new TypeError("maxVolumeParticipationPct must be in (0,100]");e.maxVolumeParticipationPct=n}if("nowMs"in t){if(!Number.isInteger(t.nowMs))throw new TypeError("nowMs must be an integer epoch milliseconds");e.nowMs=t.nowMs}return e}function Ut(t){return t/1e4}function Mn(t,e,r){let n=Ut(r);return e==="long"?t*(1+n):t*(1-n)}function vn(t,e,r){let n=Ut(r);return e==="long"?t*(1-n):t*(1+n)}function pr(t,e,r){let n=Math.abs(t)*Ut(e),o=Math.abs(t)*Ut(r);return{taker:n,builder:o,total:n+o}}function Ln(t,e){let r=t*(e.positionSizePct/100)*e.maxLeverage;return Math.min(r,e.maxNotionalUsd)}function Fn(t,e,r){let n=r/100;return e==="long"?t*(1-n):t*(1+n)}function Hn(t,e,r){let n=r/100;return e==="long"?t*(1+n):t*(1-n)}function jn(t,e,r,n){if(!(r>0))return e==="long"?0:Number.POSITIVE_INFINITY;let o=Math.min(.99,1/(2*r)+n/1e4);return e==="long"?t*(1-1/r)/(1-o):t*(1+1/r)/(1+o)}function Un(t,e,r){return e==="long"?t.l<=r:t.h>=r}function Cn(t,e,r){return e==="long"?t.h>=r:t.l<=r}function qn(t,e,r){return e==="long"?t.l<=r:t.h>=r}function _t(t,e){for(let r of t.requiredSeries)if(["fundingRate","openInterest"].includes(r)&&!e.every(n=>Q(n?.[r])))throw new Error(`strategy required series is absent: ${r}`)}function Bn(t){if(t.length<3)return 0;let e=[];for(let a=1;a<t.length;a++){let i=t[a-1].equity,l=t[a].equity;i>0&&e.push((l-i)/i)}if(e.length<2)return 0;let r=0;for(let a of e)r+=a;let n=r/e.length,o=0;for(let a of e)o+=(a-n)**2;let s=Math.sqrt(o/(e.length-1));return s>0?n/s:0}function Dn(t){let e=-1/0,r=0;for(let n of t){let o=n.equity;if(o>e&&(e=o),e>0){let s=(e-o)/e*100;s>r&&(r=s)}}return r}function ot(t,e,r={}){let n=Rn(r);mr(e);let o=Tt(e);n.nowMs!==void 0&&z(t,{nowMs:n.nowMs});let s=V(t);if(_t(s,e),n.nowMs!==void 0&&s.strategy.risk.expiresAt<=n.nowMs)throw new Error("strategy is expired: risk.expiresAt must be strictly greater than nowMs");let a=s.strategy.risk,i=s.evaluateAll(e),l=n.latencyBars,f=n.slippageBps,u=n.takerFeeBps,c=n.builderFeeBps,d=n.initialEquityUsd,m=0,p=0,b=0,E=0,k=0,P=[],T=[],x=[],v=[],_=[],w=null,J=0,st=null,at=d,X=!1,h=0,A=0,N=[],L=new Array(e.length).fill(0);function F(g){N.push(g)}function I(g){let $=e[g].v*(n.maxVolumeParticipationPct/100);return Math.max(0,$-L[g])}function R(g){if(!w)return d;let $=w.side==="long"?(g-w.entryPrice)*w.qty:(w.entryPrice-g)*w.qty;return d+$}function D(g,$,S){let H=S.o,O=Ln(d,a);if(!(O>0)||!(H>0))return;let j=Mn(H,$,f),M=O/j,q=I(g),St=j*q;if(M>q){x.push({kind:"entry",barIndex:g,time:S.t,side:$,requestedNotionalUsd:O,maxFillNotionalUsd:St,reason:"volume_participation"});return}L[g]+=M;let W=Math.abs(j-H)*M,rt=pr(O,u,c);d-=rt.total,m+=rt.taker,p+=rt.builder,E+=W,k+=O,w={lifecycleEpoch:++A,side:$,entryBarIndex:g,entryReferencePrice:H,entryPrice:j,qty:M,notionalUsd:O,stop:Fn(j,$,a.stopLossPct),take:Hn(j,$,a.takeProfitPct),liq:jn(j,$,a.maxLeverage,u+c),entryFees:rt.taker,entryBuilderFees:rt.builder,entrySlippageUsd:W,fundingAccrued:0}}function C(g,$,S,H){if(!w)return!1;let O=w.side,j=$,M=j;S!=="liquidation"&&H&&(M=vn(j,O,f));let q=w.qty,St=q*M;if(S!=="liquidation"){let Ce=I(g),jr=M*Ce;if(q>Ce)return x.push({kind:"exit",barIndex:g,time:e[g].t,side:O,requestedNotionalUsd:St,maxFillNotionalUsd:jr,reason:"volume_participation",triggerReason:S}),!1;L[g]+=q}let W=pr(St,u,c),rt=S==="liquidation"?0:Math.abs(M-j)*q,kt,Gt;O==="long"?(kt=(j-w.entryReferencePrice)*q,Gt=(M-w.entryPrice)*q):(kt=(w.entryReferencePrice-j)*q,Gt=(w.entryPrice-M)*q),d+=Gt,d-=W.total,m+=W.taker,p+=W.builder,E+=rt,k+=St;let Hr={side:O,entryBarIndex:w.entryBarIndex,entryTime:e[w.entryBarIndex].t,entryPrice:w.entryPrice,exitBarIndex:g,exitTime:e[g].t,exitPrice:M,exitReason:S,qty:q,notionalUsd:w.notionalUsd,grossPnlUsd:kt,feesUsd:w.entryFees+W.taker,builderFeesUsd:w.entryBuilderFees+W.builder,fundingUsd:w.fundingAccrued,slippageUsd:w.entrySlippageUsd+rt,netPnlUsd:kt-(w.entryFees+W.taker+w.entryBuilderFees+W.builder)-w.fundingAccrued-(w.entrySlippageUsd+rt)};return P.push(Hr),S==="liquidation"&&T.push({barIndex:g,time:e[g].t,side:O,price:M,tradeIndex:P.length-1}),w=null,A+=1,h=g+1+(a.cooldownBars||0),!0}function Z(g,$,S,H){let O=g+1;if(O>=e.length)return;N.some(M=>M.kind==="exit"&&M.side===$&&M.fillBar===O&&M.epoch===H)||F({kind:"exit",side:$,signalBar:g,fillBar:O,reason:S,epoch:H})}function Rt(g){let $=N.filter(S=>S.fillBar===g);for(let S=N.length-1;S>=0;S--)N[S].fillBar===g&&N.splice(S,1);$.sort((S,H)=>{let O=j=>j.kind==="exit"?0:1;return O(S)-O(H)});for(let S of $)if(S.kind==="exit"){if(!w||w.side!==S.side||w.lifecycleEpoch!==S.epoch)continue;let H=S.reason||"rule";C(g,e[g].o,H,!0)||Z(g,S.side,H,S.epoch)}else if(S.kind==="entry"){if(w||S.epoch!==A||g<h)continue;D(g,S.side,e[g])}}function Mt(g){if(!w)return;let $=e[g],S=$.fundingPaymentRate;if(S==null||!Q(S)||S===0)return;let H=Math.abs(w.qty*$.c),O=S*H;w.side==="long"?(d-=O,w.fundingAccrued+=O,b+=O):(d+=O,w.fundingAccrued-=O,b-=O)}function vt(g){if(!w)return;let $=e[g].o;(w.side==="long"?$<=w.liq:$>=w.liq)&&C(g,$,"liquidation",!1)}function Le(g){if(!w)return;let $=e[g],S=w.side,H=qn($,S,w.liq),O=Un($,S,w.stop),j=Cn($,S,w.take),M=q=>S==="long"?Math.min(q,$.o):Math.max(q,$.o);if(H){C(g,M(w.liq),"liquidation",!1);return}if(O&&j){C(g,M(w.stop),"stop_loss",!0)||Z(g,S,"stop_loss",w.lifecycleEpoch);return}if(O){C(g,M(w.stop),"stop_loss",!0)||Z(g,S,"stop_loss",w.lifecycleEpoch);return}j&&(C(g,w.take,"take_profit",!0)||Z(g,S,"take_profit",w.lifecycleEpoch))}for(let g=0;g<e.length;g++){let $=Math.floor(e[g].t/864e5);$!==st&&(st=$,at=R(e[g].o),X=!1),vt(g),Rt(g),Le(g),Mt(g),!X&&R(e[g].c)<=at*(1-a.maxDailyLossPct/100)&&(X=!0,v.push({type:"daily_loss_limit",barIndex:g,time:e[g].t,message:"daily loss limit reached; new entries blocked for UTC day"}));let S=i[g].signals,H=g+l;if(w)(w.side==="long"&&S.exitLong===!0||w.side==="short"&&S.exitShort===!0)&&H<e.length&&(N.some(q=>q.kind==="exit"&&q.side===w.side&&q.fillBar===H&&q.epoch===w.lifecycleEpoch)||F({kind:"exit",side:w.side,signalBar:g,fillBar:H,reason:"rule",epoch:w.lifecycleEpoch}));else{let j=S.entryLong===!0,M=S.entryShort===!0;j&&M?v.push({type:"conflicting_entry_signals",barIndex:g,time:e[g].t,message:"conflicting entry signals; no position opened"}):!X&&(j||M)&&H<e.length&&g>=h&&F({kind:"entry",side:j?"long":"short",signalBar:g,fillBar:H,epoch:A})}let O=d;w&&(J+=1,O=R(e[g].c)),_.push({barIndex:g,time:e[g].t,equity:O,positionSide:w?w.side:null})}let Fe=null;if(w){let g=e.length-1;if(C(g,e[g].c,"end_of_data",!0))_[g]={barIndex:g,time:e[g].t,equity:d,positionSide:null};else{let S=R(e[g].c);Fe={side:w.side,entryBarIndex:w.entryBarIndex,entryTime:e[w.entryBarIndex].t,entryPrice:w.entryPrice,qty:w.qty,notionalUsd:w.notionalUsd,markPrice:e[g].c,markedEquityUsd:S},v.push({type:"open_position_at_end",barIndex:g,time:e[g].t,message:"end-of-data exit missed; position remains open and marked"})}}let He=(w?R(e[e.length-1].c):d)-n.initialEquityUsd,Mr=He/n.initialEquityUsd*100,je=0,Vt=0,Jt=0;for(let g of P)g.netPnlUsd>0?(je+=1,Vt+=g.netPnlUsd):g.netPnlUsd<0&&(Jt+=-g.netPnlUsd);let Kt=P.length,vr=Kt===0?0:je/Kt,Yt=0;Jt>0?Yt=Vt/Jt:Vt>0&&(Yt=1e12);let Lr={netPnlUsd:He,netPnlPct:Mr,maxDrawdownPct:Dn(_),winRate:vr,profitFactor:Yt,tradeCount:Kt,sharpe:Bn(_),turnoverUsd:k,exposurePct:J/e.length*100},Fr={initialEquityUsd:n.initialEquityUsd,takerFeeBps:n.takerFeeBps,builderFeeBps:n.builderFeeBps,slippageBps:n.slippageBps,latencyBars:n.latencyBars,maxVolumeParticipationPct:n.maxVolumeParticipationPct},Ue={barsHash:o,strategyHash:s.strategyHash,compilerHash:lt,compilerVersion:gt,config:Fr,trades:P,equityCurve:_,metrics:Lr,costs:{feesUsd:m,builderFeesUsd:p,fundingUsd:b,slippageUsd:E},liquidations:T,missedFills:x,openPositionAtEnd:Fe,flags:v};return ue(Ue),le(jt(Ue))}import{createHash as zn}from"node:crypto";var de=256,hr=new Set(["netPnlUsd","profitFactor","sharpe","maxDrawdownPct"]);function yr(t){let e=String(t).toLowerCase();return e==="holdout"||e==="test"||e==="oos"||e.includes("holdout")||e.includes("oos")?!0:e==="testbars"||e.endsWith("testbars")||e.startsWith("test")||e.endsWith("test")?!e.includes("backtest"):!1}function wr(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function pe(t){if(t==null||typeof t!="object"||Object.isFrozen(t))return t;if(Array.isArray(t)){for(let e of t)pe(e);return Object.freeze(t)}for(let e of Object.keys(t))pe(t[e]);return Object.freeze(t)}function It(t){if(Array.isArray(t))return t.map(It);if(t!=null&&typeof t=="object"){let e={};for(let r of Object.keys(t).sort())e[r]=It(t[r]);return e}return t}function Ct(t){return JSON.stringify(It(t))}function Vn(t){let{min:e,max:r,step:n}=t;if(!(n>0)||e>r)return[];let o=[],s=Math.floor((r-e)/n+1e-9);for(let i=0;i<=s;i++){let l=e+i*n;if(l>r+1e-9)break;let f=Math.abs(l-Math.round(l))<1e-9?Math.round(l):Number(l.toPrecision(12));f<e-1e-9||f>r+1e-9||o.push(f)}if(o.length===0)return[];let a=o[o.length-1];if(Math.abs(a-r)>1e-9){let i=(r-e)/n;Math.abs(i-Math.round(i))<=1e-9&&o.push(r)}return o}function Jn(t,e){if(t.length===0)return[];let r=[{}];for(let n of t){let o=e[n],s=[];for(let a of r)for(let i of o)s.push({...a,[n]:i});r=s}return r.sort((n,o)=>{let s=Ct(n),a=Ct(o);return s<a?-1:s>a?1:0}),r}function fe(t,e,r,n,o){let s=0;if(t==="maxDrawdownPct"){if(s=e.maxDrawdownPct-n.maxDrawdownPct,s!==0)return s<0}else if(s=e[t]-n[t],s!==0)return s>0;let a=Ct(r),i=Ct(o);return a<i}function me(t,e,r={}){if(!wr(r))throw new TypeError("options must be a plain object");for(let x of Object.keys(r))if(yr(x))throw new TypeError(`options must not include holdout/test/oos key "${x}"`);let n=new Set(["maxTrials","objective","backtestOptions"]);for(let x of Object.keys(r))if(!n.has(x))throw new TypeError(`unknown option "${x}"`);let o=64;if("maxTrials"in r){let x=r.maxTrials;if(!Number.isInteger(x)||x<1||x>de)throw new TypeError(`maxTrials must be an integer 1..${de}`);o=x}let s=r.objective??"netPnlUsd";if(!hr.has(s))throw new TypeError(`objective must be one of ${[...hr].join("|")}`);let a=r.backtestOptions??{};if(!wr(a))throw new TypeError("backtestOptions must be a plain object");for(let x of Object.keys(a))if(yr(x))throw new TypeError(`backtestOptions must not include holdout/test/oos key "${x}"`);let i=z(t),l=Object.keys(i.parameters).sort();if(l.length===0)throw new Error("optimizeStrategy requires at least one declared parameter");let f={},u=1;for(let x of l){let v=Vn(i.parameters[x]);if(v.length===0)throw new Error(`parameter "${x}" produces an empty grid`);f[x]=v,u*=v.length}let c=Jn(l,f);if(c.length===0)throw new Error("parameter grid is empty");let d=c.slice(0,o),m=[],p=null,b=null;for(let x of d){let v=mt(i,x),_=ot(v,e,a);b==null&&(b=_.config);let w={netPnlUsd:_.metrics.netPnlUsd,netPnlPct:_.metrics.netPnlPct,maxDrawdownPct:_.metrics.maxDrawdownPct,winRate:_.metrics.winRate,profitFactor:_.metrics.profitFactor,tradeCount:_.metrics.tradeCount,sharpe:_.metrics.sharpe,turnoverUsd:_.metrics.turnoverUsd},J={parameters:{...x},metrics:w};m.push(J),(!p||fe(s,w,x,p.metrics,p.parameters))&&(p=J)}m.sort((x,v)=>fe(s,x.metrics,x.parameters,v.metrics,v.parameters)?-1:fe(s,v.metrics,v.parameters,x.metrics,x.parameters)?1:0);let E={...p.parameters},k=mt(i,E),P={strategyHash:ft(i),compilerHash:lt,trainBarsHash:Tt(e),backtestConfig:b,objective:s,maxTrials:o,trialsRun:m.length,candidates:m,bestParameters:E,bestStrategy:k},T={id:zn("sha256").update(JSON.stringify(It(P)),"utf8").digest("hex"),...P};return pe(It(JSON.parse(JSON.stringify(T))))}import{createHash as Kn}from"node:crypto";var Er=Object.freeze(["fail","pass_paper_only","pass_live_eligible"]);function tt(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function bt(t){return typeof t=="number"&&Number.isFinite(t)}function we(t){if(t==null||typeof t!="object"||Object.isFrozen(t))return t;if(Array.isArray(t)){for(let e of t)we(e);return Object.freeze(t)}for(let e of Object.keys(t))we(t[e]);return Object.freeze(t)}function pt(t){if(Array.isArray(t))return t.map(pt);if(t!=null&&typeof t=="object"){let e={};for(let r of Object.keys(t).sort())e[r]=pt(t[r]);return e}return t}function he(t){return{netPnlUsd:t.metrics.netPnlUsd,netPnlPct:t.metrics.netPnlPct,maxDrawdownPct:t.metrics.maxDrawdownPct,winRate:t.metrics.winRate,profitFactor:t.metrics.profitFactor,tradeCount:t.metrics.tradeCount,sharpe:t.metrics.sharpe,turnoverUsd:t.metrics.turnoverUsd,exposurePct:t.metrics.exposurePct}}function gr(t){return{feesUsd:t.costs.feesUsd,builderFeesUsd:t.costs.builderFeesUsd,fundingUsd:t.costs.fundingUsd,slippageUsd:t.costs.slippageUsd}}function Yn(t){return(t.feesUsd||0)+(t.builderFeesUsd||0)+Math.max(0,t.fundingUsd||0)+(t.slippageUsd||0)}function Gn(t){let e=0;for(let r of t.trades)r.grossPnlUsd>0&&(e+=r.grossPnlUsd);return e}function Xn(t,e,r){return!(!t||t.tradeCount<Math.max(1,Math.min(r,3))||!(t.netPnlUsd>0)||!(t.profitFactor>1)||!(t.maxDrawdownPct<=e.maxDailyLossPct))}function xr(t){if(!tt(t))throw new TypeError("evidence artifact must be a plain object");if(!Er.includes(t.status))throw new TypeError("evidence artifact status is invalid");for(let e of["strategyHash","compilerHash","barsHash"])if(typeof t[e]!="string"||!/^[0-9a-f]{64}$/.test(t[e]))throw new TypeError(`evidence artifact ${e} must be a sha256 hash`);if(!tt(t.split))throw new TypeError("evidence artifact split required");if(!Array.isArray(t.flags))throw new TypeError("evidence artifact flags must be an array");if(!tt(t.walkForward)||!Array.isArray(t.walkForward.windows))throw new TypeError("evidence artifact walkForward windows required");if(t.status==="pass_live_eligible"&&(!tt(t.train)||!tt(t.holdout)))throw new TypeError("live-eligible evidence artifact requires train and holdout facts");return pt({barsHash:t.barsHash,compilerHash:t.compilerHash,flags:t.flags.map(e=>pt(e)),holdout:t.holdout??null,split:t.split,status:t.status,strategyHash:t.strategyHash,train:t.train??null,walkForward:{passRate:t.walkForward.passRate,windowsRun:t.walkForward.windowsRun??t.walkForward.windows.length,windows:t.walkForward.windows.map(e=>({index:e.index,trainStartIndex:e.trainStartIndex,trainEndIndex:e.trainEndIndex,passed:e.passed,reason:e.reason,evalStartIndex:e.evalStartIndex,evalEndIndex:e.evalEndIndex,metrics:e.metrics}))}})}function ge(t){return Kn("sha256").update(JSON.stringify(xr(t)),"utf8").digest("hex")}function G(t,e,r=0){if(!Number.isInteger(t)||t<r)throw new Error(`${e} must be an integer >= ${r}`);return t}function ye(t,e){if(!tt(t)||!tt(t.metrics))throw new Error(`${e} metrics required`);let r=G(t.tradeCount,`${e}.tradeCount`);if(t.metrics.tradeCount!==r)throw new Error(`${e} tradeCount contradicts metrics.tradeCount`);for(let n of["netPnlUsd","profitFactor","maxDrawdownPct"])if(!bt(t.metrics[n]))throw new Error(`${e}.metrics.${n} must be finite`);if(t.metrics.maxDrawdownPct<0)throw new Error(`${e}.metrics.maxDrawdownPct must be >= 0`);return t.metrics}function Zn(t,{maxDailyLossPct:e}={}){let r=t.split,n=G(r.trainStartIndex,"split.trainStartIndex"),o=G(r.trainEndIndex,"split.trainEndIndex"),s=G(r.trainBarCount,"split.trainBarCount",1),a=G(r.holdoutStartIndex,"split.holdoutStartIndex"),i=G(r.holdoutEndIndex,"split.holdoutEndIndex"),l=G(r.holdoutBarCount,"split.holdoutBarCount",1);if(n!==0||o-n+1!==s||a!==o+1||i-a+1!==l)throw new Error("evidence split must be contiguous, chronological, and count-consistent");if(!bt(r.trainFraction)||r.trainFraction<=0||r.trainFraction>=1)throw new Error("split.trainFraction must be in (0,1)");ye(t.train,"train");let f=ye(t.holdout,"holdout");if(f.tradeCount<1||f.netPnlUsd<=0||f.profitFactor<=1)throw new Error("live-eligible holdout metrics do not pass");if(bt(e)&&f.maxDrawdownPct>e)throw new Error("live-eligible holdout drawdown exceeds strategy risk");if(t.flags.length>0)throw new Error("live-eligible evidence cannot contain failure flags");let u=t.walkForward,c=u.windows;if(c.length<1||u.windowsRun!==c.length)throw new Error("live-eligible walk-forward windowsRun must match nonempty windows");let d=0,m=-1;for(let b=0;b<c.length;b++){let E=c[b];if(!tt(E)||E.index!==b||typeof E.passed!="boolean")throw new Error("walk-forward windows must be ordered and structurally valid");let k=G(E.trainStartIndex,`walkForward.windows[${b}].trainStartIndex`),P=G(E.trainEndIndex,`walkForward.windows[${b}].trainEndIndex`),T=G(E.evalStartIndex,`walkForward.windows[${b}].evalStartIndex`),x=G(E.evalEndIndex,`walkForward.windows[${b}].evalEndIndex`);if(k!==0||P>=T||T>x||T<=m)throw new Error("walk-forward windows must be chronological and disjoint");if(m=x,E.passed){if(d+=1,E.reason!=="pass")throw new Error("passed walk-forward window reason must be pass");let v=ye({metrics:E.metrics,tradeCount:E.metrics?.tradeCount},`walkForward.windows[${b}]`);if(v.tradeCount<1||v.netPnlUsd<=0||v.profitFactor<=1)throw new Error("passed walk-forward window metrics do not pass");if(bt(e)&&v.maxDrawdownPct>e)throw new Error("passed walk-forward drawdown exceeds strategy risk")}else if(E.reason==="pass")throw new Error("failed walk-forward window cannot have pass reason")}let p=d/c.length;if(!bt(u.passRate)||Math.abs(u.passRate-p)>Number.EPSILON||p<.6)throw new Error("walk-forward passRate contradicts concrete windows or is below live threshold")}function be(t,e={}){if(typeof t?.id!="string"||!/^[0-9a-f]{64}$/.test(t.id))throw new Error("evidence.id must be a sha256 evidence artifact hash");let r=xr(t),n=pt({id:t.id,...r});if(JSON.stringify(pt(t))!==JSON.stringify(n))throw new Error("evidence artifact contains fields unbound from its deterministic identity");let o=ge(t);if(t.id!==o)throw new Error("evidence.id does not match its deterministic artifact facts digest");return t.status==="pass_live_eligible"&&Zn(t,e),t}function qt({strategy:t,bars:e,backtestOptions:r={},trainFraction:n=.7,walkForwardWindows:o=3,minTrades:s=10}={}){let a=[];if(!tt(t))throw new TypeError("strategy must be a plain object");if(!Array.isArray(e))throw new TypeError("bars must be an array");if(!tt(r))throw new TypeError("backtestOptions must be a plain object");if(!bt(n)||n<=0||n>=1)throw new TypeError("trainFraction must be in (0,1)");if(!Number.isInteger(o)||o<1)throw new TypeError("walkForwardWindows must be a positive integer");if(!Number.isInteger(s)||s<0)throw new TypeError("minTrades must be an integer >= 0");let i=z(t),l=ft(i),f=Tt(e),u=e.length,c=(I=[],R={})=>br({status:"fail",strategy:i,sHash:l,barsHash:f,split:R.split||{trainStartIndex:0,trainEndIndex:-1,trainBarCount:0,holdoutStartIndex:0,holdoutEndIndex:-1,holdoutBarCount:0,trainFraction:n},train:R.train||null,holdout:R.holdout||null,walkForward:R.walkForward||{windows:[],passRate:0},flags:[...a,...I]});if(u<10)return c([{type:"insufficient_bars",message:"need at least 10 bars for evidence"}]);let d=Math.floor(u*n),m=d,p=u-m;if(d<5||p<3)return c([{type:"invalid_windowing",message:"train/holdout split too small",trainCount:d,holdoutCount:p}]);let b=e.slice(0,d),E=e.slice(m),k,P;try{k=ot(i,b,r),P=ot(i,E,r)}catch(I){return c([{type:"backtest_error",message:String(I.message||I)}])}let T={metrics:he(k),costs:gr(k),tradeCount:k.metrics.tradeCount},x={metrics:he(P),costs:gr(P),tradeCount:P.metrics.tradeCount},v={trainStartIndex:0,trainEndIndex:d-1,trainBarCount:d,holdoutStartIndex:m,holdoutEndIndex:u-1,holdoutBarCount:p,trainFraction:n},_=[],w=Math.floor(u/(o+1));if(w<3)a.push({type:"invalid_windowing",message:"walk-forward window size too small",wfSize:w});else for(let I=0;I<o;I++){let R=w*(I+1),D=R,C=Math.min(u,D+w);if(C-D<3||R<3){_.push({index:I,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:D,evalEndIndex:C-1,passed:!1,reason:"window_too_small",metrics:null});continue}let Z=e.slice(D,C),Rt;try{Rt=ot(i,Z,r)}catch{_.push({index:I,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:D,evalEndIndex:C-1,passed:!1,reason:"backtest_error",metrics:null});continue}let Mt=he(Rt),vt=Xn(Mt,i.risk,s);_.push({index:I,trainStartIndex:0,trainEndIndex:R-1,evalStartIndex:D,evalEndIndex:C-1,passed:vt,reason:vt?"pass":"fail_metrics",metrics:Mt})}let J=_.filter(I=>I.passed).length,st=_.length===0?0:J/_.length,at={windows:_,passRate:st,windowsRun:_.length};x.metrics.tradeCount===0&&T.metrics.tradeCount===0&&a.push({type:"no_trades",message:"no trades in train or holdout"}),x.metrics.tradeCount===0&&a.push({type:"absent_oos_trades",message:"holdout produced no trades"}),x.metrics.netPnlUsd<0&&a.push({type:"holdout_loss",message:"holdout netPnlUsd is negative"}),T.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<0&&T.metrics.netPnlUsd>Math.abs(x.metrics.netPnlUsd)*.25?a.push({type:"overfit",message:"profitable train with losing holdout (OOS collapse)"}):T.metrics.netPnlUsd>0&&x.metrics.netPnlUsd>0&&x.metrics.netPnlUsd<T.metrics.netPnlUsd*.1&&T.metrics.tradeCount>=s&&a.push({type:"severe_oos_collapse",message:"holdout pnl collapsed vs train"});let X=Yn(x.costs),h=Gn(P);h>0&&X>h&&a.push({type:"costs_exceed_gross",message:"holdout costs exceed gross gains"});let A=a.some(I=>["insufficient_bars","invalid_windowing","absent_oos_trades","holdout_loss","no_trades","severe_oos_collapse","backtest_error"].includes(I.type)),N=a.some(I=>I.type==="overfit"),L="fail";return x.metrics.tradeCount>=s&&x.metrics.netPnlUsd>0&&x.metrics.profitFactor>1&&x.metrics.maxDrawdownPct<=i.risk.maxDailyLossPct&&st>=.6&&!(h>0&&X>h)&&!N&&!a.some(I=>I.type==="severe_oos_collapse"||I.type==="invalid_windowing")?L="pass_live_eligible":!A&&x.metrics.tradeCount>0&&T.metrics.tradeCount>0&&Number.isFinite(x.metrics.netPnlUsd)?(L="pass_paper_only",x.metrics.tradeCount<s&&a.push({type:"undersampled",message:"holdout trades below minTrades"})):N&&x.metrics.tradeCount>0&&T.metrics.netPnlUsd>0?L="fail":x.metrics.tradeCount>0&&T.metrics.tradeCount>0&&!A?L="pass_paper_only":L="fail",x.metrics.netPnlUsd<0&&(L=L==="pass_live_eligible"?"fail":L==="pass_paper_only"?"pass_paper_only":"fail",L="fail"),br({status:L,strategy:i,sHash:l,barsHash:f,split:v,train:T,holdout:x,walkForward:at,flags:a})}function br({status:t,strategy:e,sHash:r,barsHash:n,split:o,train:s,holdout:a,walkForward:i,flags:l}){let f={status:t,strategyHash:r,compilerHash:lt,barsHash:n,split:o,train:s,holdout:a,walkForward:i,flags:l};return f.id=ge(f),we(pt(JSON.parse(JSON.stringify(f))))}import{createHash as Wn}from"node:crypto";var B=class extends Error{constructor(e){super(e),this.name="StrategyDraftError"}},Qn=new Set(["1m","3m","5m","15m","30m","1h","2h","4h","8h","12h","1d"]),to=new Set(["BTC","ETH","SOL","HYPE"]),eo=/\b(mnemonic|private\s*key|privkey|seed\s*phrase|seed\b|api[_-]?key|secret\s*key|wallet\s*key|passphrase)\b/i,Et="Supported grammar: (1) EMA cross: <long|short> <COIN> when EMA <n> crosses <above|below> EMA <m> [on <interval>] [, exit on reverse] [, risk knobs]; (2) RSI: <long|short> <COIN> when RSI <n> <above|below> <threshold> [on <interval>] [, risk knobs]; (3) funding: <long|short> <COIN> when funding rate <above|below> <decimal|percent%> [on <interval>] [, risk knobs]. Risk knobs: stop loss %, take profit %, leverage, position size %, max notional USD. Coins: BTC ETH SOL HYPE or uppercase token <=12 chars. Intervals: 1m 3m 5m 15m 30m 1h 2h 4h 8h 12h 1d.",ro=Object.freeze({maxLeverage:1,maxNotionalUsd:100,positionSizePct:5,stopLossPct:2,takeProfitPct:4,cooldownBars:1,maxDailyLossPct:3}),no=36e5,oo=30*864e5,io=864e5;function so(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function Ee(t){if(t==null||typeof t!="object"||Object.isFrozen(t))return t;if(Array.isArray(t)){for(let e of t)Ee(e);return Object.freeze(t)}for(let e of Object.keys(t))Ee(t[e]);return Object.freeze(t)}function ao(t){return String(t).trim().replace(/\s+/g," ")}function co(t){let e=t.match(/\b(long|short)\b/i);return e?e[1].toLowerCase():null}function lo(t){for(let r of to)if(new RegExp(`\\b${r}\\b`,"i").test(t))return r;let e=t.match(/\b([A-Z][A-Z0-9]{1,11})\b/);return e?e[1]:null}function uo(t){let e=t.match(/\bon\s+(1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/i);if(!e)return"15m";let r=e[1].toLowerCase();return Qn.has(r)?r:null}function fo(t){let e={...ro},r=t.match(/stop\s*loss\s*(\d+(?:\.\d+)?)\s*%?/i);r&&(e.stopLossPct=Number(r[1]));let n=t.match(/take\s*profit\s*(\d+(?:\.\d+)?)\s*%?/i);n&&(e.takeProfitPct=Number(n[1]));let o=t.match(/leverage\s*(\d+(?:\.\d+)?)/i);o&&(e.maxLeverage=Number(o[1]));let s=t.match(/position\s*size\s*(\d+(?:\.\d+)?)\s*%?/i);s&&(e.positionSizePct=Number(s[1]));let a=t.match(/max\s*notional\s*(?:usd\s*)?\$?\s*(\d+(?:\.\d+)?)/i);return a&&(e.maxNotionalUsd=Number(a[1])),e}function po(t){return[/\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/\bleverage\s*\d+(?:\.\d+)?/gi,/\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi].some(r=>(t.match(r)??[]).length>1)}function mo(t){let e=Wn("sha256").update(t,"utf8").digest("hex").slice(0,10),r=t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40),o=`${r.length?r:"draft"}-${e}`.replace(/[^a-z0-9._-]/g,"").slice(0,64);return/^[a-z0-9]/.test(o)?o:`d${o}`.slice(0,64)}function ho(t){let e=t.match(/\bema\s*(\d+)\s*cross(?:es)?\s*(above|below)\s*ema\s*(\d+)\b/i);if(!e)return null;let r=Number(e[1]),n=e[2].toLowerCase(),o=Number(e[3]);if(!(r>0)||!(o>0)||r===o)return null;let s=/\b(exit\s+on\s+reverse|reverse\s+exit)\b/i.test(t);return{kind:"ema_cross",fast:r,slow:o,direction:n,reverse:s}}function yo(t){let e=t.match(/\brsi\s*(\d+)\s*(above|below)\s*(-?\d+(?:\.\d+)?)/i);if(!e)return null;let r=Number(e[3]);return!Number.isFinite(r)||r<=0||r>=100?null:{kind:"rsi",period:Number(e[1]),op:e[2].toLowerCase(),threshold:r}}function wo(t){let e=t.match(/\bfunding\s*rate\s*(above|below)\s*(-?\d+(?:\.\d+)?)(%?)(?=\s|,|$)/i);if(!e)return null;let r=Number(e[2]);return e[3]==="%"&&(r=r/100),{kind:"funding",op:e[1].toLowerCase(),threshold:r}}function go(t,e){let r=t.replace(/^(long|short)\s+[A-Z][A-Z0-9]{1,11}\s+when\s+/i,"");if(r===t)return!1;e.kind==="ema_cross"?r=r.replace(/^ema\s*\d+\s*cross(?:es)?\s*(?:above|below)\s*ema\s*\d+\b/i,""):e.kind==="rsi"?r=r.replace(/^rsi\s*\d+\s*(?:above|below)\s*\d+(?:\.\d+)?\b/i,""):r=r.replace(/^funding\s*rate\s*(?:above|below)\s*-?\d+(?:\.\d+)?%?(?=\s|,|$)/i,"");let n=[/(?:,\s*)?\bon\s+(?:1m|3m|5m|15m|30m|1h|2h|4h|8h|12h|1d)\b/gi,/(?:,\s*)?\bstop\s*loss\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\btake\s*profit\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bleverage\s*\d+(?:\.\d+)?/gi,/(?:,\s*)?\bposition\s*size\s*\d+(?:\.\d+)?\s*%?/gi,/(?:,\s*)?\bmax\s*notional\s*(?:usd\s*)?\$?\s*\d+(?:\.\d+)?/gi];e.kind==="ema_cross"&&n.push(/(?:,\s*)?\b(?:exit\s+on\s+reverse|reverse\s+exit)\b/gi);for(let o of n)r=r.replace(o,"");return r.replace(/[\s,;]+/g,"")===""}function Sr(t){let e=Math.max(2,Math.floor(t/2));return{value:t,min:Math.max(2,t-e),max:Math.min(500,t+e),step:1}}function bo({side:t,coin:e,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let l=[{id:"c",type:"input",field:"close"},{id:"emaLeft",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_left_period"}},{id:"emaRight",type:"indicator",indicator:"ema",input:"c",period:{param:"ema_right_period"}},{id:"cross",type:"cross",direction:i.direction,left:"emaLeft",right:"emaRight"}],f={entryLong:null,entryShort:null,exitLong:null,exitShort:null};if(t==="long"?f.entryLong="cross":f.entryShort="cross",i.reverse){let u=i.direction==="above"?"below":"above";l.push({id:"crossRev",type:"cross",direction:u,left:"emaLeft",right:"emaRight"}),t==="long"?f.exitLong="crossRev":f.exitShort="crossRev"}return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:e,interval:r},parameters:{ema_left_period:Sr(i.fast),ema_right_period:Sr(i.slow)},nodes:l,rules:f,risk:{...n,expiresAt:o}}}function Eo({side:t,coin:e,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let l=[{id:"c",type:"input",field:"close"},{id:"rsi",type:"indicator",indicator:"rsi",input:"c",period:i.period},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"rsi",right:"thr"}];return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:e,interval:r},parameters:{},nodes:l,rules:{entryLong:t==="long"?"sig":null,entryShort:t==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function xo({side:t,coin:e,interval:r,risk:n,expiresAt:o,id:s,name:a,spec:i}){let l=[{id:"fr",type:"input",field:"fundingRate"},{id:"thr",type:"constant",value:i.threshold},{id:"sig",type:"compare",op:i.op==="above"?"gt":"lt",left:"fr",right:"thr"}];return{version:1,id:s,name:a,venue:"hyperliquid",market:{coin:e,interval:r},parameters:{},nodes:l,rules:{entryLong:t==="long"?"sig":null,entryShort:t==="short"?"sig":null,exitLong:null,exitShort:null},risk:{...n,expiresAt:o}}}function xe(t,e={}){if(typeof t!="string")throw new B("prompt must be a string");if(t.length>1e3)throw new B("prompt length must be <= 1000");if(!so(e))throw new B("options must be a plain object");if(!Number.isInteger(e.nowMs))throw new B("options.nowMs is required integer epoch ms");let r=e.nowMs,n=io;if("expiresInMs"in e){if(!Number.isInteger(e.expiresInMs))throw new B("expiresInMs must be an integer");if(n=e.expiresInMs,n<no||n>oo)throw new B("expiresInMs must be between 1h and 30d")}if(eo.test(t))throw new B(`prompt appears to contain secrets and is rejected. ${Et}`);let o=ao(t);if(!o)throw new B(`empty prompt. ${Et}`);if(po(o))throw new B(`duplicate interval or risk clause. ${Et}`);let s=co(o),a=lo(o),i=uo(o);if(!s||!a||!i)throw new B(`could not parse side/coin/interval. ${Et}`);let l=fo(o);if(!(l.maxLeverage>0)||l.maxLeverage>50)throw new B("leverage out of range");if(!(l.positionSizePct>0)||l.positionSizePct>100)throw new B("position size out of range");let f=r+n,u=mo(o),c=`Draft ${a} ${s}`.slice(0,100),d=ho(o),m=yo(o),p=wo(o),b=[d,m,p].filter(Boolean);if(b.length!==1)throw new B(`unsupported or ambiguous prompt. ${Et}`);if(!go(o,b[0]))throw new B(`unsupported or ambiguous prompt. ${Et}`);let E,k=b[0],P={side:s,coin:a,interval:i,risk:l,expiresAt:f,id:u,name:c,spec:k};k.kind==="ema_cross"?E=bo(P):k.kind==="rsi"?E=Eo(P):E=xo(P);let T=Ht(E,{nowMs:r});if(!T.ok)throw new B(`draft failed validation: ${T.errors.map(x=>x.message).join("; ")}`);return Ee(z(E,{nowMs:r}))}import it from"node:fs";import Bt from"node:path";var ke=1,So=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Dt(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function et(t){return t==null?t:JSON.parse(JSON.stringify(t))}function ko(t){return String(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function xt(t,e="record"){if(Array.isArray(t)){t.forEach((r,n)=>xt(r,`${e}[${n}]`));return}if(Dt(t))for(let[r,n]of Object.entries(t)){let o=ko(r);if(So.some(s=>o.includes(s)))throw new Error(`shadow-store: forbidden secret-like field at ${e}.${r}`);xt(n,`${e}.${r}`)}}function Ao(t){if(typeof t!="string"||!t||!Bt.isAbsolute(t))throw new Error("shadow-store: path must be an absolute path")}function kr(t){let e;try{e=it.lstatSync(t)}catch(n){if(n&&n.code==="ENOENT")return;throw n}if(e.isSymbolicLink())throw new Error("shadow-store: store path must not be a symlink");if(!e.isFile())throw new Error("shadow-store: store path must be a regular file");if(e.mode&511&18)throw new Error("shadow-store: store file must not be group or world writable")}function Po(){return{version:ke,runners:[]}}function Ar(t,e){let r;try{r=JSON.parse(t)}catch{throw new Error("shadow-store: malformed JSON")}if(!Dt(r))throw new Error("shadow-store: malformed JSON root");if(r.version!==ke)throw new Error(`shadow-store: unsupported version ${r.version}`);if(!Array.isArray(r.runners))throw new Error("shadow-store: runners must be an array");return xt(r,Bt.basename(e)),{version:ke,runners:r.runners.map(n=>et(n))}}function Pr(t,e){xt(e,"store");let r=Bt.dirname(t);it.mkdirSync(r,{recursive:!0,mode:448});let n=Bt.join(r,`.shadow-store.${process.pid}.${Date.now()}.tmp`),o=`${JSON.stringify(e)}
3
+ `;try{it.writeFileSync(n,o,{mode:384,flag:"wx"}),it.renameSync(n,t);try{it.chmodSync(t,384)}catch{}}catch(s){try{it.unlinkSync(n)}catch{}throw s}}var Se=new Map;function Ae(t={}){let e=t.path;if(Ao(e),kr(e),it.existsSync(e)?Ar(it.readFileSync(e,"utf8"),e):Pr(e,Po()),Se.has(e))return Se.get(e);let r=!1,n=[];function o(){if(r)return;let p=n.shift();if(p){r=!0;try{let b=p.fn();r=!1,p.resolve(b),o()}catch(b){r=!1,p.reject(b),o()}}}function s(p){if(!r&&n.length===0){r=!0;try{return p()}finally{r=!1,queueMicrotask(o)}}return new Promise((b,E)=>{n.push({fn:p,resolve:b,reject:E}),queueMicrotask(o)})}function a(){return kr(e),Ar(it.readFileSync(e,"utf8"),e)}function i(p){Pr(e,p)}function l(p){if(!Dt(p)||typeof p.id!="string"||!p.id)throw new Error("shadow-store: create requires record with string id");xt(p,"record");let b=a();if(b.runners.some(k=>k.id===p.id))throw new Error(`shadow-store: runner id already exists: ${p.id}`);let E=et(p);return b.runners.push(E),i(b),et(E)}function f(p){let b=a().runners.find(E=>E.id===p);return b?et(b):null}function u(){return a().runners.map(p=>et(p))}function c(p,b){if(typeof b!="function")throw new Error("shadow-store: updater must be a function");let E=a(),k=E.runners.findIndex(x=>x.id===p);if(k<0)throw new Error(`shadow-store: runner not found: ${p}`);let P=et(E.runners[k]),T=b(P);if(!Dt(T)||T.id!==p)throw new Error("shadow-store: updater must return record with same id");return xt(T,"record"),E.runners[k]=et(T),i(E),et(E.runners[k])}function d(p){let b=a(),E=b.runners.findIndex(P=>P.id===p);if(E<0)throw new Error(`shadow-store: runner not found: ${p}`);let k=et(b.runners[E]);return k.status!=="stopped"&&(k.status="stopped",b.runners[E]=k,i(b)),et(b.runners[E])}let m={create(p){return s(()=>l(p))},get(p){return f(p)},list(){return u()},update(p,b){return s(()=>c(p,b))},stop(p){return s(()=>d(p))}};return Se.set(e,m),m}import{createHash as Te}from"node:crypto";function Pe(t){return t==null?t:JSON.parse(JSON.stringify(t))}function $e(t){return Array.isArray(t)?t.map($e):t&&typeof t=="object"?Object.fromEntries(Object.keys(t).sort().map(e=>[e,$e(t[e])])):t}function Tr(t){if(!t||typeof t!="object"||Array.isArray(t))throw new TypeError("shadow-runner: record must be an object");return Te("sha256").update(JSON.stringify($e(t))).digest("hex")}function $o(t,e,r,n,o){return Te("sha256").update(`${t}|${e}|${r}|${n}|${o}`).digest("hex")}function To(t,e,r,n){return Te("sha256").update(`shadow|${t}|${e}|${r}|${n??""}`).digest("hex")}function _o(t){return t==="entryLong"||t==="exitShort"?"buy":t==="entryShort"||t==="exitLong"?"sell":t}function $r(t){return t==="entryLong"||t==="entryShort"}function zt({storePath:t,clock:e=Date.now}={}){if(typeof t!="string"||!t)throw new Error("shadow-runner: storePath required");let r=Ae({path:t});function n({strategy:l,evidenceId:f=null}={}){let u=V(l),c=f==null?null:String(f),d=r.list().filter(k=>k.status==="running"&&k.strategyHash===u.strategyHash&&k.compilerHash===u.compilerHash&&k.evidenceId===c).sort((k,P)=>k.createdAt-P.createdAt||k.id.localeCompare(P.id))[0];if(d)return Pe(d);let m=e(),p=To(m,u.strategyHash,u.compilerHash,c),b=r.get(p);if(b)return Pe(b);let E={id:p,strategy:Pe(u.strategy),strategyHash:u.strategyHash,compilerHash:u.compilerHash,evidenceId:c,status:"running",cursor:null,intendedOrders:[],fills:[],missedFills:[],markouts:[],createdAt:m,updatedAt:m,position:null,cooldownBarsRemaining:0,cooldownStartT:null,lastProcessedBarIndex:-1};return r.create(E)}function o(l){return r.get(l)}function s(){return r.list()}function a(l){return r.stop(l)}function i(l,f,{markoutHorizons:u=[1,4,12]}={}){if(!Array.isArray(f))throw new TypeError("shadow-runner: bars must be an array");return r.update(l,c=>{if(c.status!=="running")throw new Error("shadow-runner: runner is stopped");if(f.length===0)return c;let m=V(c.strategy).evaluateAll(f),p=new Map;for(let h=0;h<f.length;h++)p.set(f[h].t,h);let b=c.cursor,E=[];for(let h=0;h<f.length;h++){let A=f[h].t;(b==null||A>b)&&E.push(h)}if(E.length===0)return c;let k=new Map(c.intendedOrders.map(h=>[h.id,h])),P=new Set(c.fills.map(h=>h.orderId)),T=new Map(c.missedFills.map(h=>[h.orderId,h])),x=(h,A)=>`${h}|${A}`,v=new Map(c.markouts.map(h=>[x(h.orderId,h.horizon),h])),_=c.position?{...c.position}:null,w=Number.isInteger(c.cooldownBarsRemaining)?Math.max(0,c.cooldownBarsRemaining):0,J=Number.isFinite(c.cooldownStartT)?c.cooldownStartT:null;function st({action:h,signalBarT:A,signalIndex:N}){let L=_o(h),F=$o(c.id,c.strategyHash,A,L,h);if(k.has(F))return k.get(F);let I=N+1,R=I<f.length,D={id:F,action:h,type:h,side:L,signalBarT:A,fillBarT:R?f[I].t:null,status:R?"open":"missed"};return k.set(F,D),c.intendedOrders.push(D),D}function at(h,A,N){if(P.has(h.id))return;let L={orderId:h.id,action:$r(h.action)?"entry":"exit",side:h.side,price:A.o,barT:A.t,signalBarT:h.signalBarT,barIndex:N};if(c.fills.push(L),P.add(h.id),h.status="filled",h.fillBarT=A.t,T.has(h.id)&&(T.delete(h.id),c.missedFills=c.missedFills.filter(F=>F.orderId!==h.id)),$r(h.action)){_={side:h.action==="entryLong"?"long":"short",entryOrderId:h.id,entryBarT:A.t,entryPrice:A.o,entryBarIndex:N};for(let F of u){let I=x(h.id,F);if(v.has(I))continue;let R={orderId:h.id,horizon:F,entryBarT:A.t,entryPrice:A.o,side:_.side,status:"pending",close:null,barT:null};v.set(I,R),c.markouts.push(R)}}else _=null,w=Number(c.strategy?.risk?.cooldownBars)||0,J=A.t}function X(h){if(P.has(h.id)||T.has(h.id))return;let A={orderId:h.id,action:h.action,side:h.side,signalBarT:h.signalBarT,status:"missed"};T.set(h.id,A),c.missedFills.push(A),h.status="missed"}for(let h of c.intendedOrders){if(h.status==="filled"||P.has(h.id))continue;let A=p.get(h.signalBarT);if(A==null)continue;let N=A+1;N<f.length&&(b==null||f[N].t>b)&&at(h,f[N],N)}for(let h of E){let A=f[h],N=m[h].signals,L=_,F=R=>{if(_||w>0&&(J==null||A.t>=J))return;let C=st({action:R,signalBarT:A.t,signalIndex:h}),Z=h+1;Z<f.length?at(C,f[Z],Z):X(C)},I=R=>{if(!_||_.side==="long"&&R!=="exitLong"||_.side==="short"&&R!=="exitShort")return;let D=st({action:R,signalBarT:A.t,signalIndex:h}),C=h+1;C<f.length?at(D,f[C],C):X(D)};L?(N.exitLong&&I("exitLong"),N.exitShort&&I("exitShort")):N.entryLong&&N.entryShort||(N.entryLong&&F("entryLong"),N.entryShort&&F("entryShort")),w>0&&J!=null&&A.t>=J&&(w-=1,w===0&&(J=null)),c.cursor=A.t,c.lastProcessedBarIndex=h}for(let h of c.markouts){if(h.status!=="pending")continue;let A=c.fills.find(F=>F.orderId===h.orderId&&F.action==="entry");if(!A)continue;let N=p.get(A.barT);if(N==null)continue;let L=N+h.horizon;if(L<f.length){h.close=f[L].c,h.barT=f[L].t,h.status="filled";let F=h.entryPrice;h.markout=h.side==="long"?(h.close-F)/F:(F-h.close)/F}}return c.position=_,c.cooldownBarsRemaining=w,c.cooldownStartT=J,c.updatedAt=e(),c})}return{start:n,step:i,list:s,get:o,stop:a}}import{createHash as Io,createHmac as Oo,timingSafeEqual as Mi}from"node:crypto";var No=2,Ro=300*1e3,vi=(()=>{let t=Number(process.env.ORACLE_PREPARE_HARD_MAX_AGE_MS);return Number.isFinite(t)&&t>0?t:1800*1e3})();function _e(t){return t===null||typeof t!="object"?JSON.stringify(t):Array.isArray(t)?`[${t.map(_e).join(",")}]`:`{${Object.keys(t).sort().map(r=>`${JSON.stringify(r)}:${_e(t[r])}`).join(",")}}`}function _r(t){let e=String(t?.ORACLE_STAMP_HMAC_SECRET||"").trim();return e.length>=16?e:""}function Ir(t=process.env){return _r(process.env)||_r(t)}function Mo(t){let{oraclePrepared:e,prepareHash:r,prepareMac:n,note:o,...s}=t||{};return s}function vo(t){let e=Mo(t);return Io("sha256").update(_e(e)).digest("hex")}function Lo(t,e=Ir()){return e?Oo("sha256",e).update(String(t)).digest("hex"):""}function Or(t,{provider:e,kind:r,env:n=process.env}={}){if(!t||typeof t!="object")throw new Error("stampPrepared: payload object required");let o={...t,provider:t.provider||e,kind:t.kind||r,requiresUserSignature:t.requiresUserSignature!==!1,signingReady:!1,broadcastReady:!1,executionReady:!1};if(!o.provider)throw new Error("stampPrepared: provider required");if(!o.kind)throw new Error("stampPrepared: kind required");let s=Date.now(),a=s+Ro,l={...o,preparedAt:s,expiresAt:a,prepareVersion:No},f=vo(l),u=Ir(n),c=u?Lo(f,u):void 0,d={...l,oraclePrepared:!0,prepareHash:f};return c&&(d.prepareMac=c),d}var Fo=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Ot(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function Ho(t){return String(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function Oe(t,e="value"){if(Array.isArray(t)){t.forEach((r,n)=>Oe(r,`${e}[${n}]`));return}if(Ot(t))for(let[r,n]of Object.entries(t)){let o=Ho(r);if(Fo.some(s=>o.includes(s)))throw new Error(`handoff: forbidden secret-like field at ${e}.${r}`);Oe(n,`${e}.${r}`)}}function Ie(t){return typeof t=="number"&&Number.isFinite(t)&&t>0}function Ne({strategy:t,evidence:e,shadow:r,caps:n,nowMs:o=Date.now(),env:s=process.env}={}){if(Oe({strategy:t,evidence:e,shadow:r,caps:n},"handoff"),!Ot(t))throw new Error("handoff: strategy required");if(!Ot(e))throw new Error("handoff: evidence required");if(!Ot(r))throw new Error("handoff: shadow required");if(!Ot(n))throw new Error("handoff: caps required");if(typeof r.id!="string"||!r.id.trim())throw new Error("handoff: shadow.id required");if(typeof r.stateHash!="string"||!/^[0-9a-f]{64}$/.test(r.stateHash))throw new Error("handoff: shadow.stateHash must be a sha256 hash");if(r.status!=="running")throw new Error("handoff: shadow.status must be running");if(!Number.isInteger(r.cursor)||r.cursor<=0)throw new Error("handoff: shadow.cursor must be a positive integer");if(!Number.isInteger(r.updatedAt)||r.updatedAt<=0||r.updatedAt>o)throw new Error("handoff: shadow.updatedAt must be a positive integer <= nowMs");let a=z(t,{nowMs:o}),i=V(a);if(be(e,{maxDailyLossPct:a.risk.maxDailyLossPct}),e.status!=="pass_live_eligible")throw new Error("handoff: evidence.status must be pass_live_eligible");if(e.strategyHash!==i.strategyHash)throw new Error("handoff: evidence.strategyHash mismatch");if(e.compilerHash!==i.compilerHash)throw new Error("handoff: evidence.compilerHash mismatch");let l=["perStrategyNotionalUsd","maxLeverage","dailyLossCapUsd","chainAllowlist","assetAllowlist","expiresAt","killSwitchRequired"];for(let d of l)if(!(d in n)||n[d]==null)throw new Error(`handoff: caps.${d} required`);if(!Ie(n.perStrategyNotionalUsd))throw new Error("handoff: caps.perStrategyNotionalUsd must be positive");if(n.perStrategyNotionalUsd>i.strategy.risk.maxNotionalUsd)throw new Error("handoff: caps.perStrategyNotionalUsd exceeds strategy.risk.maxNotionalUsd");if(!Ie(n.maxLeverage))throw new Error("handoff: caps.maxLeverage must be positive");if(n.maxLeverage>i.strategy.risk.maxLeverage)throw new Error("handoff: caps.maxLeverage exceeds strategy.risk.maxLeverage");if(!Ie(n.dailyLossCapUsd))throw new Error("handoff: caps.dailyLossCapUsd must be positive");let f=i.strategy.risk.maxNotionalUsd*(i.strategy.risk.maxDailyLossPct/100);if(n.dailyLossCapUsd>f)throw new Error("handoff: caps.dailyLossCapUsd exceeds strategy daily loss ceiling");if(!Array.isArray(n.chainAllowlist)||n.chainAllowlist.length===0)throw new Error("handoff: caps.chainAllowlist must be a non-empty array");if(!n.chainAllowlist.every(d=>d==="hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include only hyperliquid");if(!n.chainAllowlist.includes("hyperliquid"))throw new Error("handoff: caps.chainAllowlist must include hyperliquid");if(!Array.isArray(n.assetAllowlist)||n.assetAllowlist.length===0)throw new Error("handoff: caps.assetAllowlist must be a non-empty array");if(n.assetAllowlist.length!==1||n.assetAllowlist[0]!==i.strategy.market.coin)throw new Error("handoff: caps.assetAllowlist must contain only the strategy market coin");if(!Number.isInteger(n.expiresAt)||!(n.expiresAt>o))throw new Error("handoff: caps.expiresAt must be an integer > nowMs");if(n.expiresAt>i.strategy.risk.expiresAt)throw new Error("handoff: caps.expiresAt exceeds strategy.risk.expiresAt");if(n.killSwitchRequired!==!0)throw new Error("handoff: caps.killSwitchRequired must be exactly true");let u={perStrategyNotionalUsd:n.perStrategyNotionalUsd,maxLeverage:n.maxLeverage,dailyLossCapUsd:n.dailyLossCapUsd,chainAllowlist:[...n.chainAllowlist],assetAllowlist:[...n.assetAllowlist],expiresAt:n.expiresAt,killSwitchRequired:!0},c={strategyHash:i.strategyHash,compilerHash:i.compilerHash,evidence:JSON.parse(JSON.stringify(e)),shadow:{id:r.id,stateHash:r.stateHash,status:r.status,cursor:r.cursor,updatedAt:r.updatedAt},compiled:{strategyHash:i.strategyHash,compilerHash:i.compilerHash,compilerVersion:gt,venue:"hyperliquid",market:{coin:i.strategy.market.coin,kind:"perp",interval:i.strategy.market.interval},risk:{...i.strategy.risk},strategy:JSON.parse(JSON.stringify(i.strategy))},arming:{liveBroadcast:!1,requiresExplicitUserArm:!0,caps:u},requiresUserSignature:!0,signingReady:!1,broadcastReady:!1,executionReady:!1};return Or(c,{provider:"hl-strategy",kind:"strategy-live-handoff",env:s})}import jo from"node:os";import Uo from"node:path";var Co=["privatekey","secretkey","seed","mnemonic","passphrase","password","keystore","keymaterial","apikey","authtoken","accesstoken","refreshtoken","credential","bearer","signature","authorization","xprv","xpriv","wif"];function Nt(t){return t!=null&&typeof t=="object"&&!Array.isArray(t)}function qo(t){return String(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function Me(t){if(Array.isArray(t)){for(let e of t)Me(e);return}if(Nt(t))for(let[e,r]of Object.entries(t)){if(Co.some(n=>qo(e).includes(n)))throw new Error(`strategy service: secret-like field "${e}" is forbidden`);Me(r)}}function Bo(t){if(!Nt(t))throw new TypeError("strategy input must be a plain object");return Me(t),t}function Do(t,e){let r=e.nowMs??t.nowMs??Date.now();if(!Number.isInteger(r))throw new TypeError("nowMs must be an integer epoch milliseconds");return r}async function Re(t,e,r,n){if(Array.isArray(e.bars))return e.bars;let s=await(r.fetchBars??ae)({coin:t.market.coin,interval:t.market.interval,count:e.count??1500,endTime:e.endTime??n}),a=Array.isArray(s)?s:s?.bars;if(!Array.isArray(a))throw new Error("strategy history provider returned no bars");return a}function ve(t,e){let r=t.backtestOptions??{};if(!Nt(r))throw new TypeError("backtestOptions must be a plain object");return{...r,nowMs:e}}function Nr(t,e,r,n,o={}){let s=t.evidenceOptions??{};if(!Nt(s))throw new TypeError("evidenceOptions must be a plain object");return{...s,...o,strategy:e,bars:r,backtestOptions:ve(t,n)}}function Rr(){return Uo.join(jo.homedir(),".oracle","strategy-shadow.json")}function zo(t,e){return{perStrategyNotionalUsd:t.risk.maxNotionalUsd,maxLeverage:t.risk.maxLeverage,dailyLossCapUsd:t.risk.maxNotionalUsd*(t.risk.maxDailyLossPct/100),chainAllowlist:["hyperliquid"],assetAllowlist:[t.market.coin],expiresAt:Math.min(t.risk.expiresAt,e+864e5),killSwitchRequired:!0}}async function Vo(t,e={},r={}){let n=Bo(e),o=Do(n,r);if(t==="draft")return{strategy:xe(n.prompt,{nowMs:o})};if(t==="validate"){let s=V(n.strategy);if(s.strategy.risk.expiresAt<=o)throw new Error("strategy is expired");return{valid:!0,strategy:s.strategy,strategyHash:s.strategyHash,compilerHash:s.compilerHash,compilerVersion:s.compilerVersion,requiredSeries:s.requiredSeries}}if(t==="backtest"||t==="evidence"){let s=V(n.strategy),a=await Re(s.strategy,n,r,o);_t(s,a);let i=qt(Nr(n,s.strategy,a,o));return t==="evidence"?i:{backtest:ot(s.strategy,a,ve(n,o)),evidence:i}}if(t==="optimize"){let s=V(n.strategy),a=await Re(s.strategy,n,r,o);_t(s,a);let i=n.trainFraction,l=n.evidenceOptions?.trainFraction;if(i!=null&&l!=null&&i!==l)throw new TypeError("conflicting trainFraction controls are forbidden");let f=i??l??.7;if(typeof f!="number"||f<=0||f>=1)throw new TypeError("trainFraction must be in (0,1)");let u=a.slice(0,Math.floor(a.length*f)),c=n.options??{};if(!Nt(c))throw new TypeError("options must be a plain object");let d=me(s.strategy,u,{...c,...n.maxTrials==null?{}:{maxTrials:n.maxTrials},backtestOptions:ve(n,o)}),m=d.bestStrategy;return{strategy:m,optimization:d,evidence:qt(Nr(n,m,a,o,{trainFraction:f}))}}if(t==="shadow"){let s=zt({storePath:r.storePath??Rr(),clock:()=>o}),a=n.action;if(a==="start")return await s.start({strategy:n.strategy,evidenceId:n.evidenceId??n.evidence?.id??null});if(a==="list")return await s.list();if(a==="get")return await s.get(n.id);if(a==="stop")return await s.stop(n.id);if(a==="step"){let i=await s.get(n.id);if(!i)throw new Error(`shadow runner not found: ${n.id}`);let l=await Re(i.strategy,n,r,o);return _t(V(i.strategy),l),await s.step(n.id,l,n.stepOptions??{})}throw new Error(`unknown shadow action: ${a}`)}if(t==="prepare"){let s=V(n.strategy);if(typeof n.shadowId!="string"||!n.shadowId)throw new Error("strategy prepare requires a matching shadow runner id");let i=await zt({storePath:r.storePath??Rr(),clock:()=>o}).get(n.shadowId);if(!i)throw new Error("strategy prepare shadow runner not found");if(i.status!=="running")throw new Error("strategy prepare requires an active shadow runner");if(!Number.isFinite(i.cursor))throw new Error("strategy prepare requires a stepped shadow runner");if(i.strategyHash!==s.strategyHash||i.compilerHash!==s.compilerHash)throw new Error("strategy prepare shadow runner does not match strategy artifacts");if(i.evidenceId!==n.evidence?.id)throw new Error("strategy prepare shadow runner does not match evidence artifact");let l=n.caps??zo(s.strategy,o);return Ne({strategy:s.strategy,evidence:n.evidence,shadow:{id:i.id,stateHash:Tr(i),status:i.status,cursor:i.cursor,updatedAt:i.updatedAt},caps:l,nowMs:o,env:r.env??process.env})}throw new Error(`unknown strategy operation: ${t}`)}export{Er as EVIDENCE_STATUSES,de as MAX_OPTIMIZER_TRIALS,lt as STRATEGY_COMPILER_HASH,gt as STRATEGY_COMPILER_VERSION,Lt as STRATEGY_VERSION,B as StrategyDraftError,ut as StrategyValidationError,mt as applyParameterOverrides,be as assertEvidenceArtifact,ie as atr,ot as backtestStrategy,oe as bollinger,tr as canonicalStrategyJson,V as compileStrategy,ge as computeEvidenceArtifactId,zt as createShadowRunner,xe as draftStrategyFromPrompt,At as ema,qt as evaluateEvidence,ae as fetchHyperliquidStrategyBars,ur as intervalToMs,ne as macd,fr as normalizeHyperliquidCandles,z as normalizeStrategy,Ae as openShadowStore,me as optimizeStrategy,Ne as prepareStrategyLiveHandoff,re as rsi,Vo as runStrategyOperation,ee as sma,ft as strategyHash,Ht as validateStrategy};
@@ -0,0 +1 @@
1
+ var s=Object.freeze(["price","wallet","risk","execution","security","nft","governance","system"]),u=new Set(s);function n(e){if(!u.has(e))throw new TypeError(`Unknown watch category: ${String(e)}`);return e}function i(e={}){let r=e.subscribedCategories??[];if(!Array.isArray(r))throw new TypeError("subscribedCategories must be an array");return r}function c(){return{subscribedCategories:[]}}function f(e,r){n(r);let t=i(e);return t.includes(r)?{...e,subscribedCategories:[...t]}:{...e,subscribedCategories:[...t,r]}}function d(e,r){n(r);let t=i(e);return{...e,subscribedCategories:t.filter(o=>o!==r)}}function l({category:e,notify:r=!1,...t}={}){if(n(e),typeof r!="boolean")throw new TypeError("watch notify must be a boolean");return{...t,category:e,notify:r}}function a(e,r){return!(!r||r.notify!==!0||r.category!==e.category||e.watchId!==void 0&&r.id!==e.watchId)}function b(e,r=c(),t){if(!e||typeof e!="object")throw new TypeError("alert must be an object");return n(e.category),i(r).includes(e.category)?{deliver:!0,reason:"category-subscribed"}:a(e,t)?{deliver:!0,reason:"watch-opt-in"}:{deliver:!1,reason:"not-subscribed"}}function y(e,r,t){return b(e,r,t).deliver}export{s as WATCH_CATEGORIES,l as createWatch,c as defaultPreferences,b as evaluateAlert,y as shouldDeliverAlert,f as subscribe,d as unsubscribe};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oracle-agent/oracle",
3
- "version": "0.14.1",
3
+ "version": "0.16.0",
4
4
  "description": "Oracle: standalone prepare-only multichain agent control plane with optional Hermes integration. Policy-bounded intents for a user-signed wallet; the public package never takes your key.",
5
5
  "license": "BUSL-1.1",
6
6
  "type": "module",
@@ -26,62 +26,37 @@
26
26
  "node": ">=20.19.0"
27
27
  },
28
28
  "bin": {
29
- "oracle": "./bin/oracle.mjs",
30
- "oracle-data": "./bin/desk-server.mjs",
31
- "oracle-public": "./bin/oracle-public-server.mjs",
32
- "oracle-data-mcp": "./bin/oracle-data-mcp.mjs",
33
- "oracle-init": "./bin/oracle-init.mjs",
34
- "oracle-upgrade": "./bin/oracle-upgrade.mjs",
35
- "oracle-scan": "./bin/oracle-scan.mjs",
36
- "oracle-route": "./bin/oracle-route.mjs",
37
- "oracle-equities": "./bin/oracle-equities.mjs"
29
+ "oracle": "./dist/bin/oracle.mjs",
30
+ "oracle-data": "./dist/bin/desk-server.mjs",
31
+ "oracle-public": "./dist/bin/oracle-public-server.mjs",
32
+ "oracle-data-mcp": "./dist/bin/oracle-data-mcp.mjs",
33
+ "oracle-init": "./dist/bin/oracle-init.mjs",
34
+ "oracle-upgrade": "./dist/bin/oracle-upgrade.mjs",
35
+ "oracle-scan": "./dist/bin/oracle-scan.mjs",
36
+ "oracle-route": "./dist/bin/oracle-route.mjs",
37
+ "oracle-equities": "./dist/bin/oracle-equities.mjs"
38
38
  },
39
39
  "exports": {
40
- ".": "./src/index.mjs",
41
- "./farming": "./src/data/providers/farming.mjs",
42
- "./data": "./src/data/desk-data.mjs",
43
- "./policy": "./src/public-control/policy-schema.mjs",
44
- "./chains": "./src/chains.mjs",
45
- "./scanner": "./src/scanner/index.mjs",
46
- "./router": "./src/router/index.mjs",
47
- "./equities": "./src/equities/index.mjs",
48
- "./action-semantics": "./src/action-semantics.mjs",
49
- "./address-book": "./src/address-book.mjs",
50
- "./names": "./src/data/names.mjs",
51
- "./nft-gas-war": "./src/nft-gas-war-guard.mjs",
52
- "./prepare-envelope": "./src/prepare-envelope.mjs",
53
- "./connect": "./src/onboarding/harness-configs.mjs",
54
- "./receipts": "./src/action-receipts.mjs",
55
- "./risk": "./src/portfolio-risk.mjs",
56
- "./watch": "./src/watch-preferences.mjs",
57
- "./signals": "./src/signals/index.mjs",
58
- "./agent-grants": "./src/public-api/agent-grants.mjs"
59
- },
60
- "scripts": {
61
- "test": "ORACLE_TEST_ISOLATE_SECRETS=1 ORACLE_ROUTE_ATTESTATION_SECRET=oracle-unit-test-secret node --test test/*.test.mjs",
62
- "test:boundary": "ORACLE_TEST_ISOLATE_SECRETS=1 ORACLE_ROUTE_ATTESTATION_SECRET=oracle-unit-test-secret node --test test/custody-boundary.test.mjs",
63
- "e2e:solana-bitcoin": "node scripts/e2e-solana-bitcoin.mjs",
64
- "e2e:hypercore-staking": "node scripts/e2e-hypercore-staking.mjs",
65
- "start:data": "node bin/desk-server.mjs",
66
- "start:public": "node bin/oracle-public-server.mjs",
67
- "scan:public-apis": "node scripts/public-api-scan.mjs",
68
- "health": "node -e \"import('./src/data/desk-data.mjs').then(m=>m.data.health().then(h=>console.log(JSON.stringify(h,null,2))))\"",
69
- "init": "node bin/oracle-init.mjs",
70
- "init:apply": "node bin/oracle-init.mjs --apply",
71
- "scan": "node bin/oracle-scan.mjs",
72
- "verify:venues": "node scripts/verify-v3-venues.mjs",
73
- "route": "node bin/oracle-route.mjs",
74
- "scan:secrets": "node scripts/secret-scan.mjs",
75
- "test:count": "node scripts/check-test-count.mjs",
76
- "test:count:update": "node scripts/check-test-count.mjs --update",
77
- "test:protocol-templates": "RUN_PROTOCOL_TEMPLATE_TESTS=1 node --test test/protocol-templates.test.mjs",
78
- "protocol:gate": "node scripts/protocol-template-gate.mjs",
79
- "gate:docs": "node scripts/check-doc-drift.mjs",
80
- "gate:release": "npm run gate:docs && node --test test/flag-polarity.test.mjs",
81
- "build:dist": "node scripts/build-dist.mjs",
82
- "verify:dist": "node scripts/verify-dist.mjs",
83
- "publish:dist": "ORACLE_PUBLISH_STAGED=1 node scripts/publish-dist.mjs",
84
- "prepublishOnly": "node scripts/guard-publish.mjs"
40
+ ".": "./dist/index.mjs",
41
+ "./farming": "./dist/data/providers/farming.mjs",
42
+ "./data": "./dist/data/desk-data.mjs",
43
+ "./policy": "./dist/public-control/policy-schema.mjs",
44
+ "./chains": "./dist/chains.mjs",
45
+ "./scanner": "./dist/scanner/index.mjs",
46
+ "./router": "./dist/router/index.mjs",
47
+ "./equities": "./dist/equities/index.mjs",
48
+ "./action-semantics": "./dist/action-semantics.mjs",
49
+ "./address-book": "./dist/address-book.mjs",
50
+ "./names": "./dist/data/names.mjs",
51
+ "./nft-gas-war": "./dist/nft-gas-war-guard.mjs",
52
+ "./prepare-envelope": "./dist/prepare-envelope.mjs",
53
+ "./connect": "./dist/onboarding/harness-configs.mjs",
54
+ "./receipts": "./dist/action-receipts.mjs",
55
+ "./risk": "./dist/portfolio-risk.mjs",
56
+ "./watch": "./dist/watch-preferences.mjs",
57
+ "./signals": "./dist/signals/index.mjs",
58
+ "./strategy": "./dist/strategy/index.mjs",
59
+ "./agent-grants": "./dist/public-api/agent-grants.mjs"
85
60
  },
86
61
  "dependencies": {
87
62
  "@msgpack/msgpack": "^3.1.3",
@@ -92,32 +67,12 @@
92
67
  "viem": "^2.55.8"
93
68
  },
94
69
  "files": [
95
- "bin/",
96
- "src/",
97
- "!src/**/__pycache__/**",
98
- "profiles/",
99
- "skills/",
100
- "skins/",
101
- "plugins/",
70
+ "dist/",
102
71
  "public/",
103
72
  "artifacts/",
104
73
  "README.md",
105
74
  "SETUP.md",
106
75
  "LICENSE",
107
- "SECURITY.md",
108
- "CONTRIBUTING.md",
109
- "docs/",
110
- "examples/",
111
- "scripts/",
112
- "protocols/templates/**/src/**",
113
- "protocols/templates/**/test/**",
114
- "protocols/templates/**/foundry.toml",
115
- "protocols/templates/**/remappings.txt",
116
- "protocols/templates/**/SECURITY.md",
117
- "src/protocol-templates/**"
118
- ],
119
- "devDependencies": {
120
- "@scure/bip39": "^1.6.0",
121
- "esbuild": "^0.28.1"
122
- }
76
+ "SECURITY.md"
77
+ ]
123
78
  }
@@ -958,7 +958,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
958
958
  <a class="enter-cta primary" href="/downloads/">Download beta</a>
959
959
  <a class="enter-cta ghost" href="#cli">See the CLI</a>
960
960
  </div>
961
- <p class="hero-note-line">macOS · Windows · Linux &nbsp;/&nbsp; public CLI and desktop beta</p>
961
+ <p class="hero-note-line">macOS · Windows · Linux &nbsp;/&nbsp; desktop app or public CLI</p>
962
962
  </div>
963
963
 
964
964
  <figure class="hero-product">
@@ -997,10 +997,10 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
997
997
  <p class="section-label rv">Oracle CLI</p>
998
998
  <h2 class="section-title rv">One surface. <em>Every chain.</em></h2>
999
999
  <div class="cli-install rv">
1000
- <div class="cli-install-cmd"><code>npm i -g @oracle-agent/oracle</code></div>
1001
- <p class="cli-install-gate"><b>Locals Only</b> holders get 0% Oracle integrator fees. Everyone gets the same public CLI, desktop, source, and prepare-only product access.</p>
1000
+ <div class="cli-install-cmd"><code>npm install -g @oracle-agent/oracle</code></div>
1002
1001
  </div>
1003
- <p class="section-lede rv">The real Oracle shell, isolated from desktop chrome. Pin the active surface with <code style="color:var(--blue2)">/chain hyperliquid</code>, switch models with <code style="color:var(--blue2)">/model</code>, then ask naturally.</p>
1002
+ <p class="section-lede rv">The real Oracle shell, isolated from desktop chrome. No accounts, no servers. The CLI runs on your machine and reads straight from public RPCs.</p>
1003
+ <p class="section-lede rv">Pin the active surface with <code style="color:var(--blue2)">/chain hyperliquid</code>, switch models, ask naturally. Oracle reads, prices, and prepares — you sign.</p>
1004
1004
  <div class="convert-grid rv">
1005
1005
  <div>
1006
1006
  <figure class="cli-frame cli-proof">
@@ -1421,19 +1421,6 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1421
1421
  </div>
1422
1422
  </section>
1423
1423
 
1424
- <section class="section" id="custody" style="padding-top:clamp(48px,8vh,80px)">
1425
- <div class="strip-inner rv" style="border:1px solid var(--line);border-radius:16px;padding:22px 24px;display:flex;flex-wrap:wrap;gap:18px 28px;align-items:center;justify-content:space-between;background:linear-gradient(180deg, rgba(184,240,255,.05), transparent)">
1426
- <div class="strip-left">
1427
- <strong style="font-family:var(--display);font-weight:400;font-size:26px;display:block;margin-bottom:6px">You keep custody.</strong>
1428
- <span style="font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)">oracle never holds your keys</span>
1429
- </div>
1430
- <div class="strip-right" style="display:flex;flex-wrap:wrap;gap:10px">
1431
- <span class="pill on" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid rgba(184,240,255,.35);border-radius:999px;padding:9px 12px;color:var(--blue)">Multi-wallet</span>
1432
- <span class="pill on" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid rgba(184,240,255,.35);border-radius:999px;padding:9px 12px;color:var(--blue)">Per-wallet limits</span>
1433
- <span class="pill" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid var(--line);border-radius:999px;padding:9px 12px;color:var(--cool)">Revoke anytime</span>
1434
- </div>
1435
- </div>
1436
- </section>
1437
1424
  </main>
1438
1425
 
1439
1426
  <div class="mega-oracle rv" aria-hidden="true">oracle</div>
@@ -1464,6 +1451,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1464
1451
 
1465
1452
  var ICON = "https://icons.llamao.fi/icons/";
1466
1453
  var CHAINS = [
1454
+ { name: "Hyperliquid", id: "999", logo: "chains/rsz_hyperliquid", note: "hyperliquid agent", badge: "read" },
1467
1455
  { name: "Ethereum", id: "1", logo: "chains/rsz_ethereum", note: "evm / bridge agent", badge: "route" },
1468
1456
  { name: "Base", id: "8453", logo: "chains/rsz_base", note: "evm / bridge agent", badge: "route" },
1469
1457
  { name: "Arbitrum", id: "42161", logo: "chains/rsz_arbitrum", note: "evm / bridge agent", badge: "route" },
@@ -1472,7 +1460,6 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1472
1460
  { name: "Avalanche", id: "43114", logo: "chains/rsz_avalanche", note: "evm / bridge agent", badge: "route" },
1473
1461
  { name: "Polygon", id: "137", logo: "chains/rsz_polygon", note: "evm / bridge agent", badge: "route" },
1474
1462
  { name: "Robinhood", id: "4663", logo: "chains/rsz_robinhood", note: "robinhood agent", badge: "route" },
1475
- { name: "Hyperliquid", id: "999", logo: "chains/rsz_hyperliquid", note: "hyperliquid agent", badge: "read" },
1476
1463
  { name: "Abstract", id: "2741", logo: "chains/rsz_abstract", note: "open / add agent", badge: "read" },
1477
1464
  { name: "Stable", id: "988", logo: "chains/rsz_stable", note: "stable agent", badge: "read" },
1478
1465
  { name: "Solana", id: "SOL", logo: "chains/rsz_solana", note: "solana agent", badge: "route" },
@@ -960,7 +960,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
960
960
  <a class="enter-cta primary" href="/downloads/">Download beta</a>
961
961
  <a class="enter-cta ghost" href="#cli">See the CLI</a>
962
962
  </div>
963
- <p class="hero-note-line">macOS · Windows · Linux &nbsp;/&nbsp; public CLI and desktop beta</p>
963
+ <p class="hero-note-line">macOS · Windows · Linux &nbsp;/&nbsp; desktop app or public CLI</p>
964
964
  </div>
965
965
 
966
966
  <figure class="hero-product">
@@ -999,10 +999,10 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
999
999
  <p class="section-label rv">Oracle CLI</p>
1000
1000
  <h2 class="section-title rv">One surface. <em>Every chain.</em></h2>
1001
1001
  <div class="cli-install rv">
1002
- <div class="cli-install-cmd"><code>npm i -g @oracle-agent/oracle</code></div>
1003
- <p class="cli-install-gate"><b>Locals Only</b> holders get 0% Oracle integrator fees. Everyone gets the same public CLI, desktop, source, and prepare-only product access.</p>
1002
+ <div class="cli-install-cmd"><code>npm install -g @oracle-agent/oracle</code></div>
1004
1003
  </div>
1005
- <p class="section-lede rv">The real Oracle shell, isolated from desktop chrome. Pin the active surface with <code style="color:var(--blue2)">/chain hyperliquid</code>, switch models with <code style="color:var(--blue2)">/model</code>, then ask naturally.</p>
1004
+ <p class="section-lede rv">The real Oracle shell, isolated from desktop chrome. No accounts, no servers. The CLI runs on your machine and reads straight from public RPCs.</p>
1005
+ <p class="section-lede rv">Pin the active surface with <code style="color:var(--blue2)">/chain hyperliquid</code>, switch models, ask naturally. Oracle reads, prices, and prepares — you sign.</p>
1006
1006
  <div class="convert-grid rv">
1007
1007
  <div>
1008
1008
  <figure class="cli-frame cli-proof">
@@ -1423,19 +1423,6 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1423
1423
  </div>
1424
1424
  </section>
1425
1425
 
1426
- <section class="section" id="custody" style="padding-top:clamp(48px,8vh,80px)">
1427
- <div class="strip-inner rv" style="border:1px solid var(--line);border-radius:16px;padding:22px 24px;display:flex;flex-wrap:wrap;gap:18px 28px;align-items:center;justify-content:space-between;background:linear-gradient(180deg, rgba(140,106,63,.05), transparent)">
1428
- <div class="strip-left">
1429
- <strong style="font-family:var(--display);font-weight:400;font-size:26px;display:block;margin-bottom:6px">You keep custody.</strong>
1430
- <span style="font-family:var(--mono);font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--mute)">oracle never holds your keys</span>
1431
- </div>
1432
- <div class="strip-right" style="display:flex;flex-wrap:wrap;gap:10px">
1433
- <span class="pill on" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid rgba(140,106,63,.35);border-radius:999px;padding:9px 12px;color:var(--blue)">Multi-wallet</span>
1434
- <span class="pill on" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid rgba(140,106,63,.35);border-radius:999px;padding:9px 12px;color:var(--blue)">Per-wallet limits</span>
1435
- <span class="pill" style="font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid var(--line);border-radius:999px;padding:9px 12px;color:var(--cool)">Revoke anytime</span>
1436
- </div>
1437
- </div>
1438
- </section>
1439
1426
  </main>
1440
1427
 
1441
1428
  <div class="mega-oracle rv" aria-hidden="true">oracle</div>
@@ -1466,6 +1453,7 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1466
1453
 
1467
1454
  var ICON = "https://icons.llamao.fi/icons/";
1468
1455
  var CHAINS = [
1456
+ { name: "Hyperliquid", id: "999", logo: "chains/rsz_hyperliquid", note: "hyperliquid agent", badge: "read" },
1469
1457
  { name: "Ethereum", id: "1", logo: "chains/rsz_ethereum", note: "evm / bridge agent", badge: "route" },
1470
1458
  { name: "Base", id: "8453", logo: "chains/rsz_base", note: "evm / bridge agent", badge: "route" },
1471
1459
  { name: "Arbitrum", id: "42161", logo: "chains/rsz_arbitrum", note: "evm / bridge agent", badge: "route" },
@@ -1474,7 +1462,6 @@ footer{margin-top:clamp(72px,12vh,120px);border-top:1px solid var(--line);paddin
1474
1462
  { name: "Avalanche", id: "43114", logo: "chains/rsz_avalanche", note: "evm / bridge agent", badge: "route" },
1475
1463
  { name: "Polygon", id: "137", logo: "chains/rsz_polygon", note: "evm / bridge agent", badge: "route" },
1476
1464
  { name: "Robinhood", id: "4663", logo: "chains/rsz_robinhood", note: "robinhood agent", badge: "route" },
1477
- { name: "Hyperliquid", id: "999", logo: "chains/rsz_hyperliquid", note: "hyperliquid agent", badge: "read" },
1478
1465
  { name: "Abstract", id: "2741", logo: "chains/rsz_abstract", note: "open / add agent", badge: "read" },
1479
1466
  { name: "Stable", id: "988", logo: "chains/rsz_stable", note: "stable agent", badge: "read" },
1480
1467
  { name: "Solana", id: "SOL", logo: "chains/rsz_solana", note: "solana agent", badge: "route" },
@@ -28,10 +28,10 @@ section{padding-top:72px;scroll-margin-top:90px}.sub{color:var(--muted);line-hei
28
28
  <header><p class="eyebrow">Public release</p><h1>Install Oracle.<br><em>Your wallet signs.</em></h1><p class="lede">The CLI, desktop beta, source, research tools, and unsigned transaction preparation are public to everyone. No wallet connection or NFT is required to download or run Oracle.</p></header>
29
29
  <aside class="policy"><h2>Locals Only means 0% Oracle fees</h2><p>A Locals Only NFT waives the <b>Oracle integrator fee</b>. It does not unlock the product, arm execution, waive provider or network costs, or change the keyless prepare-only custody boundary.</p></aside>
30
30
  <section id="cli"><p class="eyebrow">Oracle CLI</p><h2>Install from npm</h2><p class="sub">Requires Node 20.19 or newer. npm <code>latest</code> contains the full public runtime.</p><div class="install"><div class="cmd"><code id="cmd">npm i -g @oracle-agent/oracle</code><button class="copy" id="copy" type="button">Copy</button></div><div class="meta"><span>public npm package</span><span>keyless</span><span>prepare-only</span></div></div></section>
31
- <section id="desktop"><p class="eyebrow">Desktop beta · 0.2.0</p><h2>Native installers</h2><p class="sub">Each installer bundles the same public runtime. Download directly, then verify it against the published SHA-256 manifest.</p><div class="artifacts">
32
- <div class="artifact" data-artifact="Oracle-0.2.0.AppImage"><div><h3>Linux</h3><small>AppImage · x64</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.0 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-0.2.0.AppImage" download>Download</a></div>
33
- <div class="artifact" data-artifact="Oracle-0.2.0-arm64.dmg"><div><h3>macOS</h3><small>DMG · Apple silicon</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.0 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-0.2.0-arm64.dmg" download>Download</a></div>
34
- <div class="artifact" data-artifact="Oracle-Setup-0.2.0.exe"><div><h3>Windows</h3><small>NSIS installer · x64</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.0 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-Setup-0.2.0.exe" download>Download</a></div>
31
+ <section id="desktop"><p class="eyebrow">Desktop beta · 0.2.1</p><h2>Native installers</h2><p class="sub">Each installer bundles the same public runtime. Download directly, then verify it against the published SHA-256 manifest.</p><div class="artifacts">
32
+ <div class="artifact" data-artifact="Oracle-0.2.1.AppImage"><div><h3>Linux</h3><small>AppImage · x64</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.1 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-0.2.1.AppImage" download>Download</a></div>
33
+ <div class="artifact" data-artifact="Oracle-0.2.1-arm64.dmg"><div><h3>macOS</h3><small>DMG · Apple silicon</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.1 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-0.2.1-arm64.dmg" download>Download</a></div>
34
+ <div class="artifact" data-artifact="Oracle-Setup-0.2.1.exe"><div><h3>Windows</h3><small>NSIS installer · x64</small></div><div class="artifact-meta"><span class="build">Oracle 0.2.1 beta</span></div><code class="hash" data-hash>checksum loading</code><a class="dl-btn" href="/downloads/artifacts/Oracle-Setup-0.2.1.exe" download>Download</a></div>
35
35
  </div><p class="platform-note">Checksums: <a class="checksum" href="/downloads/artifacts/SHA256SUMS.txt">SHA256SUMS.txt</a>. Beta installers may trigger macOS Gatekeeper or Windows SmartScreen when a build is not notarized or CA-signed. Oracle never asks for a private key, seed phrase, or wallet approval.</p></section>
36
36
  </main>
37
37
  <footer><div class="nav-inner"><span>oracle · locals only labs</span><span>public / self-custody / prepare-only</span></div></footer>