@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
@@ -1,424 +0,0 @@
1
- // Oracle Public API — connect-agent contract (Slice D).
2
- //
3
- // BFF-safe, self-custodial contract that turns a user's "connect my agent"
4
- // request into an UNSIGNED grant payload the USER signs with their own wallet.
5
- //
6
- // Hard boundaries for this file:
7
- // - NEVER signs anything. There is no signer, no key material, no signature
8
- // field ever populated here. The output hands back the exact bytes the
9
- // user must sign themselves; signing happens client-side in the user's
10
- // own wallet, never on a server.
11
- // - Imports ONLY from the assigned public peers
12
- // (src/public-control/policy-schema.mjs, session-key-model.mjs).
13
- // Never from the private executor stack (get-signer, keystore,
14
- // exec-policy, local-signer/*, adapters/*).
15
- // - Oracle Control is deterministic authorization: same input => same
16
- // canonical bytes => same grant id. No advisory logic here (that is
17
- // Oracle Router's job and Router output never gates anything here).
18
- // - Fail-closed no-secret invariant: every object returned from this module
19
- // is recursively scanned and the call THROWS if anything shaped like a
20
- // private key, session secret, bearer token, keystore path, or signer URL
21
- // is present. See assertNoSecretMaterial().
22
-
23
- import {
24
- GRANT_VERSION,
25
- GrantValidationError,
26
- normalizeGrant,
27
- canonicalizeGrant,
28
- grantId,
29
- isReadonlyAction,
30
- } from "../public-control/policy-schema.mjs";
31
-
32
- export const CONNECT_REQUEST_KIND = "oracle-connect-request";
33
- export const UNSIGNED_GRANT_KIND = "oracle-unsigned-grant";
34
-
35
- /** Identifier for how the signable bytes are derived: utf-8 encoding of the
36
- * canonical grant JSON produced by policy-schema's canonicalizeGrant(). */
37
- export const SIGNING_SCHEME = "oracle-grant-canonical-json-utf8-v1";
38
-
39
- // ---------------------------------------------------------------------------
40
- // No-secret invariant (fail closed)
41
- // ---------------------------------------------------------------------------
42
-
43
- export class SecretLeakError extends Error {
44
- constructor(path, rule) {
45
- super(`secret material must never appear in a public API object (at ${path}, rule: ${rule})`);
46
- this.name = "SecretLeakError";
47
- this.path = path;
48
- this.rule = rule;
49
- }
50
- }
51
-
52
- /** Key names that must never appear on any object we return. */
53
- const FORBIDDEN_KEY_RE =
54
- /(private[_-]?key|secret|bearer|keystore|mnemonic|seed[_-]?phrase|passphrase|password|api[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?token|signer[_-]?url|signature)/i;
55
-
56
- /** Short wallet-export aliases need exact normalized matching. Substring
57
- * matching `wif`, for example, would incorrectly reject an unrelated key such
58
- * as `swift`. Removing common separators catches snake/kebab/spaced variants
59
- * without widening those short aliases into arbitrary words. */
60
- const FORBIDDEN_KEY_ALIASES = Object.freeze(["privkey", "wif", "xprv", "seed"]);
61
-
62
- function isForbiddenKeyName(key) {
63
- const text = String(key);
64
- const normalized = text.toLowerCase().replace(/[\s._-]+/g, "");
65
- return FORBIDDEN_KEY_RE.test(text) || FORBIDDEN_KEY_ALIASES.includes(normalized);
66
- }
67
-
68
- /** String-value shapes that must never appear in any object we return. */
69
- const FORBIDDEN_VALUE_RULES = Object.freeze([
70
- // 32-byte hex — the shape of a raw EVM private key / session secret. Public
71
- // grant material never legitimately carries a 0x + 64-hex value (addresses
72
- // are 40 hex; the grant id is bare sha256 hex), so this fails closed.
73
- { rule: "raw-32-byte-hex-key", re: /^0x[0-9a-fA-F]{64}$/ },
74
- // Same 32 bytes WITHOUT the 0x prefix, as the entire string. A bare-hex
75
- // private key (the shape ethers and most wallet exports hand you) must not
76
- // pass just because it lacks the prefix.
77
- //
78
- // Deliberately anchored: an embedded/substring match would flag legitimate
79
- // prose that quotes a public sha256 identifier (the human-readable grant
80
- // render says "grant <id>"), and a scanner that cries wolf on normal output
81
- // gets disabled. Smuggling a key inside a longer string is still caught at
82
- // the serialized layer for any non-allowlisted field.
83
- { rule: "raw-32-byte-hex-bare", re: /^[0-9a-fA-F]{64}$/ },
84
- // BIP-32 private extended keys. Public xpub/tpub/ypub/zpub identifiers are
85
- // intentionally not matched; only their private-key counterparts fail.
86
- { rule: "extended-private-key", re: /\b(?:xprv|tprv|yprv|zprv)[1-9A-HJ-NP-Za-km-z]{107}\b/ },
87
- // Bitcoin WIF (mainnet 5/K/L, testnet uncompressed 9 or compressed c) —
88
- // base58, 51-52 chars.
89
- { rule: "bitcoin-wif", re: /\b[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}\b/ },
90
- // BIP-39 mnemonic: 12/15/18/21/24 lowercase words. Detect a long run of
91
- // space-separated short alpha words rather than shipping the wordlist.
92
- { rule: "bip39-mnemonic", re: /\b(?:[a-z]{3,8}\s+){11,23}[a-z]{3,8}\b/ },
93
- { rule: "bearer-token", re: /bearer\s+[A-Za-z0-9._~+/=-]+/i },
94
- { rule: "pem-private-key", re: /-----BEGIN[A-Z ]*PRIVATE KEY-----/ },
95
- { rule: "keystore-path", re: /keystore/i },
96
- { rule: "signer-url", re: /https?:\/\/\S*sign/i },
97
- { rule: "authorization-header", re: /authorization\s*:/i },
98
- ]);
99
-
100
- /**
101
- * Field names whose values are legitimately 64-hex and are NOT secrets:
102
- * sha256 grant ids, tx hashes, block hashes, canonical digests. These are
103
- * public identifiers — the whole point of a grant id is that it is quotable.
104
- *
105
- * Deliberately EXCLUDED: `nonce` and `salt`. Those are caller-supplied on the
106
- * public path, so allowlisting them would let anyone launder key material
107
- * through the scan just by naming the field `nonce`. Oracle's own nonces are
108
- * short opaque strings, not 32-byte hex, so nothing legitimate is lost.
109
- */
110
- const HEX64_ALLOWED_KEYS = Object.freeze([
111
- "grantid",
112
- "id",
113
- "hash",
114
- "sha256",
115
- "sha256hex",
116
- "checksum",
117
- "txhash",
118
- "transactionhash",
119
- "blockhash",
120
- "digest",
121
- "userophash",
122
- "commithash",
123
- "prevhash",
124
- "intenthash",
125
- "canonicalhash",
126
- "payloadhash",
127
- "requestid",
128
- ]);
129
-
130
- /**
131
- * Strip values that are legitimately 64-hex public identifiers before running
132
- * the raw-key shape rules, so a sha256 grant id does not read as a private key.
133
- * Only exact-match 64-hex values on an allowlisted key are removed; a 64-hex
134
- * string sitting anywhere else still trips the rule.
135
- */
136
- function maskAllowedHex64(json) {
137
- return json.replace(
138
- /"([A-Za-z0-9_-]+)"\s*:\s*"(?:0x)?([0-9a-fA-F]{64})"/g,
139
- (match, key) =>
140
- HEX64_ALLOWED_KEYS.includes(String(key).toLowerCase().replace(/[_-]/g, ""))
141
- ? `"${key}":"<hex64>"`
142
- : match
143
- );
144
- }
145
- /**
146
- * Scan the SERIALIZED form of a payload.
147
- *
148
- * Scanning the object graph alone is not sufficient: `toJSON()`, getters,
149
- * symbol keys, non-enumerable properties and BigInt coercion all let a value
150
- * reach the wire in a shape the graph walk never visited. Verified: an object
151
- * `{ nested: { toJSON: () => "<private key>" } }` passes a graph-only scan and
152
- * then serializes the raw key into the response body.
153
- *
154
- * So the authoritative check runs against the exact bytes we are about to
155
- * write. Whatever JSON.stringify produces is what the client sees, and that is
156
- * what we scan. Returns the JSON string when clean; throws SecretLeakError
157
- * otherwise.
158
- */
159
- export function assertSerializedNoSecrets(value) {
160
- let json;
161
- try {
162
- json = JSON.stringify(value);
163
- } catch (e) {
164
- // A payload we cannot serialize (circular, BigInt, throwing toJSON) must
165
- // not be sent at all — fail closed rather than guess.
166
- throw new SecretLeakError("$", `unserializable-payload: ${String(e?.message || e)}`);
167
- }
168
- if (json === undefined) return "null";
169
-
170
- // Public 64-hex identifiers (grant ids, tx/block hashes, sha256 digests) are
171
- // masked first so they do not read as raw key material.
172
- const scanned = maskAllowedHex64(json);
173
-
174
- for (const { rule, re } of FORBIDDEN_VALUE_RULES) {
175
- if (re.test(scanned)) throw new SecretLeakError("$<serialized>", rule);
176
- }
177
-
178
- // Embedded key material. The per-string rules are anchored (so human-readable
179
- // prose quoting a public grant id does not trip them), but at the serialized
180
- // layer a 0x-prefixed 32-byte value has no legitimate reason to appear
181
- // anywhere in a public response — addresses are 40 hex, and every public
182
- // 64-hex identifier was masked above. This is what catches a key smuggled in
183
- // via toJSON(), a getter, or concatenated into a longer string.
184
- const embedded = /(?:^|[^0-9a-fA-Fx])0x[0-9a-fA-F]{64}(?![0-9a-fA-F])/;
185
- if (embedded.test(scanned)) {
186
- throw new SecretLeakError("$<serialized>", "raw-32-byte-hex-embedded");
187
- }
188
- // Parse the exact serialized bytes with a reviver so escaped or toJSON-made
189
- // key names receive the same normalization as real object properties. This
190
- // avoids maintaining a second, inevitably drifting key-name regex.
191
- JSON.parse(json, (key, item) => {
192
- if (key && isForbiddenKeyName(key)) {
193
- throw new SecretLeakError(`$<serialized>.${key}`, "forbidden-key-name");
194
- }
195
- return item;
196
- });
197
- return json;
198
- }
199
-
200
- /**
201
- * Recursively scan a value (objects, arrays, Maps, Sets, typed arrays) for
202
- * anything shaped like secret material. Throws SecretLeakError on the first
203
- * hit — fail closed. Returns the value unchanged when clean, so it can be
204
- * used inline: `return assertNoSecretMaterial(result)`.
205
- *
206
- * `keyHint` carries the property name a string was found under, so a 64-hex
207
- * value on a known public identifier (grantId, txHash, ...) is not mistaken
208
- * for raw key material. A 64-hex string under any other key still trips.
209
- */
210
- export function assertNoSecretMaterial(value, path = "$", seen = new Set(), keyHint = "") {
211
- if (value == null) return value;
212
- if (typeof value === "string") {
213
- const hex64Ok = HEX64_ALLOWED_KEYS.includes(
214
- String(keyHint).toLowerCase().replace(/[_-]/g, "")
215
- );
216
- for (const { rule, re } of FORBIDDEN_VALUE_RULES) {
217
- if (hex64Ok && rule.startsWith("raw-32-byte-hex")) continue;
218
- if (re.test(value)) throw new SecretLeakError(path, rule);
219
- }
220
- return value;
221
- }
222
- if (typeof value !== "object") return value;
223
- if (seen.has(value)) return value;
224
- seen.add(value);
225
-
226
- if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;
227
- if (value instanceof Map) {
228
- for (const [k, v] of value.entries()) {
229
- if (typeof k === "string" && isForbiddenKeyName(k)) {
230
- throw new SecretLeakError(`${path}[${JSON.stringify(k)}]`, "forbidden-key-name");
231
- }
232
- assertNoSecretMaterial(k, `${path}[key]`, seen);
233
- assertNoSecretMaterial(v, `${path}[${String(k)}]`, seen);
234
- }
235
- return value;
236
- }
237
- if (value instanceof Set) {
238
- let i = 0;
239
- for (const v of value.values()) assertNoSecretMaterial(v, `${path}[${i++}]`, seen);
240
- return value;
241
- }
242
- if (Array.isArray(value)) {
243
- value.forEach((v, i) => assertNoSecretMaterial(v, `${path}[${i}]`, seen));
244
- return value;
245
- }
246
- for (const [k, v] of Object.entries(value)) {
247
- if (isForbiddenKeyName(k)) {
248
- throw new SecretLeakError(`${path}.${k}`, "forbidden-key-name");
249
- }
250
- assertNoSecretMaterial(v, `${path}.${k}`, seen, k);
251
- }
252
- return value;
253
- }
254
-
255
- // ---------------------------------------------------------------------------
256
- // Helpers
257
- // ---------------------------------------------------------------------------
258
-
259
- function deepFreeze(value) {
260
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
261
- Object.freeze(value);
262
- for (const v of Object.values(value)) deepFreeze(v);
263
- }
264
- return value;
265
- }
266
-
267
- function toUnixSeconds(v, label) {
268
- const n = typeof v === "string" ? Number(v.trim()) : Number(v);
269
- if (!Number.isSafeInteger(n) || n <= 0) {
270
- throw new GrantValidationError([{ field: label, message: "must be a positive unix-seconds integer" }]);
271
- }
272
- return n;
273
- }
274
-
275
- function requiredReferenceNow(opts) {
276
- if (opts?.now == null) {
277
- throw new GrantValidationError([
278
- { field: "opts.now", message: "explicit reference time is required for live grant construction" },
279
- ]);
280
- }
281
- return toUnixSeconds(opts.now, "opts.now");
282
- }
283
-
284
- /** Deterministic UTC ISO string from unix seconds. */
285
- function isoUtc(unixSeconds) {
286
- return new Date(unixSeconds * 1000).toISOString();
287
- }
288
-
289
- /** Deterministic, purely-presentational human render of a normalized grant.
290
- * Presentation only — it never adds, removes, or reinterprets authority and
291
- * only surfaces public grant material. */
292
- function renderUnsignedGrant(grant, id) {
293
- const readonlyOnly = grant.actions.every((a) => isReadonlyAction(a));
294
- return [
295
- "ORACLE — CONNECT AGENT (unsigned grant, you sign it, we never do)",
296
- "=================================================================",
297
- `Grant ID: ${id}`,
298
- `Version: ${GRANT_VERSION}`,
299
- `Chain: ${grant.chainId}`,
300
- `Agent: ${grant.agentAddress}`,
301
- `Your account: ${grant.accountAddress}`,
302
- `Actions: ${grant.actions.join(", ")}`,
303
- `Targets: ${grant.targets.length ? grant.targets.join(", ") : "(none — read/simulate only)"}`,
304
- `Max value: ${grant.maxValueWei} wei`,
305
- `Max gas: ${grant.maxGasWei} wei`,
306
- `Max slippage: ${grant.maxSlippageBps} bps`,
307
- `Expires: ${isoUtc(grant.expiresAt)} (unix ${grant.expiresAt})`,
308
- `Nonce: ${grant.nonce}`,
309
- `Revocation: ${grant.revocationKey}`,
310
- "-----------------------------------------------------------------",
311
- readonlyOnly
312
- ? "Scope: read/simulate only — this grant cannot move funds."
313
- : "Scope: includes state-changing actions bounded by the caps above.",
314
- "Self-custodial: this payload is UNSIGNED and contains public data only.",
315
- "Sign the bytes below with YOUR wallet; Oracle never holds your keys.",
316
- ].join("\n");
317
- }
318
-
319
- // ---------------------------------------------------------------------------
320
- // Public contract
321
- // ---------------------------------------------------------------------------
322
-
323
- /**
324
- * Turn raw user inputs into a validated connect request.
325
- *
326
- * Accepts the canonical grant fields (see policy-schema REQUIRED_FIELDS).
327
- * Every live construction requires explicit `opts.now` (unix seconds).
328
- * Convenience: instead of `expiresAt` the caller may pass `ttlSeconds`.
329
- * Determinism requires the library caller to supply `now`; the HTTP boundary
330
- * overwrites caller time with the server clock.
331
- *
332
- * Throws GrantValidationError on any invalid/unknown/missing field (the
333
- * schema fails closed on unknown fields, wildcard actions, empty targets for
334
- * state-changing scopes, etc). Never signs anything.
335
- *
336
- * @returns frozen { kind, version, grant } where grant is the normalized
337
- * canonical grant from policy-schema.
338
- */
339
- export function buildConnectRequest(input = {}, opts = {}) {
340
- if (input == null || typeof input !== "object" || Array.isArray(input)) {
341
- throw new GrantValidationError([{ field: "request", message: "request must be a plain object" }]);
342
- }
343
- const now = requiredReferenceNow(opts);
344
-
345
- const { ttlSeconds, ...rest } = input;
346
- const fields = { ...rest };
347
-
348
- if (ttlSeconds != null) {
349
- if (fields.expiresAt != null) {
350
- throw new GrantValidationError([
351
- { field: "ttlSeconds", message: "pass either ttlSeconds or expiresAt, not both" },
352
- ]);
353
- }
354
- const ttl = toUnixSeconds(ttlSeconds, "ttlSeconds");
355
- fields.expiresAt = now + ttl;
356
- }
357
-
358
- const grant = normalizeGrant(fields, {
359
- now,
360
- allowWildcardActions: opts.allowWildcardActions === true,
361
- });
362
-
363
- const request = deepFreeze({
364
- kind: CONNECT_REQUEST_KIND,
365
- version: GRANT_VERSION,
366
- grant,
367
- });
368
- return assertNoSecretMaterial(request);
369
- }
370
-
371
- /**
372
- * Assemble the UNSIGNED grant payload for a connect request (or raw grant
373
- * input). Returns everything a BFF/browser needs to show the user what they
374
- * are approving and exactly which bytes to sign — and nothing else:
375
- *
376
- * payload — { version, grantId, grant, canonical } canonical grant data
377
- * signing — { scheme, message, bytesHex, byteLength, sha256 } where
378
- * `message` is the exact canonical JSON string and `bytesHex`
379
- * is the 0x-hex of its utf-8 bytes: THE bytes the user signs.
380
- * render — deterministic human-readable review text
381
- * unsigned — always true; this module never signs and never will.
382
- *
383
- * Deterministic: identical grants (any key order / address casing / numeric
384
- * representation) produce byte-identical canonical/message/bytesHex/grantId.
385
- *
386
- * Fail-closed: requires explicit `opts.now`, throws GrantValidationError on bad
387
- * input, and throws SecretLeakError if the assembled object ever carried
388
- * secret-shaped material.
389
- */
390
- export function assembleUnsignedGrant(requestOrInput = {}, opts = {}) {
391
- const now = requiredReferenceNow(opts);
392
- const raw =
393
- requestOrInput && requestOrInput.kind === CONNECT_REQUEST_KIND
394
- ? requestOrInput.grant
395
- : requestOrInput;
396
-
397
- const grant = normalizeGrant(raw, {
398
- now,
399
- allowWildcardActions: opts.allowWildcardActions === true,
400
- });
401
- const canonical = canonicalizeGrant(grant);
402
- const id = grantId(grant);
403
- const bytes = Buffer.from(canonical, "utf8");
404
-
405
- const result = deepFreeze({
406
- kind: UNSIGNED_GRANT_KIND,
407
- unsigned: true,
408
- payload: deepFreeze({
409
- version: GRANT_VERSION,
410
- grantId: id,
411
- grant,
412
- canonical,
413
- }),
414
- signing: deepFreeze({
415
- scheme: SIGNING_SCHEME,
416
- message: canonical,
417
- bytesHex: `0x${bytes.toString("hex")}`,
418
- byteLength: bytes.length,
419
- sha256: id,
420
- }),
421
- render: renderUnsignedGrant(grant, id),
422
- });
423
- return assertNoSecretMaterial(result);
424
- }
@@ -1,142 +0,0 @@
1
- // Oracle Public API — grant reads (Slice D).
2
- //
3
- // Pure, deterministic read functions over an INJECTED grant store. No DB, no
4
- // chain, no clock fallback: callers pass an array/Map of grant records plus an
5
- // explicit `now` (unix seconds). Same inputs always produce the same output.
6
- //
7
- // Imports ONLY from the assigned public peers (policy-schema.mjs) and the
8
- // sibling connect-agent.mjs for the shared no-secret invariant. Never from the
9
- // private executor stack.
10
- //
11
- // Store shape (injected, caller-owned):
12
- // - an Array or Map whose entries are either
13
- // a) a raw grant object (policy-schema shape), or
14
- // b) a wrapper record { grant, revoked?, revokedAt? }.
15
- // - revocation may also be supplied out-of-band via opts.revoked: a Set /
16
- // array / Map-like of grant ids and/or revocation keys, or a function
17
- // (id, grant) => boolean.
18
- //
19
- // Fail-closed rules:
20
- // - records that do not validate against the public policy schema are
21
- // EXCLUDED from active listings (a grant that cannot validate cannot
22
- // authorize anything).
23
- // - `now` is required for listActiveGrants; without a reference time we
24
- // cannot prove liveness, so we refuse rather than guess.
25
- // - every returned object passes the no-secret invariant scan.
26
-
27
- import { validateGrant, grantId, isExpired } from "../public-control/policy-schema.mjs";
28
- import { assertNoSecretMaterial } from "./connect-agent.mjs";
29
-
30
- export const GRANT_STATUS = Object.freeze({
31
- ACTIVE: "active",
32
- EXPIRED: "expired",
33
- REVOKED: "revoked",
34
- INVALID: "invalid",
35
- });
36
-
37
- function toRecords(store) {
38
- if (store == null) return [];
39
- if (Array.isArray(store)) return store;
40
- if (store instanceof Map) return [...store.values()];
41
- if (typeof store[Symbol.iterator] === "function") return [...store];
42
- throw new TypeError("grant store must be an array, Map, or iterable of grant records");
43
- }
44
-
45
- function unwrap(record) {
46
- if (record && typeof record === "object" && !Array.isArray(record) && record.grant != null) {
47
- return {
48
- grant: record.grant,
49
- revoked: record.revoked === true || record.revokedAt != null,
50
- };
51
- }
52
- return { grant: record, revoked: false };
53
- }
54
-
55
- function toSafeNow(now) {
56
- const n = typeof now === "string" ? Number(now.trim()) : Number(now);
57
- if (!Number.isSafeInteger(n) || n < 0) {
58
- throw new TypeError("an explicit unix-seconds `now` is required (deterministic liveness, no wall-clock fallback)");
59
- }
60
- return n;
61
- }
62
-
63
- function isRevokedBy(revoked, id, grant) {
64
- if (revoked == null) return false;
65
- if (typeof revoked === "function") return revoked(id, grant) === true;
66
- const keys = [id, grant.revocationKey];
67
- if (revoked instanceof Set) return keys.some((k) => revoked.has(k));
68
- if (Array.isArray(revoked)) return keys.some((k) => revoked.includes(k));
69
- if (typeof revoked.has === "function") return keys.some((k) => revoked.has(k));
70
- return false;
71
- }
72
-
73
- /**
74
- * Classify a single store record. Returns { status, id, grant } where grant
75
- * is the normalized public grant (null when invalid). Pure + deterministic.
76
- */
77
- export function classifyGrant(record, { now, revoked } = {}) {
78
- const nowSec = toSafeNow(now);
79
- const { grant: raw, revoked: recordRevoked } = unwrap(record);
80
- const { ok, grant } = validateGrant(raw);
81
- if (!ok) return { status: GRANT_STATUS.INVALID, id: null, grant: null };
82
- const id = grantId(grant);
83
- // Revocation takes precedence over expiry (matches session-key-model
84
- // semantics: a revoked-then-expired grant still reports "revoked").
85
- if (recordRevoked || isRevokedBy(revoked, id, grant)) {
86
- return { status: GRANT_STATUS.REVOKED, id, grant };
87
- }
88
- if (isExpired(grant, nowSec)) return { status: GRANT_STATUS.EXPIRED, id, grant };
89
- return { status: GRANT_STATUS.ACTIVE, id, grant };
90
- }
91
-
92
- /**
93
- * List grants that are currently ACTIVE: valid under the public policy
94
- * schema, not expired at `now`, and not revoked (per record flag or the
95
- * injected `revoked` source). Invalid records are silently excluded
96
- * (fail closed — they cannot authorize anything).
97
- *
98
- * Optional filters: { agentAddress, accountAddress, chainId }.
99
- *
100
- * @returns frozen array of { id, grant } sorted by id (deterministic order).
101
- */
102
- export function listActiveGrants(store, { now, revoked, agentAddress, accountAddress, chainId } = {}) {
103
- const nowSec = toSafeNow(now);
104
- const wantAgent = agentAddress != null ? String(agentAddress).trim().toLowerCase() : null;
105
- const wantAccount = accountAddress != null ? String(accountAddress).trim().toLowerCase() : null;
106
- const wantChain = chainId != null ? Number(chainId) : null;
107
-
108
- const out = [];
109
- for (const record of toRecords(store)) {
110
- const { status, id, grant } = classifyGrant(record, { now: nowSec, revoked });
111
- if (status !== GRANT_STATUS.ACTIVE) continue;
112
- if (wantAgent != null && grant.agentAddress !== wantAgent) continue;
113
- if (wantAccount != null && grant.accountAddress !== wantAccount) continue;
114
- if (wantChain != null && grant.chainId !== wantChain) continue;
115
- out.push(Object.freeze({ id, grant }));
116
- }
117
- out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
118
- return assertNoSecretMaterial(Object.freeze(out));
119
- }
120
-
121
- /**
122
- * Look up a single grant by its public grant id. Returns
123
- * { id, status, grant } or null when no record in the store matches.
124
- * Unlike listActiveGrants this also surfaces expired/revoked grants (with
125
- * their status) so a UI can explain WHY a grant is not active — but invalid
126
- * records never match (they have no trustworthy id).
127
- */
128
- export function getGrant(store, id, { now, revoked } = {}) {
129
- const nowSec = toSafeNow(now);
130
- const wanted = String(id ?? "").trim().toLowerCase();
131
- if (!/^[0-9a-f]{64}$/.test(wanted)) return null;
132
- for (const record of toRecords(store)) {
133
- const res = classifyGrant(record, { now: nowSec, revoked });
134
- if (res.status === GRANT_STATUS.INVALID) continue;
135
- if (res.id === wanted) {
136
- return assertNoSecretMaterial(
137
- Object.freeze({ id: res.id, status: res.status, grant: res.grant })
138
- );
139
- }
140
- }
141
- return null;
142
- }