@oracle-agent/oracle 0.11.0 → 0.12.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 (308) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +66 -84
  3. package/SECURITY.md +37 -12
  4. package/SETUP.md +207 -272
  5. package/dist/action-receipts.mjs +1 -0
  6. package/dist/action-semantics.mjs +1 -0
  7. package/dist/address-book.mjs +2 -0
  8. package/dist/bin/desk-server.mjs +14 -0
  9. package/dist/bin/oracle-data-mcp.mjs +8 -0
  10. package/dist/bin/oracle-init.mjs +24 -0
  11. package/dist/bin/oracle-public-server.mjs +5 -0
  12. package/dist/bin/oracle-route.mjs +22 -0
  13. package/dist/bin/oracle-scan.mjs +18 -0
  14. package/dist/bin/oracle-upgrade.mjs +21 -0
  15. package/dist/bin/oracle.mjs +68 -0
  16. package/dist/chains.mjs +1 -0
  17. package/dist/cli/commands/auth.mjs +16 -0
  18. package/dist/cli/commands/bootstrap.mjs +18 -0
  19. package/dist/cli/commands/chain.mjs +21 -0
  20. package/dist/cli/commands/chat.mjs +35 -0
  21. package/dist/cli/commands/credential.mjs +1 -0
  22. package/dist/cli/commands/data-mcp.mjs +2 -0
  23. package/dist/cli/commands/data.mjs +12 -0
  24. package/dist/cli/commands/doctor.mjs +5 -0
  25. package/dist/cli/commands/gate.mjs +13 -0
  26. package/dist/cli/commands/help.mjs +1 -0
  27. package/dist/cli/commands/init.mjs +3 -0
  28. package/dist/cli/commands/mcp.mjs +33 -0
  29. package/dist/cli/commands/model.mjs +44 -0
  30. package/dist/cli/commands/prepare.mjs +2 -0
  31. package/dist/cli/commands/public.mjs +3 -0
  32. package/dist/cli/commands/route.mjs +2 -0
  33. package/dist/cli/commands/runner.mjs +1 -0
  34. package/dist/cli/commands/scan.mjs +2 -0
  35. package/dist/cli/commands/setup.mjs +34 -0
  36. package/dist/cli/commands/sign.mjs +4 -0
  37. package/dist/cli/commands/signer.mjs +1 -0
  38. package/dist/cli/commands/upgrade.mjs +2 -0
  39. package/dist/cli/commands/vault.mjs +1 -0
  40. package/dist/cli/commands/version.mjs +2 -0
  41. package/dist/data/desk-data.mjs +12 -0
  42. package/dist/index.mjs +17 -0
  43. package/dist/nft-gas-war-guard.mjs +1 -0
  44. package/dist/onboarding/harness-configs.mjs +4 -0
  45. package/dist/portfolio-risk.mjs +1 -0
  46. package/dist/prepare-envelope.mjs +1 -0
  47. package/dist/public-control/policy-schema.mjs +1 -0
  48. package/dist/router/index.mjs +2 -0
  49. package/dist/scanner/index.mjs +4 -0
  50. package/dist/signals/index.mjs +1 -0
  51. package/dist/watch-preferences.mjs +1 -0
  52. package/package.json +27 -65
  53. package/public/oracle-splash/index.html +11 -1
  54. package/CONTRIBUTING.md +0 -98
  55. package/bin/desk-server.mjs +0 -440
  56. package/bin/oracle-data-mcp.mjs +0 -1019
  57. package/bin/oracle-init.mjs +0 -496
  58. package/bin/oracle-public-server.mjs +0 -36
  59. package/bin/oracle-route.mjs +0 -254
  60. package/bin/oracle-scan.mjs +0 -192
  61. package/bin/oracle-upgrade.mjs +0 -42
  62. package/bin/oracle.mjs +0 -33
  63. package/docs/adding-a-chain.md +0 -229
  64. package/docs/architecture.md +0 -138
  65. package/docs/cli.md +0 -47
  66. package/docs/connectors.md +0 -13
  67. package/docs/oracle-pack-standard.md +0 -29
  68. package/docs/profiles.md +0 -151
  69. package/docs/public-surface.md +0 -133
  70. package/examples/add-a-chain.mjs +0 -65
  71. package/examples/oracle-pack-template.mjs +0 -38
  72. package/examples/research-a-token.mjs +0 -70
  73. package/plugins/oracle-owner-gate/__init__.py +0 -227
  74. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  75. package/profiles/_template/SOUL.md +0 -54
  76. package/profiles/_template/profile.json +0 -22
  77. package/profiles/bitcoin-agent/SOUL.md +0 -31
  78. package/profiles/bitcoin-agent/profile.json +0 -32
  79. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  80. package/profiles/hyperliquid-agent/profile.json +0 -37
  81. package/profiles/oracle/SOUL.md +0 -107
  82. package/profiles/oracle/profile.json +0 -39
  83. package/profiles/polymarket-agent/SOUL.md +0 -35
  84. package/profiles/polymarket-agent/profile.json +0 -34
  85. package/profiles/profile.schema.json +0 -90
  86. package/profiles/protocol-builder/SOUL.md +0 -57
  87. package/profiles/protocol-builder/profile.json +0 -39
  88. package/profiles/robinhood-agent/SOUL.md +0 -53
  89. package/profiles/robinhood-agent/profile.json +0 -40
  90. package/profiles/solana-agent/SOUL.md +0 -37
  91. package/profiles/solana-agent/profile.json +0 -37
  92. package/profiles/stable-agent/SOUL.md +0 -43
  93. package/profiles/stable-agent/profile.json +0 -37
  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-inscription.py +0 -230
  101. package/scripts/check-doc-drift.mjs +0 -123
  102. package/scripts/check-test-count.mjs +0 -105
  103. package/scripts/e2e-hl-markets.mjs +0 -21
  104. package/scripts/e2e-hl-perps.mjs +0 -48
  105. package/scripts/e2e-hypercore-staking.mjs +0 -128
  106. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  107. package/scripts/protocol-template-gate.mjs +0 -15
  108. package/scripts/public-api-scan.mjs +0 -23
  109. package/scripts/secret-scan.mjs +0 -181
  110. package/scripts/verify-v3-venues.mjs +0 -192
  111. package/skills/balance/SKILL.md +0 -176
  112. package/skills/oracle-action-semantics/SKILL.md +0 -40
  113. package/skills/oracle-best-execution/SKILL.md +0 -127
  114. package/skills/oracle-bitcoin/SKILL.md +0 -53
  115. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  116. package/skills/oracle-chat/SKILL.md +0 -61
  117. package/skills/oracle-chat/chain.SKILL.md +0 -31
  118. package/skills/oracle-chat/setup.SKILL.md +0 -37
  119. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  120. package/skills/oracle-contract-research/SKILL.md +0 -55
  121. package/skills/oracle-desk/SKILL.md +0 -58
  122. package/skills/oracle-dex-launch/SKILL.md +0 -38
  123. package/skills/oracle-grants/SKILL.md +0 -69
  124. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  125. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  126. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  127. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  128. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  129. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  130. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  131. package/skills/oracle-polymarket/SKILL.md +0 -60
  132. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  133. package/skills/oracle-protocol-security/SKILL.md +0 -60
  134. package/skills/oracle-public-product/SKILL.md +0 -44
  135. package/skills/oracle-receipts/SKILL.md +0 -52
  136. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  137. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  138. package/skills/oracle-solana/SKILL.md +0 -65
  139. package/skills/oracle-solana-nft/SKILL.md +0 -54
  140. package/skills/oracle-token-research/SKILL.md +0 -67
  141. package/skins/oracle.yaml +0 -56
  142. package/src/action-receipts.mjs +0 -265
  143. package/src/action-semantics.mjs +0 -62
  144. package/src/address-book.mjs +0 -208
  145. package/src/agent-auth.mjs +0 -206
  146. package/src/approval-guard.mjs +0 -282
  147. package/src/attestation-secret.mjs +0 -88
  148. package/src/audit-log.mjs +0 -196
  149. package/src/auth/oauth.mjs +0 -672
  150. package/src/auto-slippage.mjs +0 -378
  151. package/src/capability-posture.mjs +0 -125
  152. package/src/chains.mjs +0 -62
  153. package/src/cli/chain-catalog.mjs +0 -215
  154. package/src/cli/chain-state.mjs +0 -74
  155. package/src/cli/commands/auth.mjs +0 -193
  156. package/src/cli/commands/bootstrap.mjs +0 -87
  157. package/src/cli/commands/chain.mjs +0 -143
  158. package/src/cli/commands/chat.mjs +0 -434
  159. package/src/cli/commands/credential.mjs +0 -9
  160. package/src/cli/commands/data-mcp.mjs +0 -18
  161. package/src/cli/commands/data.mjs +0 -75
  162. package/src/cli/commands/doctor.mjs +0 -136
  163. package/src/cli/commands/help.mjs +0 -7
  164. package/src/cli/commands/init.mjs +0 -27
  165. package/src/cli/commands/mcp.mjs +0 -142
  166. package/src/cli/commands/model.mjs +0 -99
  167. package/src/cli/commands/prepare.mjs +0 -12
  168. package/src/cli/commands/public.mjs +0 -20
  169. package/src/cli/commands/route.mjs +0 -12
  170. package/src/cli/commands/runner.mjs +0 -9
  171. package/src/cli/commands/scan.mjs +0 -12
  172. package/src/cli/commands/setup.mjs +0 -275
  173. package/src/cli/commands/sign.mjs +0 -21
  174. package/src/cli/commands/signer.mjs +0 -9
  175. package/src/cli/commands/upgrade.mjs +0 -12
  176. package/src/cli/commands/vault.mjs +0 -9
  177. package/src/cli/commands/version.mjs +0 -22
  178. package/src/cli/first-run.mjs +0 -23
  179. package/src/cli/kernel.mjs +0 -239
  180. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  181. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  182. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  183. package/src/cli/mcp-targets/codex.mjs +0 -41
  184. package/src/cli/mcp-targets/shared.mjs +0 -61
  185. package/src/cli/messaging-platforms.mjs +0 -209
  186. package/src/cli/model-config.mjs +0 -70
  187. package/src/cli/operator-dispatch.mjs +0 -258
  188. package/src/cli/oracle-harness.py +0 -415
  189. package/src/cli/paths.mjs +0 -83
  190. package/src/cli/runtime.mjs +0 -351
  191. package/src/cli/setup-state.mjs +0 -168
  192. package/src/cli/spawn-child.mjs +0 -43
  193. package/src/data/catalog.mjs +0 -585
  194. package/src/data/desk-data.mjs +0 -695
  195. package/src/data/http.mjs +0 -253
  196. package/src/data/provider-endpoint.mjs +0 -94
  197. package/src/data/providers/aerodrome.mjs +0 -245
  198. package/src/data/providers/balancer.mjs +0 -209
  199. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  200. package/src/data/providers/bitcoin-meta.mjs +0 -378
  201. package/src/data/providers/blockscout.mjs +0 -14
  202. package/src/data/providers/bridges.mjs +0 -242
  203. package/src/data/providers/cowswap.mjs +0 -415
  204. package/src/data/providers/curve.mjs +0 -201
  205. package/src/data/providers/defillama.mjs +0 -88
  206. package/src/data/providers/dexscreener.mjs +0 -43
  207. package/src/data/providers/evm-rpc.mjs +0 -225
  208. package/src/data/providers/geckoterminal.mjs +0 -34
  209. package/src/data/providers/gmx.mjs +0 -496
  210. package/src/data/providers/hl-assets.mjs +0 -165
  211. package/src/data/providers/hl-info.mjs +0 -108
  212. package/src/data/providers/hl-markets.mjs +0 -210
  213. package/src/data/providers/hl-outcome.mjs +0 -61
  214. package/src/data/providers/hl-perps.mjs +0 -387
  215. package/src/data/providers/hl-staking.mjs +0 -353
  216. package/src/data/providers/hl-ws.mjs +0 -119
  217. package/src/data/providers/hyperevm-dex.mjs +0 -49
  218. package/src/data/providers/jupiter-venues.mjs +0 -119
  219. package/src/data/providers/jupiter.mjs +0 -315
  220. package/src/data/providers/lifi.mjs +0 -151
  221. package/src/data/providers/magiceden-sol.mjs +0 -406
  222. package/src/data/providers/morpho.mjs +0 -177
  223. package/src/data/providers/nft-gallery.mjs +0 -163
  224. package/src/data/providers/nft-portfolio.mjs +0 -494
  225. package/src/data/providers/odos.mjs +0 -156
  226. package/src/data/providers/oneinch.mjs +0 -174
  227. package/src/data/providers/opensea-multichain.mjs +0 -136
  228. package/src/data/providers/opensea-nft.mjs +0 -371
  229. package/src/data/providers/paraswap.mjs +0 -118
  230. package/src/data/providers/pendle.mjs +0 -188
  231. package/src/data/providers/poly-clob.mjs +0 -283
  232. package/src/data/providers/poly-public.mjs +0 -96
  233. package/src/data/providers/poly-ws.mjs +0 -103
  234. package/src/data/providers/portfolio-history.mjs +0 -394
  235. package/src/data/providers/portfolio.mjs +0 -594
  236. package/src/data/providers/rfq.mjs +0 -15
  237. package/src/data/providers/rh-agent.mjs +0 -59
  238. package/src/data/providers/satflow.mjs +0 -341
  239. package/src/data/providers/signed-material-guard.mjs +0 -108
  240. package/src/data/providers/solana-rpc.mjs +0 -197
  241. package/src/data/providers/uniswap-v3.mjs +0 -349
  242. package/src/data/providers/uniswap-v4.mjs +0 -414
  243. package/src/data/providers/zerox.mjs +0 -167
  244. package/src/data/public-api-scan.mjs +0 -61
  245. package/src/data/quote-placeholder.mjs +0 -31
  246. package/src/exact-integer.mjs +0 -72
  247. package/src/exec-policy.mjs +0 -455
  248. package/src/flags.mjs +0 -15
  249. package/src/fresh-window.mjs +0 -76
  250. package/src/gmx-attestation.mjs +0 -176
  251. package/src/index.mjs +0 -100
  252. package/src/nft-gas-war-guard.mjs +0 -139
  253. package/src/onboarding/agent-keys.mjs +0 -161
  254. package/src/onboarding/harness-configs.mjs +0 -102
  255. package/src/onboarding/index.mjs +0 -18
  256. package/src/onboarding/tiers.mjs +0 -139
  257. package/src/oracle-env.mjs +0 -47
  258. package/src/portfolio-risk.mjs +0 -170
  259. package/src/prepare-envelope.mjs +0 -204
  260. package/src/profile-upgrade.mjs +0 -277
  261. package/src/protocol-execution.mjs +0 -84
  262. package/src/protocol-templates/gate.mjs +0 -179
  263. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  264. package/src/public-api/buzz-integration.mjs +0 -256
  265. package/src/public-api/connect-agent.mjs +0 -416
  266. package/src/public-api/grants.mjs +0 -142
  267. package/src/public-api/http.mjs +0 -389
  268. package/src/public-control/aa-adapter.mjs +0 -402
  269. package/src/public-control/build-registry.mjs +0 -227
  270. package/src/public-control/bundler-client.mjs +0 -357
  271. package/src/public-control/grant-indexer.mjs +0 -296
  272. package/src/public-control/policy-render.mjs +0 -69
  273. package/src/public-control/policy-schema.mjs +0 -318
  274. package/src/public-control/runtime-config.mjs +0 -275
  275. package/src/public-control/session-key-model.mjs +0 -374
  276. package/src/public-control/session-orchestrator.mjs +0 -412
  277. package/src/rfq/intent.mjs +0 -180
  278. package/src/rfq/sources.mjs +0 -181
  279. package/src/route-attestation.mjs +0 -132
  280. package/src/router/best-execution.mjs +0 -326
  281. package/src/router/index.mjs +0 -226
  282. package/src/router/prepare-bridge.mjs +0 -289
  283. package/src/router/prepare-route.mjs +0 -398
  284. package/src/router/proposal.mjs +0 -311
  285. package/src/router/risk-classifier.mjs +0 -119
  286. package/src/router/route-sources.mjs +0 -364
  287. package/src/scanner/chains.config.mjs +0 -430
  288. package/src/scanner/contract.mjs +0 -270
  289. package/src/scanner/evm-scanner.mjs +0 -394
  290. package/src/scanner/index.mjs +0 -9
  291. package/src/scanner/v2-venue.mjs +0 -335
  292. package/src/scanner/v3-venue.mjs +0 -290
  293. package/src/scopes.mjs +0 -44
  294. package/src/sell-simulation.mjs +0 -167
  295. package/src/signals/engine.mjs +0 -146
  296. package/src/signals/index.mjs +0 -1
  297. package/src/token-transfer-guard.mjs +0 -188
  298. package/src/tui/app.mjs +0 -438
  299. package/src/tui/backend.mjs +0 -145
  300. package/src/tui/format.mjs +0 -272
  301. package/src/tui/gateway-client.mjs +0 -177
  302. package/src/tui/input.mjs +0 -501
  303. package/src/tui/renderer.mjs +0 -443
  304. package/src/tui/standalone-client.mjs +0 -666
  305. package/src/tui/theme.mjs +0 -81
  306. package/src/vault-attestation.mjs +0 -146
  307. package/src/venues.mjs +0 -206
  308. package/src/watch-preferences.mjs +0 -85
