@oracle-agent/oracle 0.24.1 → 0.24.2
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.
- package/dist/assets/skills/chain/SKILL.md +34 -0
- package/dist/assets/skills/chain-defi-ecosystem-analysis/SKILL.md +181 -0
- package/dist/assets/skills/chain-ecosystem-gap-analysis/SKILL.md +162 -0
- package/dist/assets/skills/cross-chain-twap-execution/SKILL.md +125 -0
- package/dist/assets/skills/defi-protocol-pmf-assessment/SKILL.md +332 -0
- package/dist/assets/skills/evm-contract-research.md +8 -3
- package/dist/assets/skills/multi-venue-prepare-only-ranking/SKILL.md +93 -0
- package/dist/assets/skills/oracle-access-control/SKILL.md +71 -0
- package/dist/assets/skills/oracle-action-arming/SKILL.md +99 -0
- package/dist/assets/skills/oracle-airdrop-calculator/SKILL.md +111 -0
- package/dist/assets/skills/oracle-desk-product/SKILL.md +341 -0
- package/dist/assets/skills/oracle-evm/SKILL.md +55 -0
- package/dist/assets/skills/oracle-harness/SKILL.md +41 -0
- package/dist/assets/skills/oracle-mcp-install/SKILL.md +140 -0
- package/dist/assets/skills/oracle-multichain-convert/SKILL.md +87 -0
- package/dist/assets/skills/oracle-native-harness/SKILL.md +32 -0
- package/dist/assets/skills/oracle-ownership-gate/SKILL.md +42 -0
- package/dist/assets/skills/oracle-public-product-ux/SKILL.md +114 -0
- package/dist/assets/skills/oracle-tailscale/SKILL.md +32 -0
- package/dist/assets/skills/oracle-thin-client/SKILL.md +47 -0
- package/dist/assets/skills/perp-venue-funding-research/SKILL.md +161 -0
- package/dist/assets/skills/polymarket/SKILL.md +160 -0
- package/dist/assets/skills/protocol-api-key-integration/SKILL.md +141 -0
- package/dist/assets/skills/self-custodial-onchain-execution/SKILL.md +1284 -0
- package/dist/assets/skills/setup/SKILL.md +40 -0
- package/dist/assets/skills/stable-launch-ops/SKILL.md +89 -0
- package/dist/assets/skills/trade-loop-circuit-breaker/SKILL.md +441 -0
- package/dist/assets/skills/venue-capability-boundaries/SKILL.md +32 -0
- package/dist/bin/desk-server.mjs +16 -16
- package/dist/bin/oracle-data-mcp.mjs +1 -1
- package/dist/bin/oracle-equities.mjs +1 -1
- package/dist/bin/oracle-init.mjs +9 -9
- package/dist/cli/commands/bootstrap.mjs +1 -1
- package/dist/cli/commands/chat.mjs +78 -77
- package/dist/cli/commands/doctor.mjs +8 -6
- package/dist/cli/commands/eval.mjs +1 -1
- package/dist/cli/commands/harness.mjs +6 -6
- package/dist/cli/commands/model.mjs +82 -81
- package/dist/cli/commands/receipt.mjs +5 -0
- package/dist/cli/commands/setup.mjs +1 -1
- package/dist/cli/commands/venues.mjs +3 -0
- package/dist/cli/commands/watch.mjs +16 -0
- package/dist/equities/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oracle-airdrop-calculator
|
|
3
|
+
description: Use when scanning a wallet for airdrop eligibility.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> Oracle native tools: `oracle_cli` (read/prepare), `vault_status`, `signer_status`, `signer_execute` (needs human confirmationNonce), `skill_load`. No generic shell. No fleet SSH.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Airdrop calculator (Oracle)
|
|
10
|
+
|
|
11
|
+
Use when DEMI asks to check a wallet's airdrop eligibility, scan for potential drops, or check "what airdrops am I qualified for." General-purpose — not tied to any single campaign.
|
|
12
|
+
|
|
13
|
+
## Architecture (shipped 2026-08-06)
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Oracle app API
|
|
17
|
+
→ GET /api/oracle/airdrop?wallet=0x...&format=summary|full
|
|
18
|
+
→ scanner.ts Blockscout V2 multi-chain activity profiler
|
|
19
|
+
→ campaign.ts known-campaign registry (12 programs, 8 ecosystems)
|
|
20
|
+
→ scorer.ts eligibility matching engine
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Code roots in `~/projects/oracle-app/`:
|
|
24
|
+
- `lib/oracle/airdrop/scanner.ts` — parallel Blockscout V2 scan
|
|
25
|
+
- `lib/oracle/airdrop/campaigns.ts` — campaign criteria registry
|
|
26
|
+
- `lib/oracle/airdrop/scorer.ts` — scoring engine
|
|
27
|
+
- `app/api/oracle/airdrop/route.ts` — API route
|
|
28
|
+
|
|
29
|
+
## How it works
|
|
30
|
+
|
|
31
|
+
**Scanner** profiles a wallet across all supported EVM chains using public Blockscout V2 APIs:
|
|
32
|
+
- `GET /api/v2/addresses/{wallet}/counters` → `transactions_count`
|
|
33
|
+
- `GET /api/v2/addresses/{wallet}` → `coin_balance` + `exchange_rate`
|
|
34
|
+
- `GET /api/v2/addresses/{wallet}/transactions` → age + protocol interactions (5s timeout, optional)
|
|
35
|
+
- `GET /api/v2/addresses/{wallet}/token-balances` → USD-denominated holdings
|
|
36
|
+
|
|
37
|
+
Chains are scanned in parallel (3 at a time). Transactions fetch has a 5s timeout — on huge wallets it times out gracefully and returns counters-only data.
|
|
38
|
+
|
|
39
|
+
**Campaign registry** holds 12 known programs with explicit criteria:
|
|
40
|
+
- Confirmed: Hyperliquid Points, HL Perps, Locals→STABLE
|
|
41
|
+
- Likely: HyperEVM Ecosystem, DeFi Power User
|
|
42
|
+
- Speculative: Base, Arbitrum, Optimism, Polygon, Abstract, LI.FI Loyalty, Across Bridge
|
|
43
|
+
|
|
44
|
+
**Scorer** compares wallet profile against each campaign's criteria, producing:
|
|
45
|
+
- `eligibility` 0-100%
|
|
46
|
+
- `verdict`: eligible / partial / ineligible / unknown
|
|
47
|
+
- `matchedCriteria` + `missedCriteria` lists
|
|
48
|
+
- Per-criterion detail logs
|
|
49
|
+
|
|
50
|
+
## API
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
# Summary (fast, overview only)
|
|
54
|
+
GET /api/oracle/airdrop?wallet=0x...&format=summary
|
|
55
|
+
|
|
56
|
+
# Full (campaign-by-campaign detail)
|
|
57
|
+
GET /api/oracle/airdrop?wallet=0x...&format=full
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Response includes `totalTx`, `totalVolumeUsd`, `chainCount`, `isMultiChain`, `walletAgeDays`, and per-campaign scores.
|
|
61
|
+
|
|
62
|
+
## Adding campaigns
|
|
63
|
+
|
|
64
|
+
Edit `lib/oracle/airdrop/campaigns.ts` — add an entry to the `CAMPAIGNS` array:
|
|
65
|
+
```ts
|
|
66
|
+
{
|
|
67
|
+
id: "unique-id",
|
|
68
|
+
name: "Human Name",
|
|
69
|
+
token: "TICKER",
|
|
70
|
+
chainId: "base",
|
|
71
|
+
status: "active" | "upcoming" | "completed" | "rumored",
|
|
72
|
+
confidence: "confirmed" | "likely" | "speculative",
|
|
73
|
+
criteria: [
|
|
74
|
+
{ kind: "tx_count", min: 10, description: "10+ tx" },
|
|
75
|
+
{ kind: "volume_usd", min: 1000, description: "$1k+ volume" },
|
|
76
|
+
{ kind: "chain_used", chainId: "base", description: "Activity on Base" },
|
|
77
|
+
{ kind: "protocol_used", contract: "0x...", chainId: 8453, label: "Protocol Name" },
|
|
78
|
+
{ kind: "wallet_age_days", min: 30, description: "30+ days old" },
|
|
79
|
+
{ kind: "nft_held", contract: "0x...", chainId: 999, label: "NFT Name" },
|
|
80
|
+
{ kind: "points_eligible", program: "hyperliquid", description: "Points program" },
|
|
81
|
+
],
|
|
82
|
+
source: "https://official.source",
|
|
83
|
+
allocationEstimate: "Range or methodology description",
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`nft_held` and `points_eligible` criteria are skipped in scoring (require dedicated APIs). All other criteria are checkable from Blockscout data alone.
|
|
88
|
+
|
|
89
|
+
## Blockscout V2 API quirks
|
|
90
|
+
|
|
91
|
+
- **Counters endpoint is `/counters`** not `/addresses/{wallet}` for tx count — the address endpoint does NOT include `tx_count`
|
|
92
|
+
- **`transactions_count` is a string**, not a number — parseInt it
|
|
93
|
+
- **Transactions `to` field** is `{ hash: "0x..." }` not a flat string
|
|
94
|
+
- **Token balances** nest: `{ token: { exchange_rate, decimals }, value }` — not flat
|
|
95
|
+
- **`coin_balance`** is in wei (divide by 1e18)
|
|
96
|
+
- **`exchange_rate`** is a USD string on the address object
|
|
97
|
+
|
|
98
|
+
## Performance design
|
|
99
|
+
|
|
100
|
+
- Parallel scan (3 chains at a time) avoids rate-limiting
|
|
101
|
+
- Transaction fetch has 5s timeout — skips gracefully on huge wallets
|
|
102
|
+
- 0 tx on a chain = early return, skip remaining fetches
|
|
103
|
+
- Summary mode skips per-campaign detail for fast response
|
|
104
|
+
|
|
105
|
+
## Pitfalls
|
|
106
|
+
|
|
107
|
+
- Blockscout instances vary by chain — URLs are hardcoded per chain in `blockscoutUrl()`
|
|
108
|
+
- Chains without Blockscout return `error: "no explorer available"`
|
|
109
|
+
- A wallet with 0 tx everywhere returns `ineligible` for all campaigns — not an error
|
|
110
|
+
- `nft_held` and `points_eligible` criteria always return "unknown" — they need dedicated API integration
|
|
111
|
+
- The `totalVolumeUsd` is based on current token holdings, not historical trade volume — it's a lower bound
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oracle-desk-product
|
|
3
|
+
description: Use for Oracle product law, self-host C+B, NL confirm/arm.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> Oracle native tools: `oracle_cli` (read/prepare), `vault_status`, `signer_status`, `signer_execute` (needs human confirmationNonce), `skill_load`. No generic shell. No fleet SSH.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Oracle desk product
|
|
10
|
+
|
|
11
|
+
Class-level product law for the Oracle multichain agent desk (app + CLI self-host).
|
|
12
|
+
|
|
13
|
+
## One-line definition
|
|
14
|
+
|
|
15
|
+
**Oracle = multi-chain, self-custodial, locally hosted agent harness.**
|
|
16
|
+
|
|
17
|
+
| Word | Meaning |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Multi-chain | EVM + Sol + BTC + HL/RH/Stable |
|
|
20
|
+
| Self-custodial | Keys on user machine or user wallet — never house cloud |
|
|
21
|
+
| Locally hosted | Desk/exec/policy on 127.0.0.1 / their box by default |
|
|
22
|
+
| Agent harness | NL chat → quote → confirm/arm → policy → sign → receipt |
|
|
23
|
+
|
|
24
|
+
## C + B (custody + rails)
|
|
25
|
+
|
|
26
|
+
| Layer | |
|
|
27
|
+
|---|---|
|
|
28
|
+
| **C** | `oracle sign init` on **their** disk. **Never paste seed in app UI.** |
|
|
29
|
+
| **B** | `~/.config/oracle/agent-policy.json` — $/trade, $/day, chains, slip, TTL, arm/disarm, **`noLimits`** |
|
|
30
|
+
|
|
31
|
+
### Policy-file integrity — RESOLVED (2026-08-08, multi-model audit 5/5 HIGH)
|
|
32
|
+
`agent-policy.json` now carries a **SHA-256 `integrity` field** over its canonical
|
|
33
|
+
body (fixed field order in `canonicalPolicyBody`). `loadAgentPolicy` fails CLOSED:
|
|
34
|
+
a file edited outside `saveAgentPolicy` (e.g. `echo '{"noLimits":true}' >
|
|
35
|
+
agent-policy.json`) no longer hashes to its own integrity → loads as **DISARMED**,
|
|
36
|
+
never as a broader grant. Save re-signs every write (mode 0600). Rules:
|
|
37
|
+
- Never let a tampered file WIDEN caps — always disarmed.
|
|
38
|
+
- Missing `integrity` on an existing file is tolerated (pre-upgrade files still
|
|
39
|
+
load), but any present-yet-mismatched integrity disarms.
|
|
40
|
+
- Unit check before shipping changes: valid passes, tampered fails, missing fails.
|
|
41
|
+
- Legacy `unlimited` key still maps to `noLimits` for compat.
|
|
42
|
+
|
|
43
|
+
### Policy modes
|
|
44
|
+
|
|
45
|
+
- **With limits** — enforce before agent sign; daily ledger
|
|
46
|
+
- **No limits** — skip caps; **Disarm still kills**; all-EVM preset
|
|
47
|
+
- API: `POST /api/oracle/agent/policy` actions `no_limits` \| `with_limits` \| `arm` \| `disarm`
|
|
48
|
+
|
|
49
|
+
DEMI Mac often: noLimits + armed + all EVM.
|
|
50
|
+
|
|
51
|
+
### Agent parity — the admin/no-fees variant shares ONE policy source (RESOLVED 2026-08-09)
|
|
52
|
+
|
|
53
|
+
There are TWO packages, NOT one:
|
|
54
|
+
- `@oracle-agent/oracle` — public npm. Prepare-only by default/hosted; self-hosters get
|
|
55
|
+
encrypted local vault + loopback signer for **their** keys, with public fees
|
|
56
|
+
(`~/projects/oracle`).
|
|
57
|
+
- `@oracle-agent/agent` — ADMIN variant, same capability, **zero** Oracle fees; DEMI's
|
|
58
|
+
local signer/key vault (`~/projects/oracle-agent`, SEPARATE repo). One-way dep:
|
|
59
|
+
agent pins `oracle`; oracle never imports agent. Separate repos/releases.
|
|
60
|
+
|
|
61
|
+
**Naming LAW (DEMI 2026-08-09): the word "operator" is GONE from the product surface.**
|
|
62
|
+
It is the AGENT everywhere. The old npm name ``@oracle-agent/agent` (private, never npm)` was **fully
|
|
63
|
+
unpublished 2026-08-09 (now E404)** — deprecation was only the stopgap; the tarball is
|
|
64
|
+
gone and the name must never be published again. Bins renamed: `oracle-operator` →
|
|
65
|
+
`oracle-agent`, `oracle-operator-caps` → `oracle-agent-caps`. Repo+dir renamed
|
|
66
|
+
`oracle-operator` → `oracle-agent`. When touching copy/docs/code: never reintroduce
|
|
67
|
+
"operator" for the product role. KEEP the EVM-standard homonym "operator"
|
|
68
|
+
(setApprovalForAll/approve — the approved address) and the comparison-operator identifier
|
|
69
|
+
in action-runner; those are unrelated to the product role and must stay. If a doc/code
|
|
70
|
+
audit turns up a product-role "operator", rename it to "agent" (see
|
|
71
|
+
`references/agent-rename-and-npm.md`).
|
|
72
|
+
|
|
73
|
+
**Renames are not done when the source is clean — they are done when the SHIPPED
|
|
74
|
+
ARTIFACT is clean.** A rename landed in source can still reach users through stale
|
|
75
|
+
build output: a packaged desktop runtime kept telling users to
|
|
76
|
+
`npm i -g @oracle-agent/oracle` (a package that no longer exists)
|
|
77
|
+
because cached content-hashed chunks rode along in the artifact. After any product-surface
|
|
78
|
+
rename, grep the packaged runtime for the old token, not just the repo.
|
|
79
|
+
|
|
80
|
+
Parity trigger = product-version (product law changes like custody semantics), NOT repo-version.
|
|
81
|
+
"Similar" is not "verified identical" — when asked if the two are in parity, DIFF the security
|
|
82
|
+
surfaces, don't assume.
|
|
83
|
+
|
|
84
|
+
### Public local signer: product law vs shipped fact (DEMI law; verify every claim)
|
|
85
|
+
DEMI's intended public product is **self-hosted Oracle + a loopback local signer for the
|
|
86
|
+
user's own keys**. The private `@oracle-agent/agent` remains the ADMIN/no-fees vault and is
|
|
87
|
+
never published. The split is about WHOSE keys, not whether self-hosting is allowed.
|
|
88
|
+
|
|
89
|
+
Do **not** turn the product target into a shipped-capability claim. Before answering "does
|
|
90
|
+
public have a local signer?", verify these three surfaces independently:
|
|
91
|
+
1. `origin/main` public package: signer commands/modules and custody-boundary tests.
|
|
92
|
+
2. Published npm `latest`: version and packed artifact, not merely source main.
|
|
93
|
+
3. This machine's deployment: active binary path plus loopback signer service/port.
|
|
94
|
+
|
|
95
|
+
Report them separately. A private deployment having `oracle-signer` active on `127.0.0.1`
|
|
96
|
+
does not prove npm users receive it. A locally hosted model/data/policy loop does not imply
|
|
97
|
+
a bundled signer. A merged feature is not public until the npm artifact containing it is
|
|
98
|
+
published and inspected.
|
|
99
|
+
|
|
100
|
+
**Current verified state as of 2026-08-12:** public npm `@oracle-agent/oracle@0.24.0`
|
|
101
|
+
ships the optional encrypted local vault + short-lived loopback signer. Hosted/default
|
|
102
|
+
Oracle stays prepare-only. Self-host after `oracle sign init|import` is **auto-armed**
|
|
103
|
+
for user-initiated actions. Public still charges the disclosed fee card; Administrator
|
|
104
|
+
(`@oracle-agent/agent`, never on npm) stays zero-fee with DEMI's keys.
|
|
105
|
+
|
|
106
|
+
Public signer families are **EVM, Solana, Bitcoin only** — not separate HL/Poly
|
|
107
|
+
account surfaces. Do not resurrect Tread.fi OEMS/API protocol interaction; TradFi
|
|
108
|
+
algorithms (TWAP/VWAP/POV/iceberg/IS) are native Oracle planners, not an external
|
|
109
|
+
broker.
|
|
110
|
+
|
|
111
|
+
A merged PR is still not "shipped" until `npm view @oracle-agent/oracle version`
|
|
112
|
+
matches the intended release and the packed tarball was secret-scanned. Never accept
|
|
113
|
+
"key file exists" or "service is active" as proof that public onboarding works.
|
|
114
|
+
|
|
115
|
+
Detail: `references/public-admin-parity.md`.
|
|
116
|
+
|
|
117
|
+
**Key-path wiring bug found + fixed 2026-08-09 (verify this stays wired).** `oracle sign
|
|
118
|
+
import` wrote the key to `<config>/keys/evm.json` and armed `exec.env`, but the loopback
|
|
119
|
+
signer daemon resolves key material from the vault path written by `oracle sign import`.
|
|
120
|
+
A freshly imported key was **silently
|
|
121
|
+
never picked up** by `oracle signer` — import reported success, signing just never found
|
|
122
|
+
it. Fix: import now also writes `signer.env` pointing both vars at the file it created,
|
|
123
|
+
preserving other entries (`wireSignerKeyEnv` in `src/cli/commands/sign.mjs`; regression
|
|
124
|
+
test in `test/cli-signplane.test.mjs` asserts key material, shred, arm, AND env wiring).
|
|
125
|
+
Lesson for this class: "the key file exists on disk" is NOT proof the signer can sign —
|
|
126
|
+
trace provision → env → daemon resolution end to end before claiming a signer works.
|
|
127
|
+
Note `sign.mjs` is ESM: helpers need `await import("node:fs"/"node:path")`, and `join`
|
|
128
|
+
scoped inside a verb block is not visible to a module-level helper.
|
|
129
|
+
|
|
130
|
+
The gap found 2026-08-09: agent enforced only its own env caps (`ORACLE_MAX_NOTIONAL_USD`, …)
|
|
131
|
+
and NEVER read the app's `agent-policy.json` — two B walls that could drift (app UI noLimits
|
|
132
|
+
while signer still enforced env caps; env raised while app route still capped). Fixed:
|
|
133
|
+
- `src/agent-policy-file.mjs` reads the SAME `~/.config/oracle/agent-policy.json` with the SAME
|
|
134
|
+
SHA-256 integrity algorithm (`oracle-agent-policy:v1:` + canonical 10-field body). Verified
|
|
135
|
+
hash-for-hash identical to the app — a file signed by the app verifies on the signer.
|
|
136
|
+
- Tampered/corrupt/no-integrity policy → signer DISARMS regardless of env (a disarmed app must
|
|
137
|
+
mean a disarmed signer; no split-brain escape hatch).
|
|
138
|
+
- Valid file merges maxUsdPerTrade/maxUsdPerDay as the cap FLOOR; env caps may only TIGHTEN.
|
|
139
|
+
- Valid noLimits lifts file dollar caps but env caps stay authoritative.
|
|
140
|
+
- KEEP the hash algorithm byte-identical across both sides — a mismatch silently disarms.
|
|
141
|
+
|
|
142
|
+
Detail + the full parity diff table: `references/agent-parity.md`.
|
|
143
|
+
|
|
144
|
+
## Chat trade flow (required UX)
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
user: swap .1 eth to base
|
|
148
|
+
app: Prepared · not signed
|
|
149
|
+
user: confirm | arm | yes | go
|
|
150
|
+
app: policy → execute → tx hash
|
|
151
|
+
user: cancel
|
|
152
|
+
app: drop quote
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- Parse `swap .1 eth to base` → ETH→**USDC** on **Base** (leading-dot amounts OK).
|
|
156
|
+
- Primary = **conversational** confirm/arm; buttons secondary.
|
|
157
|
+
- Default: **confirm each trade** until auto-within-rails is explicit.
|
|
158
|
+
- Chat `arm` = execute **pending quote**. Settings Arm = kill-switch allow execute. Disambiguate.
|
|
159
|
+
|
|
160
|
+
### Arm disambiguation — RESOLVED (2026-08-08, multi-model audit consensus 5/5)
|
|
161
|
+
The two `arm` surfaces are now labeled differently in the UI:
|
|
162
|
+
- **Settings global kill-switch**: button **"Enable execution" / "Disable execution"**, status
|
|
163
|
+
pill **"execution on" / "execution off"** (never "armed"). Copy: *"Global kill-switch ·
|
|
164
|
+
distinct from chat 'arm' (one trade)"* and *"Chat 'arm' still requires this kill-switch on."*
|
|
165
|
+
- **Chat `arm`**: unchanged — executes ONE pending quote via `parseConfirmIntent`. It fails
|
|
166
|
+
closed when the Settings kill-switch is off (`checkAgentPolicy` `disarmed` gate).
|
|
167
|
+
- Internal `agent-policy.json` field stays `armed` (API compat) — the change is UI-label only
|
|
168
|
+
in `AgentPolicySettings.tsx`. Keep these labels distinct; do not collapse them back to one
|
|
169
|
+
"arm" word.
|
|
170
|
+
|
|
171
|
+
### Receipt discipline in the UI — RESOLVED (2026-08-08, multi-model audit consensus 4/5)
|
|
172
|
+
- Celebration overlay fires ONLY when `trade.status === "done" && trade.txHash` — no receipt
|
|
173
|
+
hash, no fireworks. "Done" without a hash is a UI claim, not proof.
|
|
174
|
+
- Agent path with no txHash says: *"Submitted — no receipt hash returned. Verify on-chain
|
|
175
|
+
before treating as settled."* Never print bare "Done." without a hash.
|
|
176
|
+
- Per-trade confirm is structurally enforced via `confirmToken` even under `noLimits` — the
|
|
177
|
+
"no dollar cap but still confirm" invariant holds at the chat layer.
|
|
178
|
+
|
|
179
|
+
### Confirm-token one-time consume — RESOLVED (2026-08-09, Grok 4.5 red-team leg)
|
|
180
|
+
Grok 4.5 (6th auditor) found: owner confirm tokens were verified by HMAC + 3-min TTL only,
|
|
181
|
+
with NO spent-nonce tracking — the same token could replay the identical intent within the
|
|
182
|
+
TTL window. Fix: `lib/oracle/confirm-nonce.ts` (`tryConsumeNonce`) — a shared atomic
|
|
183
|
+
spent-nonce registry consumed by BOTH owner-exec routes (`owner/swap`, `trade/quote`). A
|
|
184
|
+
second use of any token fails "already used — re-quote". Rules:
|
|
185
|
+
- Token mints bind 14 intent fields (nonce, chainId, tokenIn, amountIn, txTo, source, ...)
|
|
186
|
+
— replaying a token against different intent fields fails HMAC anyway.
|
|
187
|
+
- Strategy/shadow modules must have ZERO edges to owner-exec (verified clean).
|
|
188
|
+
- Keep the consume check inside verify, right after TTL check, before returning ok.
|
|
189
|
+
- Regression tests: `test/confirm-nonce.test.mjs`.
|
|
190
|
+
|
|
191
|
+
Code: `lib/oracle/confirm-nonce.ts`, `app/api/oracle/owner/swap/route.ts`, `app/api/oracle/trade/quote/route.ts`.
|
|
192
|
+
|
|
193
|
+
Code: `lib/oracle/swap-intent.ts`, `ChatDeskPane`, `/api/oracle/trade/quote`.
|
|
194
|
+
|
|
195
|
+
## Sessions persist, and they are scoped BY CHAIN (DEMI law 2026-08-09)
|
|
196
|
+
|
|
197
|
+
DEMI: *"oracle should also have sessions on the side so when you go back to chat
|
|
198
|
+
you dont lose where you left off IE, building something and if you were on a
|
|
199
|
+
chain it should seperate sessions by chain."*
|
|
200
|
+
|
|
201
|
+
- The chat surface is **not stateless**. Returning to chat resumes exactly where
|
|
202
|
+
the last session stopped — mid-build, mid-comparison, mid-prepare.
|
|
203
|
+
- Sessions are **partitioned by chain**. Work begun while pinned to a chain
|
|
204
|
+
belongs to that chain's thread; `/chain` switches thread, and switching back
|
|
205
|
+
restores that chain's in-flight context instead of starting cold or bleeding
|
|
206
|
+
another chain's state into it.
|
|
207
|
+
- `~/.config/oracle/active-chain.json` already tracks the pinned chain and is
|
|
208
|
+
the natural partition key.
|
|
209
|
+
- "Which chain was I on" and "what was I doing" are the SAME lookup. Losing
|
|
210
|
+
either is the failure this exists to prevent.
|
|
211
|
+
- Session state carries build/trade context ONLY. **Oracle never holds the
|
|
212
|
+
keys** — never persist passphrases, tokens, or key material into a session.
|
|
213
|
+
|
|
214
|
+
## Custody honesty
|
|
215
|
+
|
|
216
|
+
- Wallet path: address only + wallet popup sign.
|
|
217
|
+
- Agent path: local agent key via CLI, not app paste.
|
|
218
|
+
- B-alone (Permit2 session) ≠ “sign every time”; product is **C+B**.
|
|
219
|
+
|
|
220
|
+
## Self-host surfaces
|
|
221
|
+
|
|
222
|
+
- `/api/oracle/selfhost/status|init` — local desk URLs, no keys
|
|
223
|
+
- Onboarding: Your machine. Your agent. Your keys.
|
|
224
|
+
- Downloaders ≠ Arch Tailscale default (DEMI thin-client is ops-only)
|
|
225
|
+
|
|
226
|
+
## Portfolio
|
|
227
|
+
|
|
228
|
+
- Coin list primary; Swap/Send prefill
|
|
229
|
+
- **TokenLogo** on holdings when picture exists
|
|
230
|
+
- Stable ERC-20 (FEFER): watch-token probe
|
|
231
|
+
|
|
232
|
+
## Navigation + rail (audit-consensus decisions, 2026-08-08)
|
|
233
|
+
|
|
234
|
+
- **Tab labels describe function, never repeat the brand.** Primary chat tab is
|
|
235
|
+
**"Desk"** (NOT "Oracle" — the audit called brand-name tabs a same-brand
|
|
236
|
+
collision; the product mark in the header stays "Oracle"). Swap tab is
|
|
237
|
+
**"Simulate"** (dry-run sandbox naming; the NL harness lives in Desk, so
|
|
238
|
+
Prepare/confirm/sign are NOT a separate stage tab).
|
|
239
|
+
- **Portfolio rail defaults OPEN on desktop ≥1280px**, closed on smaller
|
|
240
|
+
viewports, and the user's explicit collapse/expand persists to
|
|
241
|
+
`localStorage("oracle-rail-open")`. The default is applied in a mounted
|
|
242
|
+
effect (SSR-safe — initial state is always false, so no hydration mismatch).
|
|
243
|
+
- **Every mono figure uses tabular-nums + lining-nums** (globals.css on
|
|
244
|
+
`.font-mono`, `.font-mono-ui`, code/kbd) — JB Mono digits align vertically;
|
|
245
|
+
this is what makes a financial desk font a financial desk font.
|
|
246
|
+
|
|
247
|
+
## Evals
|
|
248
|
+
|
|
249
|
+
- Existing: `packages/oracle/test`, `adversarial-bench.mjs`, Hermes `skill_eval.py`
|
|
250
|
+
- Desired desk suite: parse → quote → policy → confirm/arm → receipt (fixture RPC)
|
|
251
|
+
|
|
252
|
+
## Fees — MINIMAL, disclosed, and pinned (DEMI law 2026-08-09)
|
|
253
|
+
|
|
254
|
+
DEMI's standing preference: **"whats our bps fees they should be minimal."**
|
|
255
|
+
When a change makes a fee legible, do not recite the code comment as if it
|
|
256
|
+
settled the rate — state the real numbers from source and propose one.
|
|
257
|
+
|
|
258
|
+
Current rate card (all OFF unless a recipient is configured; holders pay zero):
|
|
259
|
+
|
|
260
|
+
| Rail | bps |
|
|
261
|
+
|---|---|
|
|
262
|
+
| swap | 5 |
|
|
263
|
+
| bridge | 5 |
|
|
264
|
+
| perps / nft | 0 |
|
|
265
|
+
| HL builder codes | perp 2 · spot 1 · hip3 1 · hip4 1 (cap 10) |
|
|
266
|
+
|
|
267
|
+
**One flat rate beats per-action tiers.** Bridge was 15 bps until 2026-08-09 on
|
|
268
|
+
a "longer settlement, more failure modes" rationale — that prices OUR effort,
|
|
269
|
+
not user value, on a heavily comparison-shopped action. It was also
|
|
270
|
+
structurally self-defeating: only `lifi`/`paraswap` apply the integrator fee
|
|
271
|
+
while bridge candidates are `lifi`/`relay`/`across`, so once the router began
|
|
272
|
+
subtracting our own fee from `netOut`, the high tier handicapped the one venue
|
|
273
|
+
that charged it — collecting almost nothing while making an identical bridge
|
|
274
|
+
cost different amounts depending on which venue won. A per-venue accident is
|
|
275
|
+
not a pricing tier.
|
|
276
|
+
|
|
277
|
+
Three invariants to keep:
|
|
278
|
+
|
|
279
|
+
- **A cost we charge is a cost we rank on.** Subtract the fee before ranking
|
|
280
|
+
routes, including on the degraded/gross path — a fee taken off the output is
|
|
281
|
+
exactly known even when gas is not. Otherwise "cheapest" is a number the user
|
|
282
|
+
never receives, breaking hard rule 0.
|
|
283
|
+
- **Disclosure must reach a user, not just exist.** `describeFee()` sat with
|
|
284
|
+
zero production callers for a whole release: defined, unit-tested, rendered
|
|
285
|
+
nowhere. A disclosure function nobody calls is an unenforced invariant. Grep
|
|
286
|
+
for CALLERS outside the module and its tests before believing a fee is shown.
|
|
287
|
+
- **Never stack rails.** perps/nft carry a 0 bps integrator tier precisely so a
|
|
288
|
+
Hyperliquid trade is charged only by its builder code. This is now pinned by
|
|
289
|
+
a test — if either tier goes nonzero, one action gets billed twice.
|
|
290
|
+
|
|
291
|
+
**Pin every beneficiary of a value transfer.** Both paying addresses
|
|
292
|
+
(`ORACLE_INTEGRATOR_FEE_RECIPIENT` and `ORACLE_HL_BUILDER_ADDRESS`) were
|
|
293
|
+
shape-validated only (`0x` + 40 hex), so anything that could write an env var —
|
|
294
|
+
a shell rc, a CI var, a stray `.env`, an npm postinstall — silently redirected
|
|
295
|
+
user money. Both now check `~/.config/oracle/fee-recipient` (0600, one file for
|
|
296
|
+
both rails so they cannot disagree) and fail **CLOSED to ZERO fee** on
|
|
297
|
+
mismatch, never to "charge anyway to an unverified address." Unpinned installs
|
|
298
|
+
are unchanged, so it is opt-in. Be honest about scope in the code comment: the
|
|
299
|
+
pin does not stop code that can also rewrite the pin file — it raises the bar
|
|
300
|
+
from "any env write anywhere" to "write this specific file" and makes the
|
|
301
|
+
authorized recipient auditable.
|
|
302
|
+
|
|
303
|
+
## Audit discipline (DEMI preference, corrected 2026-08-09)
|
|
304
|
+
|
|
305
|
+
- **After a multi-model audit, apply EVERY recommendation.** Do not list
|
|
306
|
+
"kept intentionally" dissent items as the default outcome — DEMI reads that
|
|
307
|
+
as unfinished work ("i thought we fixed all") and will say "keep what you
|
|
308
|
+
recommend", meaning fix them. Only truly user-directed keeps survive, and
|
|
309
|
+
only with explicit sign-off per item.
|
|
310
|
+
- When a red-team/audit finding says "must verify in-repo", verify it against
|
|
311
|
+
the tree BEFORE reporting — a red-team claim is a hypothesis, not a fact.
|
|
312
|
+
- Report the verdict count as N/M across auditors (e.g. 5/6 ship-with-fixes)
|
|
313
|
+
and name which auditor dissented.
|
|
314
|
+
- 7-auditor roster: deepseek-v4-pro · deepseek-v4-flash · gpt-5.6-sol · opus-5 ·
|
|
315
|
+
opus-4-8 · fable-5 · grok-4.5 (xai-oauth). Both DeepSeek legs route through
|
|
316
|
+
**`nous-direct`** (`deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`) —
|
|
317
|
+
the bare `deepseek` provider has an empty credential pool and its
|
|
318
|
+
`No usable credentials` error does NOT mean the model is unavailable. Harness:
|
|
319
|
+
`~/.hermes/profiles/oracle/scripts/oracle-multimodel-audit.sh`, brief refreshed
|
|
320
|
+
to current state before each run. Full procedure: `multi-model-product-audit`.
|
|
321
|
+
|
|
322
|
+
## Pitfalls
|
|
323
|
+
|
|
324
|
+
- Electron fake-home can hide `~/.config/oracle` / force execute off — use `ORACLE_REAL_HOME`.
|
|
325
|
+
- Never claim house signs for downloaders.
|
|
326
|
+
- Do not auto-broadcast on quote.
|
|
327
|
+
- Overlap: `oracle-public-product-ux` (chrome/themes); this skill owns product definition + confirm/arm + noLimits.
|
|
328
|
+
|
|
329
|
+
## References
|
|
330
|
+
|
|
331
|
+
- `references/nl-confirm-arm.md` — chat confirm/arm parse + arm disambiguation
|
|
332
|
+
- `references/agent-policy-nolimits.md` — noLimits / API actions
|
|
333
|
+
- `references/agent-parity.md` — agent=admin variant parity diff, shared-policy hash fix, merge-vs-remote-CI-shape-tests technique
|
|
334
|
+
- `references/agent-rename-and-npm.md` — the 2026-08-09 operator→agent rename procedure + npm unpublish/deprecate/2FA knowledge
|
|
335
|
+
- `references/public-admin-parity.md` — public vs Admin: whose keys, fees, auto-arm, EVM/SOL/BTC-only signer, no Tread OEMS
|
|
336
|
+
|
|
337
|
+
## Related
|
|
338
|
+
|
|
339
|
+
- `oracle-public-product-ux` — app chrome, themes (overlaps; curator may merge later)
|
|
340
|
+
- `oracle-action-semantics` — watch vs arm planes
|
|
341
|
+
- `oracle-fleet-desk-wiring` — DEMI Mac→Arch
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oracle-evm
|
|
3
|
+
description: Use for any EVM chain desk work — ETH, Base, Arb, OP, Polygon, BSC, Avalanche, HyperEVM, Abstract, Stable, RH, or a registered extra chain.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> Oracle native tools: `oracle_cli` (read/prepare), `vault_status`, `signer_status`, `signer_execute` (needs human confirmationNonce), `skill_load`. No generic shell. No fleet SSH.
|
|
7
|
+
|
|
8
|
+
# Oracle EVM desk
|
|
9
|
+
|
|
10
|
+
Same agent, same vault, same key. Different `chainId`.
|
|
11
|
+
|
|
12
|
+
Do **not** treat Robinhood (4663) or HyperEVM (999) as the only EVM surfaces.
|
|
13
|
+
If the token’s home chain is Base / Arb / ETH / …, work there.
|
|
14
|
+
|
|
15
|
+
## Shipped registry (`src/chains.mjs`)
|
|
16
|
+
|
|
17
|
+
| key | chainId | name |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| ethereum | 1 | Ethereum |
|
|
20
|
+
| optimism | 10 | OP Mainnet |
|
|
21
|
+
| bsc | 56 | BNB Smart Chain |
|
|
22
|
+
| polygon | 137 | Polygon |
|
|
23
|
+
| abstract | 2741 | Abstract |
|
|
24
|
+
| base | 8453 | Base |
|
|
25
|
+
| hyperevm | 999 | HyperEVM |
|
|
26
|
+
| stable | 988 | Stable Mainnet |
|
|
27
|
+
| avalanche | 43114 | Avalanche C-Chain |
|
|
28
|
+
| arbitrum | 42161 | Arbitrum One |
|
|
29
|
+
| robinhood | 4663 | Robinhood Chain |
|
|
30
|
+
|
|
31
|
+
Unknown chain → `oracle chain list`, then DexScreener via `oracle_cli` `data call dex-screener …`. If still ambiguous, ask. Never guess a chainId.
|
|
32
|
+
|
|
33
|
+
A new EVM chain can be registered at runtime (`registerChain`). Unsupported = `UNAVAILABLE`, not fake coverage.
|
|
34
|
+
|
|
35
|
+
## How to work a request
|
|
36
|
+
|
|
37
|
+
1. Resolve home chain first (`dex_search` / `dex_token`).
|
|
38
|
+
2. Pin: `oracle chain use <key>` (or `argv ['chain','use','base']` via `oracle_cli` is not allowed — chain use is a CLI pin; in native chat use `/chain`).
|
|
39
|
+
3. Quote net of gas: `oracle_cli` `route swap` / `route bridge`. Rank on **net received**.
|
|
40
|
+
4. Prepare unsigned. Confirm is human. `signer_execute` needs a confirmationNonce.
|
|
41
|
+
5. Receipt or it did not happen.
|
|
42
|
+
|
|
43
|
+
## Surfaces (all EVM)
|
|
44
|
+
|
|
45
|
+
- swap / bridge / approve / mint
|
|
46
|
+
- token + contract research
|
|
47
|
+
- meme scan (`evm_token_sniper_scan` is the same scanner on every supported EVM)
|
|
48
|
+
- NFT mint gas-war caps
|
|
49
|
+
- RFQ / tokenized assets when the venue exists on that chain
|
|
50
|
+
|
|
51
|
+
Solana and Bitcoin are separate signer families. HL L1 perps and Polymarket are data/prepare venues, not extra EVM signer families.
|
|
52
|
+
|
|
53
|
+
## Related
|
|
54
|
+
|
|
55
|
+
`chain` · `evm-contract-research` · `oracle-best-execution` · `oracle-meme-token-sniper` · `oracle-multichain-convert` · `venue-capability-boundaries`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oracle-harness
|
|
3
|
+
description: Use when deciding what Oracle native absorbs from Hermes, Claude, Codex, or other clients.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Oracle is the harness
|
|
7
|
+
|
|
8
|
+
Oracle native (`oracle chat`) is the product loop. Other clients are **feature sources** and optional engines, not the home.
|
|
9
|
+
|
|
10
|
+
## Absorb (public)
|
|
11
|
+
|
|
12
|
+
From Hermes / Claude / Codex / Cursor-class agents, ship the **desk capabilities**, not the brand:
|
|
13
|
+
|
|
14
|
+
| Capability | Oracle surface |
|
|
15
|
+
|---|---|
|
|
16
|
+
| Agent loop + tools | standalone client (16–50 steps) |
|
|
17
|
+
| Skills | packaged + `~/.config/oracle/skills/<name>/SKILL.md` |
|
|
18
|
+
| Memory / cron / todos / session | native tools |
|
|
19
|
+
| Web fetch + search | `web_fetch` / `web_search` |
|
|
20
|
+
| Bounded browser + vision | `browser_exec` / `vision_analyze` |
|
|
21
|
+
| MCP in and out | `mcp_list` / `mcp_call` + `oracle mcp install` |
|
|
22
|
+
| Plugins | `oracle plugins install` |
|
|
23
|
+
| Multi-model | `oracle setup model` / `/model` |
|
|
24
|
+
| Attach another engine | `oracle chat --backend hermes\|claude\|codex` |
|
|
25
|
+
| Quote / route / prepare | `oracle_cli` |
|
|
26
|
+
| Local sign | vault + loopback `signer_execute` (human nonce) |
|
|
27
|
+
| All shipped EVM | `oracle-evm` — same vault, different chainId |
|
|
28
|
+
| Your desk across your machines | `oracle-thin-client` / `oracle-tailscale` placeholders |
|
|
29
|
+
|
|
30
|
+
## Do not absorb into public
|
|
31
|
+
|
|
32
|
+
- Fleet SSH / Kanban / Orca / Pop-PC2
|
|
33
|
+
- GitHub admin packs (Admin overlay only)
|
|
34
|
+
- Someone else's Tailnet or thin-client `desk.json`
|
|
35
|
+
- Generic unrestricted shell / desktop CUA on the signer box
|
|
36
|
+
- House executor wallets
|
|
37
|
+
|
|
38
|
+
## Rule
|
|
39
|
+
|
|
40
|
+
If a feature makes the **crypto desk** better and stays fail-closed, take it.
|
|
41
|
+
If it only exists to operate DEMI's machines, leave it on Admin Hermes.
|