@oracle-agent/oracle 0.11.0 → 0.13.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 (487) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +13 -516
  3. package/bin/oracle.mjs +19 -27
  4. package/package.json +15 -98
  5. package/CONTRIBUTING.md +0 -98
  6. package/SECURITY.md +0 -89
  7. package/SETUP.md +0 -381
  8. package/artifacts/inscription/oracle-was-here-preview.png +0 -0
  9. package/artifacts/inscription/oracle-was-here.svg +0 -1
  10. package/artifacts/specialist-packs/oracle-full-crypto.json +0 -295
  11. package/bin/desk-server.mjs +0 -440
  12. package/bin/oracle-data-mcp.mjs +0 -1019
  13. package/bin/oracle-init.mjs +0 -496
  14. package/bin/oracle-public-server.mjs +0 -36
  15. package/bin/oracle-route.mjs +0 -254
  16. package/bin/oracle-scan.mjs +0 -192
  17. package/bin/oracle-upgrade.mjs +0 -42
  18. package/docs/adding-a-chain.md +0 -229
  19. package/docs/architecture.md +0 -138
  20. package/docs/cli.md +0 -47
  21. package/docs/connectors.md +0 -13
  22. package/docs/oracle-pack-standard.md +0 -29
  23. package/docs/profiles.md +0 -151
  24. package/docs/public-surface.md +0 -133
  25. package/examples/add-a-chain.mjs +0 -65
  26. package/examples/oracle-pack-template.mjs +0 -38
  27. package/examples/research-a-token.mjs +0 -70
  28. package/plugins/oracle-owner-gate/__init__.py +0 -227
  29. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  30. package/profiles/_template/SOUL.md +0 -54
  31. package/profiles/_template/profile.json +0 -22
  32. package/profiles/bitcoin-agent/SOUL.md +0 -31
  33. package/profiles/bitcoin-agent/profile.json +0 -32
  34. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  35. package/profiles/hyperliquid-agent/profile.json +0 -37
  36. package/profiles/oracle/SOUL.md +0 -107
  37. package/profiles/oracle/profile.json +0 -39
  38. package/profiles/polymarket-agent/SOUL.md +0 -35
  39. package/profiles/polymarket-agent/profile.json +0 -34
  40. package/profiles/profile.schema.json +0 -90
  41. package/profiles/protocol-builder/SOUL.md +0 -57
  42. package/profiles/protocol-builder/profile.json +0 -39
  43. package/profiles/robinhood-agent/SOUL.md +0 -53
  44. package/profiles/robinhood-agent/profile.json +0 -40
  45. package/profiles/solana-agent/SOUL.md +0 -37
  46. package/profiles/solana-agent/profile.json +0 -37
  47. package/profiles/stable-agent/SOUL.md +0 -43
  48. package/profiles/stable-agent/profile.json +0 -37
  49. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  50. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  51. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  52. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  53. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  54. package/public/agent-connect/app.js +0 -84
  55. package/public/agent-connect/index.html +0 -83
  56. package/public/agent-connect/styles.css +0 -70
  57. package/public/index.html +0 -12
  58. package/public/oracle-console/app.js +0 -272
  59. package/public/oracle-console/bitcoin-wallets.js +0 -206
  60. package/public/oracle-console/index.html +0 -91
  61. package/public/oracle-console/styles.css +0 -239
  62. package/public/oracle-splash/assets/cli-chain-hyperliquid.jpg +0 -0
  63. package/public/oracle-splash/assets/hero/orb.avif +0 -0
  64. package/public/oracle-splash/assets/hero/orb.webm +0 -0
  65. package/public/oracle-splash/assets/llms/claude.svg +0 -1
  66. package/public/oracle-splash/assets/llms/codex-icon.svg +0 -1
  67. package/public/oracle-splash/assets/llms/codex.svg +0 -1
  68. package/public/oracle-splash/assets/llms/cursor-icon.svg +0 -12
  69. package/public/oracle-splash/assets/llms/cursor.svg +0 -17
  70. package/public/oracle-splash/assets/llms/deepseek.svg +0 -1
  71. package/public/oracle-splash/assets/llms/gemini-icon.svg +0 -1
  72. package/public/oracle-splash/assets/llms/gemini.svg +0 -1
  73. package/public/oracle-splash/assets/llms/grok.svg +0 -8
  74. package/public/oracle-splash/assets/llms/hermes.png +0 -0
  75. package/public/oracle-splash/assets/llms/kimi-icon.svg +0 -1
  76. package/public/oracle-splash/assets/llms/kimi.svg +0 -1
  77. package/public/oracle-splash/assets/llms/manus.svg +0 -18
  78. package/public/oracle-splash/assets/llms/openclaw.svg +0 -22
  79. package/public/oracle-splash/assets/llms/perplexity.svg +0 -1
  80. package/public/oracle-splash/assets/llms/qwen.svg +0 -1
  81. package/public/oracle-splash/assets/llms/windsurf.svg +0 -1
  82. package/public/oracle-splash/assets/protocols/abcdex.png +0 -0
  83. package/public/oracle-splash/assets/protocols/across.png +0 -0
  84. package/public/oracle-splash/assets/protocols/aerodrome.png +0 -0
  85. package/public/oracle-splash/assets/protocols/balancer.png +0 -0
  86. package/public/oracle-splash/assets/protocols/cowswap.png +0 -0
  87. package/public/oracle-splash/assets/protocols/curve.png +0 -0
  88. package/public/oracle-splash/assets/protocols/dreamcash.png +0 -0
  89. package/public/oracle-splash/assets/protocols/felix.png +0 -0
  90. package/public/oracle-splash/assets/protocols/gmx.png +0 -0
  91. package/public/oracle-splash/assets/protocols/hyena.png +0 -0
  92. package/public/oracle-splash/assets/protocols/hyperbeat.png +0 -0
  93. package/public/oracle-splash/assets/protocols/hyperliquid.png +0 -0
  94. package/public/oracle-splash/assets/protocols/hyperswap.png +0 -0
  95. package/public/oracle-splash/assets/protocols/jupiter.png +0 -0
  96. package/public/oracle-splash/assets/protocols/kinetiq.png +0 -0
  97. package/public/oracle-splash/assets/protocols/lfj.png +0 -0
  98. package/public/oracle-splash/assets/protocols/lifi.png +0 -0
  99. package/public/oracle-splash/assets/protocols/magic-eden.png +0 -0
  100. package/public/oracle-splash/assets/protocols/morpho.png +0 -0
  101. package/public/oracle-splash/assets/protocols/odos.png +0 -0
  102. package/public/oracle-splash/assets/protocols/oneinch.png +0 -0
  103. package/public/oracle-splash/assets/protocols/opensea.png +0 -0
  104. package/public/oracle-splash/assets/protocols/pancakeswap.png +0 -0
  105. package/public/oracle-splash/assets/protocols/paragon.png +0 -0
  106. package/public/oracle-splash/assets/protocols/paraswap.png +0 -0
  107. package/public/oracle-splash/assets/protocols/pendle.png +0 -0
  108. package/public/oracle-splash/assets/protocols/polymarket.png +0 -0
  109. package/public/oracle-splash/assets/protocols/quickswap.png +0 -0
  110. package/public/oracle-splash/assets/protocols/relay.png +0 -0
  111. package/public/oracle-splash/assets/protocols/stargate.png +0 -0
  112. package/public/oracle-splash/assets/protocols/tradexyz.png +0 -0
  113. package/public/oracle-splash/assets/protocols/uniswap.png +0 -0
  114. package/public/oracle-splash/assets/protocols/velodrome.png +0 -0
  115. package/public/oracle-splash/assets/protocols/ventuals.png +0 -0
  116. package/public/oracle-splash/assets/wordmarks/across-icon.webp +0 -0
  117. package/public/oracle-splash/assets/wordmarks/across.svg +0 -4
  118. package/public/oracle-splash/assets/wordmarks/aerodrome.svg +0 -23
  119. package/public/oracle-splash/assets/wordmarks/balancer.svg +0 -3
  120. package/public/oracle-splash/assets/wordmarks/cowswap.svg +0 -1
  121. package/public/oracle-splash/assets/wordmarks/curve.png +0 -0
  122. package/public/oracle-splash/assets/wordmarks/gmx.svg +0 -13
  123. package/public/oracle-splash/assets/wordmarks/hop-icon.webp +0 -0
  124. package/public/oracle-splash/assets/wordmarks/hyena.svg +0 -7
  125. package/public/oracle-splash/assets/wordmarks/hyperliquid.svg +0 -21
  126. package/public/oracle-splash/assets/wordmarks/hyperswap.svg +0 -13
  127. package/public/oracle-splash/assets/wordmarks/jupiter.svg +0 -35
  128. package/public/oracle-splash/assets/wordmarks/kinetiq.svg +0 -1
  129. package/public/oracle-splash/assets/wordmarks/lfj.webp +0 -0
  130. package/public/oracle-splash/assets/wordmarks/lifi.png +0 -0
  131. package/public/oracle-splash/assets/wordmarks/magic-eden.svg +0 -1
  132. package/public/oracle-splash/assets/wordmarks/markets.svg +0 -1
  133. package/public/oracle-splash/assets/wordmarks/morpho.svg +0 -1
  134. package/public/oracle-splash/assets/wordmarks/odos.svg +0 -3
  135. package/public/oracle-splash/assets/wordmarks/oneinch-icon.webp +0 -0
  136. package/public/oracle-splash/assets/wordmarks/oneinch.svg +0 -6
  137. package/public/oracle-splash/assets/wordmarks/opensea-icon.svg +0 -17
  138. package/public/oracle-splash/assets/wordmarks/opensea.svg +0 -1
  139. package/public/oracle-splash/assets/wordmarks/outcome.svg +0 -16
  140. package/public/oracle-splash/assets/wordmarks/pancakeswap.svg +0 -18
  141. package/public/oracle-splash/assets/wordmarks/paragon.svg +0 -9
  142. package/public/oracle-splash/assets/wordmarks/paraswap.svg +0 -16
  143. package/public/oracle-splash/assets/wordmarks/pendle.png +0 -0
  144. package/public/oracle-splash/assets/wordmarks/polymarket.png +0 -0
  145. package/public/oracle-splash/assets/wordmarks/quickswap.png +0 -0
  146. package/public/oracle-splash/assets/wordmarks/relay.svg +0 -8
  147. package/public/oracle-splash/assets/wordmarks/satflow-icon.png +0 -0
  148. package/public/oracle-splash/assets/wordmarks/stargate-icon.webp +0 -0
  149. package/public/oracle-splash/assets/wordmarks/stargate.svg +0 -15
  150. package/public/oracle-splash/assets/wordmarks/uniswap.svg +0 -18
  151. package/public/oracle-splash/assets/wordmarks/velodrome.svg +0 -84
  152. package/public/oracle-splash/assets/wordmarks/xyz.svg +0 -12
  153. package/public/oracle-splash/assets/wordmarks/zerox-icon.webp +0 -0
  154. package/public/oracle-splash/brand/aave.webp +0 -0
  155. package/public/oracle-splash/brand/aavev2.webp +0 -0
  156. package/public/oracle-splash/brand/aborean.webp +0 -0
  157. package/public/oracle-splash/brand/across.webp +0 -0
  158. package/public/oracle-splash/brand/aerodrome.webp +0 -0
  159. package/public/oracle-splash/brand/afi.webp +0 -0
  160. package/public/oracle-splash/brand/arcus.webp +0 -0
  161. package/public/oracle-splash/brand/aster.webp +0 -0
  162. package/public/oracle-splash/brand/avant.webp +0 -0
  163. package/public/oracle-splash/brand/balancer.webp +0 -0
  164. package/public/oracle-splash/brand/beefy.webp +0 -0
  165. package/public/oracle-splash/brand/benqi.webp +0 -0
  166. package/public/oracle-splash/brand/bestinslot.ico +0 -0
  167. package/public/oracle-splash/brand/bitfi.webp +0 -0
  168. package/public/oracle-splash/brand/bonkswap.webp +0 -0
  169. package/public/oracle-splash/brand/bouncebit.webp +0 -0
  170. package/public/oracle-splash/brand/camelot.webp +0 -0
  171. package/public/oracle-splash/brand/compound.webp +0 -0
  172. package/public/oracle-splash/brand/concrete.webp +0 -0
  173. package/public/oracle-splash/brand/cow.webp +0 -0
  174. package/public/oracle-splash/brand/curve.webp +0 -0
  175. package/public/oracle-splash/brand/derive.webp +0 -0
  176. package/public/oracle-splash/brand/dolomite.webp +0 -0
  177. package/public/oracle-splash/brand/eigenlayer.webp +0 -0
  178. package/public/oracle-splash/brand/ekubo.webp +0 -0
  179. package/public/oracle-splash/brand/ethena.webp +0 -0
  180. package/public/oracle-splash/brand/etherfi.webp +0 -0
  181. package/public/oracle-splash/brand/etherfiborrow.webp +0 -0
  182. package/public/oracle-splash/brand/felix.webp +0 -0
  183. package/public/oracle-splash/brand/fluid.webp +0 -0
  184. package/public/oracle-splash/brand/fluxbeam.webp +0 -0
  185. package/public/oracle-splash/brand/folks.webp +0 -0
  186. package/public/oracle-splash/brand/fortyacres.webp +0 -0
  187. package/public/oracle-splash/brand/gainsnetwork.webp +0 -0
  188. package/public/oracle-splash/brand/gassss.webp +0 -0
  189. package/public/oracle-splash/brand/gmx.webp +0 -0
  190. package/public/oracle-splash/brand/harmonix.webp +0 -0
  191. package/public/oracle-splash/brand/hlorderbook.webp +0 -0
  192. package/public/oracle-splash/brand/hlp.webp +0 -0
  193. package/public/oracle-splash/brand/hop.webp +0 -0
  194. package/public/oracle-splash/brand/hyperbeat.webp +0 -0
  195. package/public/oracle-splash/brand/hyperlend.webp +0 -0
  196. package/public/oracle-splash/brand/hyperliquid.webp +0 -0
  197. package/public/oracle-splash/brand/hyperliquidhpl.webp +0 -0
  198. package/public/oracle-splash/brand/hyperliquidspot.webp +0 -0
  199. package/public/oracle-splash/brand/hyperswap.webp +0 -0
  200. package/public/oracle-splash/brand/hypha.webp +0 -0
  201. package/public/oracle-splash/brand/joedex.webp +0 -0
  202. package/public/oracle-splash/brand/jupiter.webp +0 -0
  203. package/public/oracle-splash/brand/kelp.webp +0 -0
  204. package/public/oracle-splash/brand/kinetiq.webp +0 -0
  205. package/public/oracle-splash/brand/kmhype.webp +0 -0
  206. package/public/oracle-splash/brand/kona.webp +0 -0
  207. package/public/oracle-splash/brand/konalend.webp +0 -0
  208. package/public/oracle-splash/brand/lfj.webp +0 -0
  209. package/public/oracle-splash/brand/lido.webp +0 -0
  210. package/public/oracle-splash/brand/lifi.webp +0 -0
  211. package/public/oracle-splash/brand/lighter.webp +0 -0
  212. package/public/oracle-splash/brand/lista.webp +0 -0
  213. package/public/oracle-splash/brand/loopedhype.webp +0 -0
  214. package/public/oracle-splash/brand/lorenzo.webp +0 -0
  215. package/public/oracle-splash/brand/magic-eden.webp +0 -0
  216. package/public/oracle-splash/brand/magiceden.webp +0 -0
  217. package/public/oracle-splash/brand/mempool.png +0 -0
  218. package/public/oracle-splash/brand/meteora.webp +0 -0
  219. package/public/oracle-splash/brand/morpho.webp +0 -0
  220. package/public/oracle-splash/brand/myriad.webp +0 -0
  221. package/public/oracle-splash/brand/noxa.webp +0 -0
  222. package/public/oracle-splash/brand/odos.webp +0 -0
  223. package/public/oracle-splash/brand/oneinch.webp +0 -0
  224. package/public/oracle-splash/brand/openbook.webp +0 -0
  225. package/public/oracle-splash/brand/opensea.webp +0 -0
  226. package/public/oracle-splash/brand/orca.webp +0 -0
  227. package/public/oracle-splash/brand/ordinals.png +0 -0
  228. package/public/oracle-splash/brand/ostium.webp +0 -0
  229. package/public/oracle-splash/brand/pancakeswap.webp +0 -0
  230. package/public/oracle-splash/brand/pendle.webp +0 -0
  231. package/public/oracle-splash/brand/perena.webp +0 -0
  232. package/public/oracle-splash/brand/pharaoh.webp +0 -0
  233. package/public/oracle-splash/brand/phoenix.webp +0 -0
  234. package/public/oracle-splash/brand/polymarket.webp +0 -0
  235. package/public/oracle-splash/brand/polynomial.webp +0 -0
  236. package/public/oracle-splash/brand/projectx.webp +0 -0
  237. package/public/oracle-splash/brand/pumpfun.webp +0 -0
  238. package/public/oracle-splash/brand/quickswap.webp +0 -0
  239. package/public/oracle-splash/brand/rain.webp +0 -0
  240. package/public/oracle-splash/brand/raydium.webp +0 -0
  241. package/public/oracle-splash/brand/relay.webp +0 -0
  242. package/public/oracle-splash/brand/rocketpool.webp +0 -0
  243. package/public/oracle-splash/brand/saber.webp +0 -0
  244. package/public/oracle-splash/brand/sakuraswap.webp +0 -0
  245. package/public/oracle-splash/brand/sanctum.webp +0 -0
  246. package/public/oracle-splash/brand/satflow.png +0 -0
  247. package/public/oracle-splash/brand/sierra.webp +0 -0
  248. package/public/oracle-splash/brand/sky.webp +0 -0
  249. package/public/oracle-splash/brand/solv.webp +0 -0
  250. package/public/oracle-splash/brand/spark.webp +0 -0
  251. package/public/oracle-splash/brand/sparksavings.webp +0 -0
  252. package/public/oracle-splash/brand/sphere.webp +0 -0
  253. package/public/oracle-splash/brand/ssv.webp +0 -0
  254. package/public/oracle-splash/brand/stabble.webp +0 -0
  255. package/public/oracle-splash/brand/stableswap.webp +0 -0
  256. package/public/oracle-splash/brand/stakewise.webp +0 -0
  257. package/public/oracle-splash/brand/stargate.webp +0 -0
  258. package/public/oracle-splash/brand/sthype.webp +0 -0
  259. package/public/oracle-splash/brand/sushiswap.webp +0 -0
  260. package/public/oracle-splash/brand/unisat.png +0 -0
  261. package/public/oracle-splash/brand/uniswap.webp +0 -0
  262. package/public/oracle-splash/brand/uniswapv2.webp +0 -0
  263. package/public/oracle-splash/brand/uniswapv4.webp +0 -0
  264. package/public/oracle-splash/brand/unit.webp +0 -0
  265. package/public/oracle-splash/brand/velodrome.webp +0 -0
  266. package/public/oracle-splash/brand/velora.webp +0 -0
  267. package/public/oracle-splash/brand/venus.webp +0 -0
  268. package/public/oracle-splash/brand/wbeth.webp +0 -0
  269. package/public/oracle-splash/brand/xsy.webp +0 -0
  270. package/public/oracle-splash/brand/yieldyak.webp +0 -0
  271. package/public/oracle-splash/brand/zerobase.webp +0 -0
  272. package/public/oracle-splash/brand/zerox.webp +0 -0
  273. package/public/oracle-splash/favicon.ico +0 -0
  274. package/public/oracle-splash/favicon.svg +0 -6
  275. package/public/oracle-splash/index.html +0 -1558
  276. package/public/oracle-splash/mesh-graph.png +0 -0
  277. package/public/oracle-splash/mesh-graph.svg +0 -216
  278. package/scripts/adversarial-bench.mjs +0 -114
  279. package/scripts/build-inscription.py +0 -230
  280. package/scripts/check-doc-drift.mjs +0 -123
  281. package/scripts/check-test-count.mjs +0 -105
  282. package/scripts/e2e-hl-markets.mjs +0 -21
  283. package/scripts/e2e-hl-perps.mjs +0 -48
  284. package/scripts/e2e-hypercore-staking.mjs +0 -128
  285. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  286. package/scripts/protocol-template-gate.mjs +0 -15
  287. package/scripts/public-api-scan.mjs +0 -23
  288. package/scripts/secret-scan.mjs +0 -181
  289. package/scripts/verify-v3-venues.mjs +0 -192
  290. package/skills/balance/SKILL.md +0 -176
  291. package/skills/oracle-action-semantics/SKILL.md +0 -40
  292. package/skills/oracle-best-execution/SKILL.md +0 -127
  293. package/skills/oracle-bitcoin/SKILL.md +0 -53
  294. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  295. package/skills/oracle-chat/SKILL.md +0 -61
  296. package/skills/oracle-chat/chain.SKILL.md +0 -31
  297. package/skills/oracle-chat/setup.SKILL.md +0 -37
  298. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  299. package/skills/oracle-contract-research/SKILL.md +0 -55
  300. package/skills/oracle-desk/SKILL.md +0 -58
  301. package/skills/oracle-dex-launch/SKILL.md +0 -38
  302. package/skills/oracle-grants/SKILL.md +0 -69
  303. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  304. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  305. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  306. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  307. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  308. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  309. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  310. package/skills/oracle-polymarket/SKILL.md +0 -60
  311. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  312. package/skills/oracle-protocol-security/SKILL.md +0 -60
  313. package/skills/oracle-public-product/SKILL.md +0 -44
  314. package/skills/oracle-receipts/SKILL.md +0 -52
  315. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  316. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  317. package/skills/oracle-solana/SKILL.md +0 -65
  318. package/skills/oracle-solana-nft/SKILL.md +0 -54
  319. package/skills/oracle-token-research/SKILL.md +0 -67
  320. package/skins/oracle.yaml +0 -56
  321. package/src/action-receipts.mjs +0 -265
  322. package/src/action-semantics.mjs +0 -62
  323. package/src/address-book.mjs +0 -208
  324. package/src/agent-auth.mjs +0 -206
  325. package/src/approval-guard.mjs +0 -282
  326. package/src/attestation-secret.mjs +0 -88
  327. package/src/audit-log.mjs +0 -196
  328. package/src/auth/oauth.mjs +0 -672
  329. package/src/auto-slippage.mjs +0 -378
  330. package/src/capability-posture.mjs +0 -125
  331. package/src/chains.mjs +0 -62
  332. package/src/cli/chain-catalog.mjs +0 -215
  333. package/src/cli/chain-state.mjs +0 -74
  334. package/src/cli/commands/auth.mjs +0 -193
  335. package/src/cli/commands/bootstrap.mjs +0 -87
  336. package/src/cli/commands/chain.mjs +0 -143
  337. package/src/cli/commands/chat.mjs +0 -434
  338. package/src/cli/commands/credential.mjs +0 -9
  339. package/src/cli/commands/data-mcp.mjs +0 -18
  340. package/src/cli/commands/data.mjs +0 -75
  341. package/src/cli/commands/doctor.mjs +0 -136
  342. package/src/cli/commands/help.mjs +0 -7
  343. package/src/cli/commands/init.mjs +0 -27
  344. package/src/cli/commands/mcp.mjs +0 -142
  345. package/src/cli/commands/model.mjs +0 -99
  346. package/src/cli/commands/prepare.mjs +0 -12
  347. package/src/cli/commands/public.mjs +0 -20
  348. package/src/cli/commands/route.mjs +0 -12
  349. package/src/cli/commands/runner.mjs +0 -9
  350. package/src/cli/commands/scan.mjs +0 -12
  351. package/src/cli/commands/setup.mjs +0 -275
  352. package/src/cli/commands/sign.mjs +0 -21
  353. package/src/cli/commands/signer.mjs +0 -9
  354. package/src/cli/commands/upgrade.mjs +0 -12
  355. package/src/cli/commands/vault.mjs +0 -9
  356. package/src/cli/commands/version.mjs +0 -22
  357. package/src/cli/first-run.mjs +0 -23
  358. package/src/cli/kernel.mjs +0 -239
  359. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  360. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  361. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  362. package/src/cli/mcp-targets/codex.mjs +0 -41
  363. package/src/cli/mcp-targets/shared.mjs +0 -61
  364. package/src/cli/messaging-platforms.mjs +0 -209
  365. package/src/cli/model-config.mjs +0 -70
  366. package/src/cli/operator-dispatch.mjs +0 -258
  367. package/src/cli/oracle-harness.py +0 -415
  368. package/src/cli/paths.mjs +0 -83
  369. package/src/cli/runtime.mjs +0 -351
  370. package/src/cli/setup-state.mjs +0 -168
  371. package/src/cli/spawn-child.mjs +0 -43
  372. package/src/data/catalog.mjs +0 -585
  373. package/src/data/desk-data.mjs +0 -695
  374. package/src/data/http.mjs +0 -253
  375. package/src/data/provider-endpoint.mjs +0 -94
  376. package/src/data/providers/aerodrome.mjs +0 -245
  377. package/src/data/providers/balancer.mjs +0 -209
  378. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  379. package/src/data/providers/bitcoin-meta.mjs +0 -378
  380. package/src/data/providers/blockscout.mjs +0 -14
  381. package/src/data/providers/bridges.mjs +0 -242
  382. package/src/data/providers/cowswap.mjs +0 -415
  383. package/src/data/providers/curve.mjs +0 -201
  384. package/src/data/providers/defillama.mjs +0 -88
  385. package/src/data/providers/dexscreener.mjs +0 -43
  386. package/src/data/providers/evm-rpc.mjs +0 -225
  387. package/src/data/providers/geckoterminal.mjs +0 -34
  388. package/src/data/providers/gmx.mjs +0 -496
  389. package/src/data/providers/hl-assets.mjs +0 -165
  390. package/src/data/providers/hl-info.mjs +0 -108
  391. package/src/data/providers/hl-markets.mjs +0 -210
  392. package/src/data/providers/hl-outcome.mjs +0 -61
  393. package/src/data/providers/hl-perps.mjs +0 -387
  394. package/src/data/providers/hl-staking.mjs +0 -353
  395. package/src/data/providers/hl-ws.mjs +0 -119
  396. package/src/data/providers/hyperevm-dex.mjs +0 -49
  397. package/src/data/providers/jupiter-venues.mjs +0 -119
  398. package/src/data/providers/jupiter.mjs +0 -315
  399. package/src/data/providers/lifi.mjs +0 -151
  400. package/src/data/providers/magiceden-sol.mjs +0 -406
  401. package/src/data/providers/morpho.mjs +0 -177
  402. package/src/data/providers/nft-gallery.mjs +0 -163
  403. package/src/data/providers/nft-portfolio.mjs +0 -494
  404. package/src/data/providers/odos.mjs +0 -156
  405. package/src/data/providers/oneinch.mjs +0 -174
  406. package/src/data/providers/opensea-multichain.mjs +0 -136
  407. package/src/data/providers/opensea-nft.mjs +0 -371
  408. package/src/data/providers/paraswap.mjs +0 -118
  409. package/src/data/providers/pendle.mjs +0 -188
  410. package/src/data/providers/poly-clob.mjs +0 -283
  411. package/src/data/providers/poly-public.mjs +0 -96
  412. package/src/data/providers/poly-ws.mjs +0 -103
  413. package/src/data/providers/portfolio-history.mjs +0 -394
  414. package/src/data/providers/portfolio.mjs +0 -594
  415. package/src/data/providers/rfq.mjs +0 -15
  416. package/src/data/providers/rh-agent.mjs +0 -59
  417. package/src/data/providers/satflow.mjs +0 -341
  418. package/src/data/providers/signed-material-guard.mjs +0 -108
  419. package/src/data/providers/solana-rpc.mjs +0 -197
  420. package/src/data/providers/uniswap-v3.mjs +0 -349
  421. package/src/data/providers/uniswap-v4.mjs +0 -414
  422. package/src/data/providers/zerox.mjs +0 -167
  423. package/src/data/public-api-scan.mjs +0 -61
  424. package/src/data/quote-placeholder.mjs +0 -31
  425. package/src/exact-integer.mjs +0 -72
  426. package/src/exec-policy.mjs +0 -455
  427. package/src/flags.mjs +0 -15
  428. package/src/fresh-window.mjs +0 -76
  429. package/src/gmx-attestation.mjs +0 -176
  430. package/src/index.mjs +0 -100
  431. package/src/nft-gas-war-guard.mjs +0 -139
  432. package/src/onboarding/agent-keys.mjs +0 -161
  433. package/src/onboarding/harness-configs.mjs +0 -102
  434. package/src/onboarding/index.mjs +0 -18
  435. package/src/onboarding/tiers.mjs +0 -139
  436. package/src/oracle-env.mjs +0 -47
  437. package/src/portfolio-risk.mjs +0 -170
  438. package/src/prepare-envelope.mjs +0 -204
  439. package/src/profile-upgrade.mjs +0 -277
  440. package/src/protocol-execution.mjs +0 -84
  441. package/src/protocol-templates/gate.mjs +0 -179
  442. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  443. package/src/public-api/buzz-integration.mjs +0 -256
  444. package/src/public-api/connect-agent.mjs +0 -416
  445. package/src/public-api/grants.mjs +0 -142
  446. package/src/public-api/http.mjs +0 -389
  447. package/src/public-control/aa-adapter.mjs +0 -402
  448. package/src/public-control/build-registry.mjs +0 -227
  449. package/src/public-control/bundler-client.mjs +0 -357
  450. package/src/public-control/grant-indexer.mjs +0 -296
  451. package/src/public-control/policy-render.mjs +0 -69
  452. package/src/public-control/policy-schema.mjs +0 -318
  453. package/src/public-control/runtime-config.mjs +0 -275
  454. package/src/public-control/session-key-model.mjs +0 -374
  455. package/src/public-control/session-orchestrator.mjs +0 -412
  456. package/src/rfq/intent.mjs +0 -180
  457. package/src/rfq/sources.mjs +0 -181
  458. package/src/route-attestation.mjs +0 -132
  459. package/src/router/best-execution.mjs +0 -326
  460. package/src/router/index.mjs +0 -226
  461. package/src/router/prepare-bridge.mjs +0 -289
  462. package/src/router/prepare-route.mjs +0 -398
  463. package/src/router/proposal.mjs +0 -311
  464. package/src/router/risk-classifier.mjs +0 -119
  465. package/src/router/route-sources.mjs +0 -364
  466. package/src/scanner/chains.config.mjs +0 -430
  467. package/src/scanner/contract.mjs +0 -270
  468. package/src/scanner/evm-scanner.mjs +0 -394
  469. package/src/scanner/index.mjs +0 -9
  470. package/src/scanner/v2-venue.mjs +0 -335
  471. package/src/scanner/v3-venue.mjs +0 -290
  472. package/src/scopes.mjs +0 -44
  473. package/src/sell-simulation.mjs +0 -167
  474. package/src/signals/engine.mjs +0 -146
  475. package/src/signals/index.mjs +0 -1
  476. package/src/token-transfer-guard.mjs +0 -188
  477. package/src/tui/app.mjs +0 -438
  478. package/src/tui/backend.mjs +0 -145
  479. package/src/tui/format.mjs +0 -272
  480. package/src/tui/gateway-client.mjs +0 -177
  481. package/src/tui/input.mjs +0 -501
  482. package/src/tui/renderer.mjs +0 -443
  483. package/src/tui/standalone-client.mjs +0 -666
  484. package/src/tui/theme.mjs +0 -81
  485. package/src/vault-attestation.mjs +0 -146
  486. package/src/venues.mjs +0 -206
  487. package/src/watch-preferences.mjs +0 -85