package/SETUP.md CHANGED
@@ -1,381 +1,316 @@
1
- # Setup
1
+ # Oracle setup
2
2
 
3
- ## Unified CLI
3
+ Oracle's public CLI is a standalone, prepare-only multichain agent. It can read,
4
+ research, quote, simulate, and build unsigned artifacts. It does not need Hermes,
5
+ it does not accept wallet private keys, and it does not broadcast transactions.
4
6
 
5
- Prefer the root `oracle` command:
7
+ The owner-operated signer/executor is private infrastructure. It is not published
8
+ on npm and is not part of public or holder onboarding.
6
9
 
7
- ```bash
8
- npm i -g @oracle-agent/oracle
9
- oracle
10
- oracle init --apply
11
- oracle doctor
12
- ```
10
+ ## Requirements
13
11
 
14
- Full reference: [docs/cli.md](./docs/cli.md). Connectors: [docs/connectors.md](./docs/connectors.md).
12
+ - Node.js `20.19.0` or newer
13
+ - npm
14
+ - A supported model login or API key for chat
15
+ - A user-controlled wallet only when reviewing and signing a prepared artifact
15
16
 
17
+ Linux, Windows, and macOS apps are in beta.
16
18
 
17
- Oracle's public surface runs locally against your API accounts and never accepts
18
- a wallet private key. Prepared actions are signed in the user's wallet.
19
-
20
- ## Install
19
+ ## 1. Install the standalone CLI
21
20
 
22
21
  ```bash
23
- npm install @oracle-agent/oracle # Node >= 20.19.0
22
+ npm view @oracle-agent/oracle version
23
+ npm i -g @oracle-agent/oracle@latest
24
+ oracle --version
24
25
  ```
25
26
 
26
- Or from source, if you want to run the suite:
27
+ The npm `latest` tag is the install source of truth. The repository can contain
28
+ an unreleased next version, so do not infer the published version from a branch.
29
+
30
+ For a project-local library install instead:
27
31
 
28
32
  ```bash
29
- git clone https://github.com/demi-hl/oracle.git
30
- cd oracle
31
- npm install
32
- npm test
33
+ npm i @oracle-agent/oracle@latest
33
34
  ```
34
35
 
35
- ## The one thing to understand first
36
+ The package declares this floor through `engines`; `oracle doctor` treats an
37
+ unsupported Node runtime as blocking. npm may only warn unless the user's npm
38
+ configuration enables strict engine checks, so verify `node --version` yourself.
36
39
 
37
- Oracle has two distribution boundaries and they are separate on purpose:
40
+ ## 2. Authenticate a model provider
38
41
 
39
- | Plane | What it does | Needs a key? |
40
- |---|---|---|
41
- | **Read / prepare** | Market data, quotes, and *unsigned* transactions or EIP-712 actions | No, mostly |
42
- | **Owner-local source lane** | Optional companion `@oracle-agent/operator` — keys on YOUR machine | Yes |
42
+ ### OAuth
43
43
 
44
- A prepared object is inert. It becomes real only when something signs it. You
45
- choose whether that something is your browser wallet or separately operated
46
- owner-local infrastructure.
47
-
48
- ## Public posture: always prepare-only
49
-
50
- The public data facade rejects `hl-exec` even when a signing key exists in the
51
- environment. The npm artifact excludes the key vault and live signer modules.
52
- Wallet signing, submission, receipt confirmation, and revocation happen outside
53
- that public surface.
54
-
55
- ### Capability is not authorization
56
-
57
- The public Oracle profile must report these as separate planes:
58
-
59
- | Plane | Default capability |
60
- |---|---|
61
- | Public Oracle package | read, quote, simulate, unsigned prepare |
62
- | Generic `oracle-signer` daemon | six bounded surfaces: `hl`, `poly`, `evm-swap`, `evm-bridge`, `btc`, `sol` (each fails closed on empty allowlists) |
63
- | Ordinary EVM | unsigned preparation, user-wallet signature |
64
- | Optional owner-gated EVM executor | one exact bounded action after explicit `arm` |
65
-
66
- The optional EVM executor is not bundled into this public package and must never be exposed over LAN or a tailnet. A profile may describe bounded EVM execution as available only after verifying that separate local executor and its owner gate. Otherwise say the current deployment is prepare-only. Do not claim EVM execution is universally impossible.
67
-
68
- Action records require explicit fields:
69
-
70
- ```json
71
- {
72
- "active": true,
73
- "actionMode": "alert_only"
74
- }
44
+ ```bash
45
+ oracle auth login claude
46
+ # or
47
+ oracle auth login codex
48
+ oracle auth login grok
75
49
  ```
76
50
 
77
- `watch`, `watch this`, and `ping me` always use `alert_only`. `arm` uses `execute` only for one exact owner-authorized action. A legacy `status: armed` field is not execution authority.
51
+ The command opens the provider's authorization flow and selects its default
52
+ model. Use `--no-browser` when the browser must be opened manually.
78
53
 
79
- ---
80
-
81
- ## Source-only operator credentials
82
-
83
- This section applies only to an owner-local source checkout. These signing
84
- credentials are not consumed by the public package entrypoints.
85
-
86
- ## Keys: what each one unlocks
87
-
88
- Everything is optional. Oracle degrades to whatever you have configured.
89
-
90
- ### Hyperliquid — perps, spot, staking
91
-
92
- Hyperliquid does not issue API keys. You authorize with an **Ethereum private
93
- key**, either your account key or (recommended) an **API wallet**.
94
-
95
- Create an API wallet at <https://app.hyperliquid.xyz/API>. It can trade your
96
- account but **cannot withdraw**, which is exactly what you want for an agent.
54
+ ### API key
97
55
 
98
56
  ```bash