@@ -1,256 +0,0 @@
1
- // Oracle ↔ Buzz integration API (public plane).
2
- //
3
- // Buzz should integrate Oracle **via HTTP**, not by embedding our private
4
- // executor. This module is the contract Buzz (or any partner) can call:
5
- //
6
- // 1) Discovery GET /public/buzz
7
- // 2) Grants existing /public/connect/* + /public/grants/*
8
- // 3) Shared auth POST /public/buzz/auth/verify (capability tokens)
9
- // 4) Shared audit POST /public/buzz/audit/{append,verify,entries}
10
- //
11
- // Hard boundaries (same as the rest of the public plane):
12
- // - No private keys, no bearer mint, no broadcast.
13
- // - Minting capabilities stays client-side (owner wallet signs).
14
- // - Audit detail is scanned for secret shapes before append/response.
15
- // - Fail closed on unknown fields / bad capability tags.
16
-
17
- import {
18
- verifyCapability,
19
- authPreimage,
20
- AUTH_DOMAIN,
21
- } from "../agent-auth.mjs";
22
- import {
23
- appendAudit,
24
- verifyChain,
25
- getEntries,
26
- AUDIT_ACTIONS,
27
- GENESIS_HASH,
28
- } from "../audit-log.mjs";
29
- import { assertNoSecretMaterial, SecretLeakError } from "./connect-agent.mjs";
30
-
31
- export const BUZZ_API_VERSION = 1;
32
- export const BUZZ_INTEGRATION_ID = "oracle-buzz-http-v1";
33
-
34
- /** Public-safe audit actions partners may append. */
35
- export const BUZZ_PUBLIC_AUDIT_ACTIONS = Object.freeze([
36
- AUDIT_ACTIONS.AUTH_GRANT,
37
- AUDIT_ACTIONS.AUTH_OK,
38
- AUDIT_ACTIONS.AUTH_FAIL,
39
- "connect.assemble",
40
- "connect.bound",
41
- "grant.revoke",
42
- "grant.active",
43
- "buzz.ping",
44
- ]);
45
-
46
- export function buildBuzzCatalog({ baseUrl = null } = {}) {
47
- const base = baseUrl || "";
48
- return Object.freeze({
49
- ok: true,
50
- integration: BUZZ_INTEGRATION_ID,
51
- version: BUZZ_API_VERSION,
52
- plane: "public",
53
- unsigned: true,
54
- custody: "user-signs",
55
- defaultPosture: "DISARMED",
56
- summary:
57
- "Oracle exposes grants, capability verify, and audit over HTTP so Buzz (or any client) can integrate without house keys.",
58
- doAll: {
59
- api: true,
60
- sharedAuth: true,
61
- sharedAudit: true,
62
- note: "One surface — not three separate products. Buzz calls these routes; user still signs grants/capabilities.",
63
- },
64
- endpoints: Object.freeze([
65
- {
66
- method: "GET",
67
- path: `${base}/public/buzz`,
68
- purpose: "Discovery catalog for Buzz integrators",
69
- },
70
- {
71
- method: "GET",
72
- path: `${base}/public/health`,
73
- purpose: "Liveness",
74
- },
75
- {
76
- method: "GET",
77
- path: `${base}/public/config`,
78
- purpose: "Public custody config (Privy flags, no secrets)",
79
- },
80
- {
81
- method: "POST",
82
- path: `${base}/public/connect/request`,
83
- purpose: "Build human-readable connect request",
84
- },
85
- {
86
- method: "POST",
87
- path: `${base}/public/connect/assemble`,
88
- purpose: "Assemble unsigned grant for user personal_sign",
89
- },
90
- {
91
- method: "POST",
92
- path: `${base}/public/grants/active`,
93
- purpose: "List active grants from injected store",
94
- },
95
- {
96
- method: "POST",
97
- path: `${base}/public/grants/get`,
98
- purpose: "Get one grant by id",
99
- },
100
- {
101
- method: "POST",
102
- path: `${base}/public/buzz/auth/verify`,
103
- purpose: "Verify owner-signed capability token (shared auth)",
104
- },
105
- {
106
- method: "POST",
107
- path: `${base}/public/buzz/auth/preimage`,
108
- purpose: "Build exact capability signing preimage (client mints)",
109
- },
110
- {
111
- method: "POST",
112
- path: `${base}/public/buzz/audit/append`,
113
- purpose: "Append public audit event to shared hash chain",
114
- },
115
- {
116
- method: "POST",
117
- path: `${base}/public/buzz/audit/verify`,
118
- purpose: "Verify audit chain integrity",
119
- },
120
- {
121
- method: "POST",
122
- path: `${base}/public/buzz/audit/entries`,
123
- purpose: "Read audit entries (paginated)",
124
- },
125
- ]),
126
- auth: Object.freeze({
127
- domain: AUTH_DOMAIN,
128
- format: '["auth", ownerAddress, conditions, signature]',
129
- mint: "client-side only — owner wallet personal_sign(preimage)",
130
- verify: "POST /public/buzz/auth/verify",
131
- clauses: ["chain=<id>", "action=<scope>", "expires<unix", "notbefore>unix"],
132
- }),
133
- audit: Object.freeze({
134
- model: "sha256 hash-chain",
135
- genesis: GENESIS_HASH,
136
- publicActions: BUZZ_PUBLIC_AUDIT_ACTIONS,
137
- streamDefault: "buzz-public",
138
- }),
139
- never: Object.freeze([
140
- "private-executor-broadcast",
141
- "server-side-capability-mint-with-house-key",
142
- "raw-private-keys-in-responses",
143
- ]),
144
- });
145
- }
146
-
147
- export function handleBuzzAuthPreimage(body = {}) {
148
- const agentAddress = body.agentAddress;
149
- const conditions = body.conditions == null ? "" : String(body.conditions);
150
- if (!agentAddress || typeof agentAddress !== "string") {
151
- const err = new Error("agentAddress required");
152
- err.code = "invalid-auth-preimage";
153
- throw err;
154
- }
155
- const preimage = authPreimage(agentAddress, conditions);
156
- return {
157
- ok: true,
158
- domain: AUTH_DOMAIN,
159
- agentAddress,
160
- conditions,
161
- preimage,
162
- note: "Owner personal_sign(preimage). Server never mints with a house key.",
163
- };
164
- }
165
-
166
- export function handleBuzzAuthVerify(body = {}) {
167
- const tag = body.capability ?? body.tag ?? body.auth;
168
- const agentAddress = body.agentAddress;
169
- if (tag == null) {
170
- const err = new Error("capability tag required");
171
- err.code = "invalid-capability";
172
- throw err;
173
- }
174
- if (!agentAddress) {
175
- const err = new Error("agentAddress required");
176
- err.code = "invalid-capability";
177
- throw err;
178
- }
179
- const result = verifyCapability(tag, {
180
- agentAddress,
181
- chainId: body.chainId ?? null,
182
- action: body.action ?? null,
183
- now: body.now ?? null,
184
- });
185
- if (!result || result.ok !== true) {
186
- return {
187
- ok: false,
188
- valid: false,
189
- reason: (result && (result.reason || result.error)) || "invalid",
190
- result,
191
- };
192
- }
193
- return {
194
- ok: true,
195
- valid: true,
196
- result,
197
- };
198
- }
199
-
200
- function assertPublicAuditAction(action) {
201
- if (!BUZZ_PUBLIC_AUDIT_ACTIONS.includes(action)) {
202
- const err = new Error(
203
- `action not allowed on public buzz audit: ${action}`
204
- );
205
- err.code = "audit-action-forbidden";
206
- throw err;
207
- }
208
- }
209
-
210
- export async function handleBuzzAuditAppend(body = {}, { path } = {}) {
211
- const action = body.action;
212
- if (!action) {
213
- const err = new Error("action required");
214
- err.code = "invalid-audit";
215
- throw err;
216
- }
217
- assertPublicAuditAction(action);
218
- const detail = body.detail ?? null;
219
- try {
220
- assertNoSecretMaterial(detail);
221
- } catch (e) {
222
- if (e instanceof SecretLeakError || e?.name === "SecretLeakError") {
223
- const err = new Error("audit detail blocked: secret-shaped material");
224
- err.code = "secret-leak-blocked";
225
- throw err;
226
- }
227
- throw e;
228
- }
229
- const entry = await appendAudit({
230
- action,
231
- actor: body.actor ?? null,
232
- objectId: body.objectId ?? null,
233
- detail,
234
- stream: body.stream || "buzz-public",
235
- path,
236
- });
237
- return { ok: true, entry };
238
- }
239
-
240
- export function handleBuzzAuditVerify(body = {}, { path } = {}) {
241
- const out = verifyChain({
242
- stream: body.stream || "buzz-public",
243
- path,
244
- });
245
- return { ok: true, ...out };
246
- }
247
-
248
- export function handleBuzzAuditEntries(body = {}, { path } = {}) {
249
- const entries = getEntries({
250
- stream: body.stream || "buzz-public",
251
- fromSeq: body.fromSeq ?? 1,
252
- limit: Math.min(Number(body.limit || 100), 500),
253
- path,
254
- });
255
- return { ok: true, count: entries.length, entries };
256
- }
@@ -1,416 +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
- /** Deterministic UTC ISO string from unix seconds. */
276
- function isoUtc(unixSeconds) {
277
- return new Date(unixSeconds * 1000).toISOString();
278
- }
279
-
280
- /** Deterministic, purely-presentational human render of a normalized grant.
281
- * Presentation only — it never adds, removes, or reinterprets authority and
282
- * only surfaces public grant material. */
283
- function renderUnsignedGrant(grant, id) {
284
- const readonlyOnly = grant.actions.every((a) => isReadonlyAction(a));
285
- return [
286
- "ORACLE — CONNECT AGENT (unsigned grant, you sign it, we never do)",
287
- "=================================================================",
288
- `Grant ID: ${id}`,
289
- `Version: ${GRANT_VERSION}`,
290
- `Chain: ${grant.chainId}`,
291
- `Agent: ${grant.agentAddress}`,
292
- `Your account: ${grant.accountAddress}`,
293
- `Actions: ${grant.actions.join(", ")}`,
294
- `Targets: ${grant.targets.length ? grant.targets.join(", ") : "(none — read/simulate only)"}`,
295
- `Max value: ${grant.maxValueWei} wei`,
296
- `Max gas: ${grant.maxGasWei} wei`,
297
- `Max slippage: ${grant.maxSlippageBps} bps`,
298
- `Expires: ${isoUtc(grant.expiresAt)} (unix ${grant.expiresAt})`,
299
- `Nonce: ${grant.nonce}`,
300
- `Revocation: ${grant.revocationKey}`,
301
- "-----------------------------------------------------------------",
302
- readonlyOnly
303
- ? "Scope: read/simulate only — this grant cannot move funds."
304
- : "Scope: includes state-changing actions bounded by the caps above.",
305
- "Self-custodial: this payload is UNSIGNED and contains public data only.",
306
- "Sign the bytes below with YOUR wallet; Oracle never holds your keys.",
307
- ].join("\n");
308
- }
309
-
310
- // ---------------------------------------------------------------------------
311
- // Public contract
312
- // ---------------------------------------------------------------------------
313
-
314
- /**
315
- * Turn raw user inputs into a validated connect request.
316
- *
317
- * Accepts the canonical grant fields (see policy-schema REQUIRED_FIELDS).
318
- * Convenience: instead of `expiresAt` the caller may pass `ttlSeconds`
319
- * together with an explicit `now` (unix seconds) — determinism requires the
320
- * caller to supply `now`; there is no wall-clock fallback here.
321
- *
322
- * Throws GrantValidationError on any invalid/unknown/missing field (the
323
- * schema fails closed on unknown fields, wildcard actions, empty targets for
324
- * state-changing scopes, etc). Never signs anything.
325
- *
326
- * @returns frozen { kind, version, grant } where grant is the normalized
327
- * canonical grant from policy-schema.
328
- */
329
- export function buildConnectRequest(input = {}, opts = {}) {
330
- if (input == null || typeof input !== "object" || Array.isArray(input)) {
331
- throw new GrantValidationError([{ field: "request", message: "request must be a plain object" }]);
332
- }
333
-
334
- const { ttlSeconds, ...rest } = input;
335
- const fields = { ...rest };
336
-
337
- if (ttlSeconds != null) {
338
- if (fields.expiresAt != null) {
339
- throw new GrantValidationError([
340
- { field: "ttlSeconds", message: "pass either ttlSeconds or expiresAt, not both" },
341
- ]);
342
- }
343
- if (opts.now == null) {
344
- throw new GrantValidationError([
345
- { field: "ttlSeconds", message: "ttlSeconds requires an explicit opts.now (unix seconds) for determinism" },
346
- ]);
347
- }
348
- const ttl = toUnixSeconds(ttlSeconds, "ttlSeconds");
349
- fields.expiresAt = toUnixSeconds(opts.now, "opts.now") + ttl;
350
- }
351
-
352
- const grant = normalizeGrant(fields, {
353
- now: opts.now,
354
- allowWildcardActions: opts.allowWildcardActions === true,
355
- });
356
-
357
- const request = deepFreeze({
358
- kind: CONNECT_REQUEST_KIND,
359
- version: GRANT_VERSION,
360
- grant,
361
- });
362
- return assertNoSecretMaterial(request);
363
- }
364
-
365
- /**
366
- * Assemble the UNSIGNED grant payload for a connect request (or raw grant
367
- * input). Returns everything a BFF/browser needs to show the user what they
368
- * are approving and exactly which bytes to sign — and nothing else:
369
- *
370
- * payload — { version, grantId, grant, canonical } canonical grant data
371
- * signing — { scheme, message, bytesHex, byteLength, sha256 } where
372
- * `message` is the exact canonical JSON string and `bytesHex`
373
- * is the 0x-hex of its utf-8 bytes: THE bytes the user signs.
374
- * render — deterministic human-readable review text
375
- * unsigned — always true; this module never signs and never will.
376
- *
377
- * Deterministic: identical grants (any key order / address casing / numeric
378
- * representation) produce byte-identical canonical/message/bytesHex/grantId.
379
- *
380
- * Fail-closed: throws GrantValidationError on bad input and SecretLeakError
381
- * if the assembled object ever carried secret-shaped material.
382
- */
383
- export function assembleUnsignedGrant(requestOrInput = {}, opts = {}) {
384
- const raw =
385
- requestOrInput && requestOrInput.kind === CONNECT_REQUEST_KIND
386
- ? requestOrInput.grant
387
- : requestOrInput;
388
-
389
- const grant = normalizeGrant(raw, {
390
- now: opts.now,
391
- allowWildcardActions: opts.allowWildcardActions === true,
392
- });
393
- const canonical = canonicalizeGrant(grant);
394
- const id = grantId(grant);
395
- const bytes = Buffer.from(canonical, "utf8");
396
-
397
- const result = deepFreeze({
398
- kind: UNSIGNED_GRANT_KIND,
399
- unsigned: true,
400
- payload: deepFreeze({
401
- version: GRANT_VERSION,
402
- grantId: id,
403
- grant,
404
- canonical,
405
- }),
406
- signing: deepFreeze({
407
- scheme: SIGNING_SCHEME,
408
- message: canonical,
409
- bytesHex: `0x${bytes.toString("hex")}`,
410
- byteLength: bytes.length,
411
- sha256: id,
412
- }),
413
- render: renderUnsignedGrant(grant, id),
414
- });
415
- return assertNoSecretMaterial(result);
416
- }