99
- export HL_PRIVATE_KEY=0xabc... # the API wallet's key
100
- # or, better, keep it in a file:
101
- export HL_KEY_FILE=~/.config/oracle/keys/hl.key
57
+ oracle auth api-key openrouter
58
+ # also supported: openai, xai, deepseek, gemini, custom
102
59
  ```
103
60
 
104
- Reads (prices, funding, order books, your positions) need **no key at all**.
105
-
106
- ### Polymarket — prediction markets
107
-
108
- Two different credentials, for two different things:
61
+ Interactive API-key entry is hidden. Do not put a key directly in the command
62
+ line, shell history, a screenshot, or Oracle chat. For controlled automation,
63
+ pipe the secret over stdin instead of passing it as an argument:
109
64
 
110
65
  ```bash
111
- # 1. L2 API credentials — read your orders, post orders to the CLOB
112
- export POLYMARKET_API_KEY=...
113
- export POLYMARKET_API_SECRET=...
114
- export POLYMARKET_API_PASSPHRASE=...
115
-
116
- # 2. The Polygon key that actually owns the funds
117
- export POLYMARKET_PRIVATE_KEY=0x...
66
+ printf '%s\n' "$OPENROUTER_API_KEY" | oracle auth api-key openrouter --stdin
118
67
  ```
119
68
 
120
- Derive the L2 credentials from your wallet at <https://polymarket.com> under
121
- API access, or via the CLOB `create-api-key` endpoint. Public market data,
122
- prices, and order books need **no credentials**.
69
+ Check configuration without revealing credentials:
123
70
 
124
- ### Everything else
71
+ ```bash
72
+ oracle auth status
73
+ oracle model --show
74
+ ```
125
75
 
126
- | Variable | Unlocks | Without it |
127
- |---|---|---|
128
- | `OPENSEA_API_KEY` | NFT collections, listings, offers | Heavily rate limited |
129
- | `MAGICEDEN_API_KEY` | Solana NFT buy/list/mint intents | Floor and listing reads still work |
130
- | `SATFLOW_API_KEY` | Bitcoin ordinals + runes marketplace | Esplora reads still work |
131
- | `ZEROX_API_KEY` | 0x swap routing | Other routers still quote |
132
- | `ONEINCH_API_KEY` | 1inch routing | Other routers still quote |
133
- | `UNISAT_API_KEY` | Ordinals/BRC-20 indexing | Tip and UTXOs still work |
134
- | `ORACLE_ROUTE_ATTESTATION_SECRET` | HMAC-signs route and slippage guards | **Required for swap sign/broadcast.** Read/quote/prepare still work. Fresh installs: `oracle-init --apply` writes one to `~/.config/oracle/exec.env`. Unsigned guards are refused at the signer boundary. |
76
+ OAuth credentials and stored API keys use the OS credential store when
77
+ available, with a private `0600` local fallback.
135
78
 
136
- Chain RPCs default to public endpoints. Override any of them:
79
+ ## 3. Open Oracle
137
80
 
138
81
  ```bash
139
- export ETH_RPC_URL=https://...
140
- export BASE_RPC_URL=https://...
141
- export SOLANA_RPC_URL=https://...
82
+ oracle
142
83
  ```
143
84
 
144
- `/balance` and plain `balance` need only public addresses. Set any families the
145
- wallet uses, then start `oracle-data` from the same environment:
85
+ Useful first commands:
146
86
 
147
87
  ```bash
148
- export ORACLE_EVM_ADDRESS=0x...
149
- export ORACLE_SOLANA_ADDRESS=...
150
- export ORACLE_BITCOIN_ADDRESS=bc1...
151
- export ORACLE_HYPERLIQUID_ADDRESS=0x... # optional, defaults to EVM address
152
- npx oracle-data
88
+ oracle chain list
89
+ oracle chain use hyperliquid
90
+ oracle chain show
91
+ oracle doctor
153
92
  ```
154
93
 
155
- Missing address families are reported as `not-configured`, failed providers as
156
- `unavailable`, and unsupported chain families as `unsupported`. They are never
157
- reported as zero. EVM native balances cover every configured EVM chain. Solana
158
- adds SPL and Token-2022 accounts, Bitcoin adds Runes and inscriptions when an
159
- address indexer is configured, Hyperliquid adds spot and perp account state, and
160
- NFT inventory adds OpenSea-supported EVM/Solana collections plus Bitcoin
161
- inscriptions where owner indexers are available.
94
+ Inside chat:
162
95
 
163
- Every `portfolio_snapshot` call appends one compact observation to
164
- `$HERMES_HOME/state/oracle/portfolio-history.jsonl` with mode `0600`. It stores a
165
- public-address fingerprint, coverage, value breakdown, and warnings, not keys,
166
- prepared transactions, or raw NFT metadata. Override the internal location only
167
- when needed:
96
+ - `/chain` lists or selects the active chain.
97
+ - `/model` changes the model without changing the Oracle persona.
98
+ - `/setup` opens optional messaging setup.
168
99
 
169
- ```bash
170
- export ORACLE_PORTFOLIO_HISTORY_FILE="$HOME/.local/state/oracle/portfolio-history.jsonl"
171
- ```
100
+ A model response is not authorization, a prepared object is not a transaction,
101
+ and a submitted transaction is not a confirmed receipt.
102
+
103
+ ## Public capability boundary
172
104
 
173
- `portfolio_history` reads those observations. `portfolio_value_graph` returns an
174
- SVG chart of known priced value and omits unavailable observations instead of
175
- plotting them as zero.
105
+ | Surface | Available to a public install | Custody |
106
+ |---|---:|---|
107
+ | Chat, research, market data | yes | none |
108
+ | Quotes and simulations | yes | none |
109
+ | Unsigned transaction / typed-data preparation | yes | user's wallet reviews and signs |
110
+ | Signing, submission, broadcast | no | private owner-operated boundary only |
111
+ | Automatic trading | no | not a public capability |
176
112
 
177
- ---
113
+ Never paste a seed phrase, private key, hardware-wallet recovery phrase, vault
114
+ passphrase, signer token, bot token, or provider credential into chat.
178
115
 
179
- ## Where keys are stored
116
+ ## Optional Hermes integration
180
117
 
181
- **Oracle never transmits your keys anywhere except the venue they authenticate
182
- to.** Provider endpoints are pinned: if something redirects a provider's
183
- `baseUrl` to another host, the credential is dropped rather than forwarded.
184
- A plaintext `http://` downgrade also drops it.
118
+ Hermes is optional. Add it only if you want specialist profiles, messaging
119
+ channels, durable sessions, or the MCP-based local read plane:
185
120
 
186
- Three options, worst to best:
121
+ ```bash
122
+ oracle bootstrap
123
+ oracle init # dry run
124
+ oracle init --apply
125
+ oracle data serve
126
+ oracle doctor
127
+ ```
187
128
 
188
- ### 1. Environment variables
129
+ `oracle bootstrap` installs an isolated Hermes compatibility runtime under
130
+ Oracle's config directory and never modifies system Python. `oracle init
131
+ --apply` writes profiles and a local HMAC attestation secret; it does not write a
132
+ wallet key.
189
133
 
190
- Fine for a laptop. Visible in `ps`, inherited by child processes, and easy to
191
- leak into a shell history or a log.
134
+ The data service binds to `127.0.0.1:8787`. Keep it on loopback.
192
135
 
193
- ### 2. A key file
136
+ ## Optional public HTTP plane
194
137
 
195
138
  ```bash
196
- mkdir -p ~/.config/oracle/keys && chmod 700 ~/.config/oracle/keys
197
- printf '%s' "0xYOUR_KEY" > ~/.config/oracle/keys/hl.key
198
- chmod 600 ~/.config/oracle/keys/hl.key
199
- export HL_KEY_FILE=~/.config/oracle/keys/hl.key
139
+ oracle public serve --port 8799
200
140
  ```
201
141
 
202
- Keeps the secret out of the process environment.
142
+ The public plane binds to `127.0.0.1` and exposes read, connect, grant,
143
+ portfolio, approval, prepare, Buzz-auth, and audit contracts. It has no signer,
144
+ key, send, execute, or broadcast route.
203
145
 
204
- ### 3. An encrypted vault (recommended)
146
+ The service is rate limited but unauthenticated. It is **not** a Locals-holder
147
+ gate and must not be exposed directly to the internet, LAN, or tailnet. A hosted
148
+ deployment needs a controlled reverse proxy, TLS, edge limits, and the
149
+ server-side holder gate described in
150
+ [holder-beta.md](docs/holder-beta.md).
205
151
 
206
- Install the companion and use its CLI (not shipped in this package):
152
+ Verify liveness only after starting it:
207
153
 
208
154
  ```bash
209
- npm i -g @oracle-agent/operator # or npm i -D in your project
210
- oracle-vault encrypt ~/.config/oracle/keys/hl.key
211
- # writes hl.key.vault.json (scrypt N=2^17 + AES-256-GCM)
212
- # moves hl.key -> hl.key.plaintext.bak
155
+ curl -fsS http://127.0.0.1:8799/public/health
156
+ curl -fsS http://127.0.0.1:8799/public/buzz
157
+ ```
158
+
159
+ A static Oracle website does not imply that this API is running.
213
160
 
214
- export ORACLE_VAULT_PASSPHRASE="..." # or be prompted
215
- export HL_KEY_FILE=~/.config/oracle/keys/hl.key.vault.json
161
+ ## Optional messaging
216
162
 
217
- # verify it unlocks, THEN destroy the plaintext backup
218
- oracle-vault inspect ~/.config/oracle/keys/hl.key.vault.json
219
- shred -u ~/.config/oracle/keys/hl.key.plaintext.bak
163
+ ```bash
164
+ oracle setup
165
+ oracle setup telegram --allowed-users <telegram-user-id>
166
+ oracle setup status
167
+ oracle setup gateway start
220
168
  ```
221
169
 
222
- The operator vault decrypts in memory only. The key is never written back to
223
- disk, never logged, and never included in any returned object.
170
+ Interactive bot-token entry is hidden. Do not use `--token` in a normal shell;
171
+ arguments can be retained in history or visible to other local processes. For a
172
+ holder beta, do not run one shared messaging bot without a separate holder
173
+ admission layer and per-user session isolation.
174
+
175
+ ## Public wallet addresses and portfolio reads
224
176
 
225
- **What the vault does and does not protect.** It defends against a key file read
226
- by something that is not you: a synced backup, a stolen laptop at rest, an
227
- overly-broad `chmod`, a leaked tarball. It does **not** defend against malware
228
- running as your user while the vault is unlocked. Nothing file-based does. If
229
- you need that, use a hardware wallet and the prepare-only path.
177
+ Portfolio and approval reads use public addresses only:
230
178
 
231
179
  ```bash
232
- oracle-vault rekey <vault> # rotate the passphrase
233
- oracle-vault inspect <vault> # show KDF params, no secret
180
+ export ORACLE_EVM_ADDRESS=0x...
181
+ export ORACLE_SOLANA_ADDRESS=...
182
+ export ORACLE_BITCOIN_ADDRESS=bc1...
183
+ export ORACLE_HYPERLIQUID_ADDRESS=0x... # optional; EVM address is the fallback
184
+ oracle data serve
234
185
  ```
235
186
 
236
- ---
187
+ Missing address families are reported as `not-configured`, provider failures as
188
+ `unavailable`, and unsupported families as `unsupported`. They are never
189
+ reported as zero. Portfolio history is stored profile-locally with mode `0600`
190
+ and contains public-address fingerprints and value observations, not wallet
191
+ keys or prepared transactions.
237
192
 
238
- ## Two ways to trade
193
+ ## Preparing an action
239
194
 
240
- ### A. Non-custodial — Oracle never sees a key
241
-
242
- Oracle prepares, your wallet signs:
195
+ Preparation requires the real wallet that will sign. Placeholder and burn
196
+ addresses are rejected.
243
197
 
244
198
  ```js
245
- import { data } from "./src/index.mjs";
199
+ import { data } from "@oracle-agent/oracle";
246
200
 
247
- const order = await data.call("hl-perps", "prepareOrder", {
248
- coin: "BTC", side: "buy", type: "limit", price: "60000", size: "0.01",
201
+ const prepared = await data.call("hl-perps", "prepareOrder", {
202
+ /* exact market, side, size, limits, and owner wallet */
249
203
  });
250
-
251
- // order.action + order.signingReady === false
252
- // Hand order.action to the user's wallet. Oracle is done.
253
204
  ```
254
205
 
255
- ### B. Owner-local execution
206
+ Review the chain, destination, calldata or typed data, amount, minimum output,
207
+ expiry, approvals, and fees in the user's wallet. Oracle's public package stops
208
+ before signing. Report success only after a real transaction hash, successful
209
+ receipt, and expected balance or state change.
256
210
 
257
- The public `data.call()` facade refuses `hl-exec`. Operator signing lives in
258
- [`@oracle-agent/operator`](https://github.com/demi-hl/oracle-operator) on your
259
- machine with your key. Import `hlSignAndSubmit` from that package — never from
260
- this one. Do not expose it on a public HTTP port.
211
+ ## Locals-only holder beta
261
212
 
262
- The public prepare path hard-caps slippage at 100 bps, bounds leverage by the
263
- asset maximum, rounds sizes and prices to venue precision, and makes brackets
264
- reduce-only. Any separately operated executor must enforce those controls again
265
- at its signing and broadcast boundaries.
213
+ Current release status is **HOLD for a holder-gated hosted launch**. The package
214
+ is safe to distribute for local read/research/prepare use, but this repository
215
+ does not contain an integrated Locals ownership gate. UI hiding, a wallet text
216
+ field, or possession of a URL is not access control.
266
217
 
267
- ---
218
+ Do not invite holders to a hosted surface until every required gate in
219
+ [holder-beta.md](docs/holder-beta.md) passes.
268
220
 
269
- ## Model providers: use anything, but Hermes is better here
221
+ ## Buzz integration
270
222
 
271
- Oracle is a library — it does not care what drives it. Point Claude, GPT,
272
- Gemini, Grok, a local Llama, or your own script at it. The tools are plain
273
- functions and an MCP server.
223
+ Oracle includes a public, unsigned Buzz HTTP contract. It does not embed the
224
+ private executor and it does not turn Buzz into a custody surface. Setup,
225
+ endpoints, and deployment status rules are documented in
226
+ [buzz-integration.md](docs/buzz-integration.md).
227
+
228
+ ## Doctor output
274
229
 
275
230
  ```bash
276
- npx oracle-data # local read plane on 127.0.0.1:8787
277
- npx oracle-data-mcp # MCP stdio server, works with any MCP client (needs oracle-data up)
231
+ oracle doctor --json
278
232
  ```
279
233
 
280
- **Why [Hermes](https://claude-code.nousresearch.com/docs) is the better host: per-profile routing.**
234
+ A clean standalone install can legitimately show warnings for:
281
235
 
282
- A trading stack is not one workload, it is several with opposite requirements,
283
- and a single model config is wrong for all of them at once:
236
+ - `data_server` when `oracle data serve` is not running;
237
+ - `agent_runtime` when optional Hermes is not installed;
238
+ - `hermes_lanes` before optional `oracle init --apply`.
284
239
 
285
- - **Research** — wide context, cheap, tolerant of latency. A big cheap model.
286
- - **Execution** — fast and deterministic. Latency is money; a slow model turns
287
- a limit order into a market order.
288
- - **Risk review** — the strongest model available, because this is the one that
289
- says no.
290
- - **Alerts and crons** — small and cheap, running unattended all day.
240
+ A Node-version failure is blocking. Signing warnings are irrelevant to the
241
+ public holder path because signing is not installed there.
291
242
 
292
- Hermes gives each of those its own **profile**: its own model, its own tools,
293
- its own memory, its own key scope. The research profile can hold no signing key
294
- at all. The execution profile can hold one but run a fast model. The risk
295
- profile can be the expensive model that reviews what the others propose.
243
+ ## Upgrade
296
244
 
297
- That last point is the real argument. **Different model lineages have different
298
- blind spots.** Oracle's own pre-release audit ran four — Grok 4.5, Opus 5,
299
- Fable 5, and GPT-5.6 — and each found a critical issue the others missed:
245
+ ```bash
246
+ npm i -g @oracle-agent/oracle@latest
247
+ oracle --version
248
+ oracle doctor
249
+ ```
300
250
 
301
- - a credential leak in an HTTP dedupe cache
302
- - a `Number()` truncation that made a signing UI display a different amount
303
- than the one being signed
304
- - a spending guard that authorized any amount when both limit fields were
305
- omitted
306
- - a cap passed as a JS number above 2^53 that silently rounded **upward**
251
+ Review release notes before upgrading a machine that also runs private
252
+ owner-operated infrastructure.
307
253
 
308
- One model reviewing its own work would have shipped three of those. Per-profile
309
- routing is what makes running several practical instead of theoretical.
254
+ ## Uninstall
310
255
 
311
- Everything still works fine with a single provider. It is just better with a
312
- router that knows which brain to use for which job.
256
+ ```bash
257
+ npm rm -g @oracle-agent/oracle
258
+ ```
313
259
 
314
- ### Operator hardening (0.4+)
260
+ The CLI does not silently delete local configuration or credentials. Remove
261
+ those separately only after confirming they are no longer needed.
315
262
 
316
- Prefer the local signer daemon so the agent never sees the vault passphrase:
263
+ ## Build and test from source
317
264
 
318
265
  ```bash
319
- npx oracle-signer # reads the passphrase from the OS credential store
320
- # agent: ORACLE_SIGNER_URL + ORACLE_SIGNER_TOKEN only
266
+ git clone https://github.com/demi-hl/oracle.git
267
+ cd oracle
268
+ npm ci --no-audit --no-fund
269
+ npm run gate:release
270
+ npm run test:boundary
271
+ npm test
272
+ npm run typecheck
273
+ npm run build
274
+ npm run scan:secrets
321
275
  ```
322
276
 
323
- See [oracle-operator SETUP](https://github.com/demi-hl/oracle-operator/blob/main/SETUP.md).
277
+ The repository may be private or ahead of npm while a release is being staged.
278
+ The npm artifact remains the public installation source.
324
279
 
325
- ## Local HIP-3 / HIP-4 / Polymarket (no VPS)
280
+ ## Troubleshooting
326
281
 
327
- ### Hyperliquid HIP-3 (builder perps)
328
- ```js
329
- const prep = await data.call("hl-perps", "prepareOrder", {
330
- coin: "xyz:TSLA", side: "buy", type: "limit", price: "250", size: "1",
331
- });
332
- await hlSignAndSubmit(prep, { keyFile, userInitiated: true });
333
- // or signViaDaemon({ surface: "hl", prepared: prep, userInitiated: true })
334
- ```
282
+ ### `oracle` says no provider is configured
335
283
 
336
- ### Hyperliquid HIP-4 (outcomes)
337
- ```js
338
- const prep = await data.call("hl-outcome", "prepareOrder", {
339
- outcome: 969, side: "yes", // or coin: "#9690"
340
- side: "buy", type: "limit", price: "0.42", size: "20",
341
- });
342
- await hlSignAndSubmit(prep, { keyFile, userInitiated: true });
343
- ```
284
+ Run `oracle auth login <provider>` or `oracle auth api-key <provider>`, then
285
+ confirm with `oracle auth status`.
344
286
 
345
- ### Polymarket (local CLOB)
346
- ```js
347
- const prep = await data.call("poly-clob", "prepareOrder", {
348
- tokenId, side: "BUY", price: 0.45, size: 10,
349
- maker: eoa, signer: eoa, tickSize: "0.01",
350
- });
351
- // signer process needs POLYMARKET_API_KEY/SECRET/PASSPHRASE + key
352
- await polySignAndSubmit(prep, { keyFile, userInitiated: true });
353
- // or signViaDaemon({ surface: "poly", prepared: prep, userInitiated: true })
354
- ```
287
+ ### `oracle setup` says the local runtime is missing
355
288
 
356
- ## Protocol templates (builder)
289
+ Messaging uses optional Hermes. Run `oracle bootstrap`, then retry setup.
290
+ Standalone chat, chain selection, and public read/prepare commands do not require
291
+ Hermes.
357
292
 
358
- Gated Foundry templates under `protocols/templates/`.
293
+ ### `oracle doctor` says the data server is down
359
294
 
360
- ```bash
361
- # requires Foundry (forge)
362
- cd protocols/templates/safe-erc20 && forge install && forge test
363
- npm run protocol:gate -- safe-erc20
364
- ```
295
+ Start it in another terminal with `oracle data serve`. Do not expose port `8787`
296
+ off-host.
365
297
 
366
- `prepareTemplateDeploy` will not stamp an unsigned deploy unless `forge test` passes.
367
- **Not a paid security-firm audit** — see each template `SECURITY.md`.
298
+ ### The public API or Buzz endpoint is unreachable
368
299
 
300
+ Start `oracle public serve --port 8799` and verify `/public/health`. Do not claim
301
+ the API is live based on the static site or source code alone.
369
302
 
370
- ## Optional keyed prepare stamps (hardening)
303
+ ### A prepared action cannot be signed
371
304
 
372
- Integrity hash is always on. For a shared HMAC between prepare process and signer:
305
+ That is expected in the public package. Hand the reviewed artifact to a
306
+ user-controlled wallet. Do not install or request private owner infrastructure
307
+ as a workaround.
373
308
 
374
- ```bash
375
- # same secret on prepare host and signer host (not in the agent chat)
376
- export ORACLE_STAMP_HMAC_SECRET='long-random-secret'
377
- # signer-only: refuse envelopes without MAC
378
- export ORACLE_STAMP_REQUIRE_MAC=1
379
- ```
309
+ ## References
380
310
 
381
- Default remains hash-only (public GO path). HMAC is opt-in hardening.
311
+ - [CLI reference](docs/cli.md)
312
+ - [Public API and environment surface](docs/public-surface.md)
313
+ - [Locals-holder beta launch gate](docs/holder-beta.md)
314
+ - [Buzz integration](docs/buzz-integration.md)
315
+ - [Architecture](docs/architecture.md)
316
+ - [Security policy](SECURITY.md)
@@ -0,0 +1 @@
1
+ import{createHash as m}from"node:crypto";import{wordlists as g}from"ethers";var A=1,E=new Set(["privatekey","privkey","secretkey","seedphrase","seed","mnemonic","passphrase","password","keystore","keymaterial","wif","xprv","xpriv","bearer","authorization","signature","apikey","credential"]),x=[/\b[5KL][1-9A-HJ-NP-Za-km-z]{50,51}\b/,/\bxprv[0-9A-Za-z]{50,}\b/],$=new Set([12,15,18,21,24]);function S(e){let t=String(e).trim().toLowerCase().split(/\s+/).filter(Boolean);return $.has(t.length)&&t.every(r=>g.en.getWordIndex(r)>=0)}var H=/^\s*(?:0x)?[0-9a-fA-F]{64}\s*$/,O=/(hash|digest|root|salt|nonce|proof|commitment|sig|id)(?:e?s)?$/i,j=new Set(["calldata","data","publickey","pubkey","message","payload","input","extradata"]);function T(e){let t=b(e);return j.has(t)||O.test(t)}var f=class extends Error{constructor(t){super(`action receipt refused: secret-bearing field at ${t}`),this.name="ActionReceiptSecretError",this.code="ACTION_RECEIPT_SECRET"}};function b(e){return String(e).replace(/[^a-z0-9]/gi,"").toLowerCase()}function C(e){let t=b(e);return[...E].some(r=>t.includes(r))}function _(e,t,r){if(typeof t=="string"){if(x.some(o=>o.test(t))||S(t))throw new f(r);if(H.test(t)&&!T(e))throw new f(r)}}function a(e,t="$",r=""){if(e==null||typeof e=="boolean")return e;if(typeof e=="string")return _(r,e,t),e;if(typeof e=="number"){if(!Number.isFinite(e))throw new TypeError(`action receipt: non-finite number at ${t}`);return e}if(typeof e=="bigint")return e.toString();if(Array.isArray(e))return e.map((n,i)=>a(n,`${t}[${i}]`,r));if(typeof e!="object"||Object.getPrototypeOf(e)!==Object.prototype)throw new TypeError(`action receipt: JSON-like value required at ${t}`);let o={};for(let n of Object.keys(e).sort()){let i=`${t}.${n}`;if(C(n))throw new f(i);e[n]!==void 0&&(o[n]=a(e[n],i,n))}return o}function L(e){return a(e)}function d(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(d).join(",")}]`:`{${Object.keys(e).map(t=>`${JSON.stringify(t)}:${d(e[t])}`).join(",")}}`}function R(e){return d(a(e))}function k(e){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("action receipt: object required");let{receiptId:t,summary:r,...o}=e;return m("sha256").update(R(o)).digest("hex")}function c(e,...t){for(let r of t)if(e[r]!==void 0)return e[r]}function s(e,t,r){let o=c(e,...t);if(o==null)throw new TypeError(`action receipt: ${r} required`);return o}function I(e){let t=c(e,"balances","balanceChanges"),r=c(e,"beforeBalances","balancesBefore","before"),o=c(e,"afterBalances","balancesAfter","after");return t!==void 0?{balances:t}:r===void 0&&o===void 0?{}:{balances:{...r===void 0?{}:{before:r},...o===void 0?{}:{after:o}}}}function N(e={}){if(!e||typeof e!="object"||Array.isArray(e))throw new TypeError("action receipt: input object required");a(e);let t=c(e,"txHash","transactionHash"),r=c(e,"phase","stage","resultType")??(t==null?"prepare":"execute");if(r!=="prepare"&&r!=="execute")throw new TypeError('action receipt: phase must be "prepare" or "execute"');let o={receiptVersion:A,phase:r,intent:s(e,["intent"],"intent"),route:s(e,["route"],"route"),decodedAction:s(e,["decodedAction","action"],"decodedAction"),policyChecks:s(e,["policyChecks","checks"],"policyChecks"),allowlistHits:s(e,["allowlistHits","allowlistMatches"],"allowlistHits"),prepareHash:s(e,["prepareHash"],"prepareHash"),...t==null?{}:{txHash:t},...I(e)},n=a(o);return Object.freeze({...n,receiptId:k(n)})}var q=N;function u(e,t=[]){if(typeof e=="string"||typeof e=="number")return String(e);for(let r of t)if(e?.[r]!=null)return String(e[r]);return"recorded"}function y(e){if(typeof e=="boolean")return e;if(e&&typeof e=="object"){if(typeof e.ok=="boolean")return e.ok;if(typeof e.allowed=="boolean")return e.allowed;if(typeof e.passed=="boolean")return e.passed}return null}function z(e){if(!e||typeof e!="object")throw new TypeError("action receipt: object required");let t=u(e.decodedAction,["type","action","method","name"]),r=u(e.route,["name","provider","venue","id"]),o=Array.isArray(e.policyChecks)?e.policyChecks:Object.values(e.policyChecks||{}),n=o.filter(l=>y(l)===!0).length,i=o.filter(l=>y(l)===!1).length,p=Array.isArray(e.allowlistHits)?e.allowlistHits.length:Object.keys(e.allowlistHits||{}).length,h=e.txHash==null?"no transaction hash":`tx ${e.txHash}`,w=e.balances==null?"balances not provided":"before/after balances recorded";return`${e.phase} ${t} via ${r}; policy ${n} passed, ${i} failed; ${p} allowlist hit${p===1?"":"s"}; ${h}; ${w}; receipt ${e.receiptId}`}var F=z;export{A as ACTION_RECEIPT_VERSION,f as ActionReceiptSecretError,L as assertNoReceiptSecrets,R as canonicalReceiptJson,k as computeReceiptId,q as createActionReceipt,F as formatActionReceipt,N as normalizeActionReceipt,z as summarizeActionReceipt};
@@ -0,0 +1 @@
1
+ var o=Object.freeze({ALERT_ONLY:"alert_only",EXECUTE:"execute"}),i=new Set(["watch","watch this","ping","ping me","alert","notify"]),r=new Set(["watching","armed"]);function a(t){if(typeof t!="string"||!t.trim())throw new TypeError("explicit action verb required");let e=t.trim().toLowerCase().replace(/\s+/g," ");if(i.has(e))return o.ALERT_ONLY;if(e==="arm")return o.EXECUTE;throw new TypeError(`unsupported action verb: ${e}`)}function c(t={}){let{verb:e,...n}=t;return{...n,active:!0,actionMode:a(e)}}function u(t){if(!t||typeof t!="object"||typeof t.active!="boolean")throw new TypeError("active must be boolean");if(!Object.values(o).includes(t.actionMode))throw new TypeError("actionMode must be alert_only or execute");return t}function E(t){return t?.active===!0&&t?.actionMode===o.ALERT_ONLY}function s(t){return t?.active===!0&&t?.actionMode===o.EXECUTE}function p(t={}){if(t.actionMode!==void 0&&t.actionMode!==o.ALERT_ONLY)throw new TypeError("non-alert record cannot enter alert-only watch migration");let e=typeof t.active=="boolean"?t.active:r.has(String(t.status||"").toLowerCase());return{...t,active:e,actionMode:o.ALERT_ONLY}}export{o as ACTION_MODES,a as actionModeForVerb,u as assertActionRecord,c as createActionRecord,E as isActiveAlert,s as isActiveExecution,p as migrateLegacyWatchRecord};
@@ -0,0 +1,2 @@
1
+ import c from"node:fs";import d from"node:path";import{homedir as b}from"node:os";import{join as h}from"node:path";var w=h(b(),".config","oracle"),z=h(b(),".config","mad-desk");function m(e,r,t=""){let o=process.env[e];if(o!=null&&String(o).trim()!=="")return o;let n=r?process.env[r]:void 0;return n!=null&&String(n).trim()!==""?n:t}var g=/^0x[0-9a-fA-F]{40}$/,_=new Set(["privatekey","private_key","secret","seed","mnemonic","passphrase","signature","keystore"]),D=["privatekey","privkey","secretkey","secret","seedphrase","seed","mnemonic","passphrase","password","keystore","keymaterial","signature","wif","xprv","xpriv","apikey","bearer","credential"],O=[/\b[5KL][1-9A-HJ-NP-Za-km-z]{50,51}\b/,/\bxprv[0-9A-Za-z]{50,}\b/,/\b(?:[a-z]{3,8}\s+){11,}[a-z]{3,8}\b/i],y=/^\s*(?:0x)?[0-9a-fA-F]{64}\s*$/;function I(e){return String(e).toLowerCase().replace(/[^a-z0-9]/g,"")}function L(e,r){let t=I(e);if(_.has(String(e).toLowerCase())||D.some(o=>t.includes(o)))throw new Error(`address-book: ${r} is forbidden; the book stores labels, never key material`)}function N(e,r){if(typeof e=="string"&&(O.some(t=>t.test(e))||y.test(e)))throw new Error(`address-book: ${r} looks like key material; the book stores labels, never key material`)}function E(){let e=m("ORACLE_ADDRESS_BOOK","MAD_ADDRESS_BOOK","");if(e)return d.resolve(e);let r=m("ORACLE_CONFIG_DIR","MAD_CONFIG_DIR",w);return d.join(r,"address-book.json")}function p(e,r="field"){if(Array.isArray(e)){e.forEach((t,o)=>p(t,`${r}[${o}]`));return}if(!e||typeof e!="object"){N(e,r);return}for(let[t,o]of Object.entries(e))L(t,t),p(o,t)}function S(e){let r=String(e||"").trim();if(!g.test(r))throw new Error("address-book: address must be 0x + 40 hex characters");return r.toLowerCase()}function a(e,r){return e==null||e===""?null:String(e).slice(0,r)}function k(){return{version:1,updatedAt:null,entries:[]}}function x(e){return{address:String(e.address).toLowerCase(),label:a(e.label,80)||"unknown",who:a(e.who,120),role:a(e.role,40),chainIds:Array.isArray(e.chainIds)?e.chainIds.map(Number).filter(Number.isFinite):[],notes:a(e.notes,500),source:a(e.source,80),firstSeenAt:e.firstSeenAt||null,lastSeenAt:e.lastSeenAt||null}}function l(){try{let e=JSON.parse(c.readFileSync(E(),"utf8"));if(!e||typeof e!="object")return k();let r=Array.isArray(e.entries)?e.entries:[];return{version:1,updatedAt:e.updatedAt||null,entries:r.filter(t=>t&&typeof t=="object"&&g.test(String(t.address||""))).map(x)}}catch{return k()}}function v(e){let r=E();c.mkdirSync(d.dirname(r),{recursive:!0,mode:448});let t={...e,version:1,updatedAt:new Date().toISOString()},o=d.join(d.dirname(r),`.address-book.${process.pid}.tmp`);c.writeFileSync(o,`${JSON.stringify(t,null,2)}
2
+ `,{mode:384}),c.renameSync(o,r);try{c.chmodSync(r,384)}catch{}return t}function G(e={}){let r=l(),t=r.entries;if(e.role&&(t=t.filter(o=>o.role===String(e.role))),e.who){let o=String(e.who).toLowerCase();t=t.filter(n=>(n.who||"").toLowerCase().includes(o)||(n.label||"").toLowerCase().includes(o))}if(e.q){let o=String(e.q).toLowerCase();t=t.filter(n=>n.address.includes(o)||(n.label||"").toLowerCase().includes(o)||(n.who||"").toLowerCase().includes(o)||(n.notes||"").toLowerCase().includes(o))}return{updatedAt:r.updatedAt,count:t.length,entries:t}}function P(e){let r=S(e),t=l().entries.filter(o=>o.address===r);return{address:r,found:t.length>0,entries:t}}function q(e={}){p(e);let r=S(e.address),t=a(e.label??e.role,80)||"wallet",o=new Date().toISOString(),n=l(),i=n.entries.findIndex(s=>s.address===r&&s.label===t),u=x({address:r,label:t,who:e.who,role:e.role,chainIds:e.chainIds,notes:e.notes,source:e.source||"agent",firstSeenAt:i>=0&&n.entries[i].firstSeenAt||o,lastSeenAt:o});i>=0?n.entries[i]=u:n.entries.push(u);let A=s=>s==="agent"?0:s==="owner"?1:2;n.entries.sort((s,f)=>A(s.role)-A(f.role)||s.label.localeCompare(f.label)||s.address.localeCompare(f.address));let C=v(n);return{ok:!0,entry:u,count:C.entries.length}}function Y(e,r=null){let t=S(e),o=l(),n=o.entries.length;return o.entries=o.entries.filter(i=>i.address!==t?!0:r==null?!1:i.label!==String(r)),v(o),{ok:!0,removed:n-o.entries.length,count:o.entries.length}}export{E as addressBookPath,Y as forgetAddress,G as listAddresses,P as lookupAddress,l as readAddressBook,q as rememberAddress};