@oneie/claude 0.1.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.
- package/.claude-plugin/plugin.json +16 -0
- package/.mcp.json +12 -0
- package/README.md +204 -0
- package/agents/w1-recon.md +102 -0
- package/agents/w2-decide.md +164 -0
- package/agents/w3-edit.md +91 -0
- package/agents/w4-verify.md +416 -0
- package/commands/browser.md +55 -0
- package/commands/cc-connect.md +67 -0
- package/commands/claw.md +135 -0
- package/commands/close.md +143 -0
- package/commands/create.md +78 -0
- package/commands/deploy.md +415 -0
- package/commands/do-autonomous.md +80 -0
- package/commands/do-improve.md +51 -0
- package/commands/do-show.md +89 -0
- package/commands/do.md +226 -0
- package/commands/improve.md +99 -0
- package/commands/kill.md +45 -0
- package/commands/release.md +144 -0
- package/commands/see.md +161 -0
- package/commands/setup.md +75 -0
- package/commands/sync.md +185 -0
- package/hooks/hooks.json +90 -0
- package/hooks/lib/signal.sh +28 -0
- package/hooks/scripts/design-check.sh +83 -0
- package/hooks/scripts/post-edit-check.sh +32 -0
- package/hooks/scripts/session-end-verify.sh +51 -0
- package/hooks/scripts/session-start.sh +88 -0
- package/hooks/scripts/stop-reflect.sh +95 -0
- package/hooks/scripts/sync-todo-docs.sh +46 -0
- package/hooks/scripts/task-complete-verify.sh +52 -0
- package/hooks/scripts/tool-signal.sh +48 -0
- package/package.json +33 -0
- package/rules/api.md +50 -0
- package/rules/astro.md +206 -0
- package/rules/design.md +221 -0
- package/rules/documentation.md +218 -0
- package/rules/engine.md +297 -0
- package/rules/react.md +137 -0
- package/rules/ui.md +82 -0
- package/scripts/cc-connect.sh +345 -0
- package/scripts/do-analyze.sh +42 -0
- package/scripts/do-folder.sh +63 -0
- package/scripts/do-prove.sh +51 -0
- package/scripts/do-reconcile.sh +28 -0
- package/scripts/do-smoke.sh +60 -0
- package/scripts/do-survey.sh +30 -0
- package/scripts/do-tier.sh +43 -0
- package/skills/build/SKILL.md +52 -0
- package/skills/cloudflare/SKILL.md +503 -0
- package/skills/dev/SKILL.md +58 -0
- package/skills/do/SKILL.md +24 -0
- package/skills/oneie/SKILL.md +51 -0
- package/skills/perf/SKILL.md +45 -0
- package/skills/signal/SKILL.md +108 -0
- package/skills/sui/SKILL.md +441 -0
- package/skills/tutorial/SKILL.md +96 -0
- package/skills/typecheck/SKILL.md +66 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: perf
|
|
3
|
+
description: Iterative perf tuning — instrument, measure quantiles, attack the biggest bin, re-measure. Use when latency or throughput targets are missed and the bottleneck is unknown.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /perf — Performance Optimization Loop
|
|
7
|
+
|
|
8
|
+
Enforces Rule 3 on perf work: quantiles, not averages; bottleneck rank, not slowest call.
|
|
9
|
+
|
|
10
|
+
## The loop (one iteration)
|
|
11
|
+
|
|
12
|
+
1. **Instrument** — bracket every async boundary; extend `packages/sdk/src/telemetry.ts` before inventing a new surface. No target → no work.
|
|
13
|
+
2. **Run** — production-shaped load (real signal sizes, real receiver distribution). Capture every trace row.
|
|
14
|
+
3. **Analyse** — script reports per-op `count / p50 / p95 / p99 / total = count × p50`. Sort by total; the top 1–2 lines are the next cycle. Optimize the *biggest* op, not the *slowest*.
|
|
15
|
+
4. **Propose → measure** — one change per iteration. Re-run 2–3. Compare quantiles, not averages.
|
|
16
|
+
|
|
17
|
+
**Symptom → likely cause:**
|
|
18
|
+
|
|
19
|
+
| Symptom | Cause |
|
|
20
|
+
|---|---|
|
|
21
|
+
| High p99, low p50 | tail latency — locks, GC, retries |
|
|
22
|
+
| High flat distribution | algorithmic — wrong data structure |
|
|
23
|
+
| Many short calls dominate | call overhead — fan-out, async hop, JSON parse |
|
|
24
|
+
| Memory-bound | redundant copies, missing buffer reuse |
|
|
25
|
+
| Network-bound | round-trips — coalesce, cache |
|
|
26
|
+
|
|
27
|
+
**Stop:** target hit, or 3 iterations with <10% delta on the top bin.
|
|
28
|
+
|
|
29
|
+
## Receipt (Rule 3)
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{ "receiver": "perf:session:ok", "data": { "weight": 1, "content": {
|
|
33
|
+
"path": "<surface>", "target_us": N,
|
|
34
|
+
"before": { "p50_us": N, "p95_us": N, "p99_us": N },
|
|
35
|
+
"after": { "p50_us": N, "p95_us": N, "p99_us": N },
|
|
36
|
+
"delta_pct": { "p50": -N, "p95": -N, "p99": -N },
|
|
37
|
+
"wins": [ { "iter": N, "change": "...", "p50_delta_pct": -N } ]
|
|
38
|
+
}}}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Negative `delta_pct` = faster. Pheromone marks the path; substrate learns which optimization shapes pay off where.
|
|
42
|
+
|
|
43
|
+
## Targets
|
|
44
|
+
|
|
45
|
+
`50ms` agent wallet · `<10ms` gateway · `3s` buy · `30s` list. From root `CLAUDE.md`.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Signal
|
|
3
|
+
description: Signal system — receiver naming, weight conventions, four outcomes (result/timeout/dissolved/failure), emitters (bash/TypeScript/React), and observability endpoints. Use when working with signals, mark/warn/fade, the /api/signal route, or hook-emitted pheromones.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Signal — The Universal Primitive
|
|
8
|
+
|
|
9
|
+
**Receiver names the edge. Weight deposits pheromone. Tags classify. Everything else is convention.**
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
type Signal = { receiver: string; data?: unknown }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Two fields. The type is frozen — never narrow it. Everything below is a pattern for filling those two fields, not a contract.
|
|
16
|
+
|
|
17
|
+
## Data convention (router reads these, not the type)
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
data = { tags?: string[], weight?: number, content?: unknown }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- **`weight`** — `+1` marks, `-1` warns, omitted = `+1`, `0` = neutral. Gradations (`-0.5` for dissolved, chain-depth multipliers for marks) are discretion, not rules.
|
|
24
|
+
- **`tags`** — classification. Queries filter on these. Not required.
|
|
25
|
+
- **`content`** — opaque payload. Router never reads it for routing.
|
|
26
|
+
|
|
27
|
+
## The four outcomes (Rule 1)
|
|
28
|
+
|
|
29
|
+
Every loop closes in exactly one of these. Pick the weight; the substrate does the rest.
|
|
30
|
+
|
|
31
|
+
| Outcome | Weight | When |
|
|
32
|
+
|-------------|----------|----------------------------------------|
|
|
33
|
+
| result | `+1` | success |
|
|
34
|
+
| timeout | `0` | slow, not the agent's fault |
|
|
35
|
+
| dissolved | `-0.5` | missing unit/capability, server down |
|
|
36
|
+
| failure | `-1` | agent produced nothing |
|
|
37
|
+
|
|
38
|
+
If in doubt: `+1` on success, `-1` on failure. The gradations are discretion.
|
|
39
|
+
|
|
40
|
+
## Receiver naming
|
|
41
|
+
|
|
42
|
+
`receiver` matches `/^[a-zA-Z0-9:_-]+$/`, max 255 chars. The first colon-delimited segment is the **surface** — prefixes are **query-partitioning hints**, not a type contract. Any string works; these are the conventions in use:
|
|
43
|
+
|
|
44
|
+
| Prefix | Example | Emitter |
|
|
45
|
+
|--------------|-------------------------------|---------------------------------------------------------|
|
|
46
|
+
| `ui:*` | `ui:chat:copy` | React `onClick` via `emitClick()` |
|
|
47
|
+
| `tool:*` | `tool:Edit:ok`, `tool:Bash:fail` | `.claude/hooks/tool-signal.sh` on PostToolUse |
|
|
48
|
+
| `hook:*` | `hook:post-edit:warn` | other hook scripts via `emit_signal` (`hooks/lib/signal.sh`) |
|
|
49
|
+
| `cli:*` | `cli:signal:send` | `oneie` CLI verbs |
|
|
50
|
+
| `bridge:*` | `bridge:mirrorMark` | `src/engine/bridge.ts` |
|
|
51
|
+
| `l4:*` | `l4:payment:settle` | L4 economic loop |
|
|
52
|
+
| `w4:*` | `w4:verify:ok` | W4 rubric gate outcomes |
|
|
53
|
+
| `do:*` | `do:close` | `/do` wave/cycle boundaries |
|
|
54
|
+
| `loop:*` | `loop:feedback` | `/close` per-task rubric feedback |
|
|
55
|
+
| `unit:skill` | `scout:observe` | substrate tasks (plain unit + skill name) |
|
|
56
|
+
|
|
57
|
+
Format: `<surface>:<subject>:<action-or-outcome>`. New surfaces are fine — pick a prefix, stick with it.
|
|
58
|
+
|
|
59
|
+
## Emitters
|
|
60
|
+
|
|
61
|
+
### Bash hook
|
|
62
|
+
```bash
|
|
63
|
+
source "$CLAUDE_PROJECT_DIR/.claude/hooks/lib/signal.sh"
|
|
64
|
+
emit_signal "hook:post-edit:ok" 1 "file=$FILE"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Fire-and-forget, 2s max. Silent on dev-server-down.
|
|
68
|
+
|
|
69
|
+
### TypeScript (API route)
|
|
70
|
+
```ts
|
|
71
|
+
import { signalSend } from '@/lib/signalSender'
|
|
72
|
+
await signalSend({ receiver: 'w4:verify:ok', data: { tags: ['verify'], weight: 1, content: { passed: 320 } } })
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### React click
|
|
76
|
+
```tsx
|
|
77
|
+
import { emitClick } from '@/lib/ui-signal'
|
|
78
|
+
<Button onClick={() => emitClick('ui:chat:copy')}>Copy</Button>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Substrate task
|
|
82
|
+
```ts
|
|
83
|
+
unit('scout').on('observe', async (data, emit) => {
|
|
84
|
+
emit({ receiver: 'analyst:classify', data: { content: data } })
|
|
85
|
+
return data
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## What `POST /api/signal` validates
|
|
90
|
+
|
|
91
|
+
Three deterministic pre-checks (no LLM): receiver format regex + length, toxicity (`isToxic(edge)` with cold-start protection), ADL gates (lifecycle → 410, network allowedHosts → 403). All cached 5 min. Full list: `src/pages/api/signal.ts`.
|
|
92
|
+
|
|
93
|
+
## Observability
|
|
94
|
+
|
|
95
|
+
- `/api/export/paths` — all edges
|
|
96
|
+
- `/api/export/highways` — top by strength
|
|
97
|
+
- `/api/export/toxic` — blocked by resistance
|
|
98
|
+
- `/api/signals?since=T` — raw history
|
|
99
|
+
|
|
100
|
+
## See Also
|
|
101
|
+
|
|
102
|
+
- `docs/dictionary.md` § Three Slots of Data — canonical convention
|
|
103
|
+
- `docs/routing.md` § Four Outcomes — weight semantics
|
|
104
|
+
- `src/engine/CLAUDE.md` § Rule 1 — code-level contract
|
|
105
|
+
- `.claude/hooks/lib/signal.sh` — bash helper
|
|
106
|
+
- `src/lib/signalSender.ts` — TS helper
|
|
107
|
+
- `src/lib/ui-signal.ts` — `emitClick`
|
|
108
|
+
- `src/pages/api/signal.ts` — the one receiver
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# Sui Move Skill
|
|
2
|
+
|
|
3
|
+
Build secure, production-ready Move contracts for the ONE substrate and agent ecosystem.
|
|
4
|
+
|
|
5
|
+
**Status:** Phase 1 (testnet) ✅ · Phase 2 (identity & wallets) ✅ shipped 2026-04-18 · Phase 3 (escrow) scaffolding shipped, W3-W4 ready per `docs/SUI-todo.md`. Phase 4-6 next.
|
|
6
|
+
|
|
7
|
+
**Package versions (locked):** `@mysten/sui@^2.16.0`, `@mysten/dapp-kit@^1.0.4`. SDK is **v2** — imports are NOT backward-compatible with v1. See "SDK Imports (Sui v2)" below before writing any Sui code.
|
|
8
|
+
|
|
9
|
+
## What This Skill Does
|
|
10
|
+
|
|
11
|
+
- **Generate Move modules** — scaffolding, best practices, gas optimization
|
|
12
|
+
- **Agent wallet integration** — keypair derivation, signing, address generation (Sui + ONE)
|
|
13
|
+
- **Envelope contracts** — payment channels, multi-sig, conditional execution
|
|
14
|
+
- **TypeDB ↔ Sui sync** — contract state ↔ substrate knowledge (paths, units, skills) via `bridge.ts`
|
|
15
|
+
- **Testing & deployment** — Move test suites, devnet/testnet/mainnet
|
|
16
|
+
- **ONE patterns** — pheromone trails as contract state, agent reputation on-chain
|
|
17
|
+
|
|
18
|
+
## Phases (from docs/SUI-todo.md)
|
|
19
|
+
|
|
20
|
+
| Phase | What | Status |
|
|
21
|
+
|-------|------|--------|
|
|
22
|
+
| 1 | Testnet, contract publish, protocol funded | ✅ DONE |
|
|
23
|
+
| 2 | Deterministic keypair derivation, agent identity, `syncAgentWithIdentity()` | ✅ DONE (2026-04-18) |
|
|
24
|
+
| 3 | Escrow (`createEscrow/releaseEscrow/cancelEscrow`), x402 settlement, treasury fee 50 bps | 🟡 Scaffolding shipped in `sui.ts`; W3-W4 wiring next |
|
|
25
|
+
| 4 | On-chain fade, harden highways, frozen Path objects | 📋 Next |
|
|
26
|
+
| 5 | Group economics, treasury, federation | 📋 Next |
|
|
27
|
+
| 6 | Mainnet, audit, SDK, multi-chain | 📋 Next |
|
|
28
|
+
|
|
29
|
+
## When to Use
|
|
30
|
+
|
|
31
|
+
- Writing Move smart contracts for ONE agents or payment flows (Phase 2-6)
|
|
32
|
+
- Generating agent wallets and keypairs from substrate identity (Phase 2)
|
|
33
|
+
- Syncing on-chain state back to TypeDB (via `src/engine/bridge.ts` absorb loop)
|
|
34
|
+
- Building envelope payment channels or multi-agent coordination contracts (Phase 3)
|
|
35
|
+
- Deploying to Sui (devnet, testnet, mainnet)
|
|
36
|
+
- Auditing Move code for security, gas, or ONE patterns
|
|
37
|
+
|
|
38
|
+
## Core Components (What's Built)
|
|
39
|
+
|
|
40
|
+
| File | Lines | What |
|
|
41
|
+
|------|------:|------|
|
|
42
|
+
| `src/move/one/sources/one.move` | 691 | Move contract: Unit, Signal, Path, Escrow, fade, harden |
|
|
43
|
+
| `src/lib/sui.ts` | 652 | Sui client: Six Verbs + escrow + wallet derivation + faucet |
|
|
44
|
+
| `src/engine/bridge.ts` | 479 | Mirror/absorb: Runtime ↔ Sui ↔ TypeDB sync |
|
|
45
|
+
| `src/schema/world.tql` | — | `sui-unit-id`, `sui-path-id`, `wallet` attributes on unit/path |
|
|
46
|
+
| `src/engine/persist.ts` | — | Auto-mirror on mark/warn/actor |
|
|
47
|
+
|
|
48
|
+
**Exported API surface (from `src/lib/sui.ts` — read before reinventing):**
|
|
49
|
+
|
|
50
|
+
| Category | Functions |
|
|
51
|
+
|----------|-----------|
|
|
52
|
+
| Client | `getClient()` — returns cached `SuiJsonRpcClient` |
|
|
53
|
+
| Wallet | `deriveKeypair(uid)`, `addressFor(uid)`, `platformKeypair()`, `signAndExecute()` |
|
|
54
|
+
| Units | `createUnit()`, `registerTask()`, `getOwnedUnits()`, `getObject()`, `resolveUnit(uid)` |
|
|
55
|
+
| Paths (Six Verbs) | `mark()`, `warn()`, `send()`, `consume()`, `pay()`, `createPath()`, `harden()` |
|
|
56
|
+
| Escrow | `createEscrow()`, `releaseEscrow()`, `cancelEscrow()`, `viewEscrow()` + `*Tx()` builders |
|
|
57
|
+
| Ops | `ensureFunded()` (faucet) |
|
|
58
|
+
|
|
59
|
+
**Testnet Package:** `0xa5e6bddae833220f58546ea4d2932a2673208af14a52bb25c4a603492078a09e`
|
|
60
|
+
**Protocol Object:** `SUI_PROTOCOL_ID` (treasury, fee_bps = 50 → 0.5%)
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## SDK Imports (Sui v2) — LOCKED
|
|
65
|
+
|
|
66
|
+
The SDK is v2 since commit `74c15a0`. The JSON-RPC client moved out of `/client` and was renamed. **The v1 imports silently survive editor autocomplete from stale docs — they do not exist at runtime.** Vite throws `does not provide an export named 'SuiClient'` and cascades up through `src/pages/api/signal.ts`, taking down every page that routes a UI click.
|
|
67
|
+
|
|
68
|
+
### Rename map (v1 → v2)
|
|
69
|
+
|
|
70
|
+
| v1 (removed) | v2 (use this) |
|
|
71
|
+
|-------------------------------------------|-------------------------------------------------------|
|
|
72
|
+
| `SuiClient` from `@mysten/sui/client` | `SuiJsonRpcClient` from `@mysten/sui/jsonRpc` |
|
|
73
|
+
| `getFullnodeUrl` from `@mysten/sui/client` | `getJsonRpcFullnodeUrl` from `@mysten/sui/jsonRpc` |
|
|
74
|
+
| `SuiClientOptions` | `SuiJsonRpcClientOptions` |
|
|
75
|
+
| `SuiHTTPTransport` | `JsonRpcHTTPTransport` |
|
|
76
|
+
| `isSuiClient` | `isSuiJsonRpcClient` |
|
|
77
|
+
| `SuiTransactionBlockResponse` (either path) | Same name, now also exported from `/jsonRpc` |
|
|
78
|
+
| `SuiClientProvider` (dapp-kit) | **Same name — unchanged.** dapp-kit 1.0.4+ already uses v2 types internally |
|
|
79
|
+
|
|
80
|
+
Migration guide: `node_modules/@mysten/sui/docs/migrations/sui-2.0/sui.md`.
|
|
81
|
+
|
|
82
|
+
### Constructor now requires `network`
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// WRONG (v1 — crashes with type error in v2)
|
|
86
|
+
const client = new SuiClient({ url: getFullnodeUrl('testnet') })
|
|
87
|
+
|
|
88
|
+
// RIGHT (v2)
|
|
89
|
+
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc'
|
|
90
|
+
const client = new SuiJsonRpcClient({
|
|
91
|
+
url: getJsonRpcFullnodeUrl('testnet'),
|
|
92
|
+
network: 'testnet', // REQUIRED — used by MVR resolver and future multi-network tooling
|
|
93
|
+
})
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Same applies to every `NetworkConfig` entry passed to `createNetworkConfig({...})` in dapp-kit — each entry must include `network: 'testnet'` (or 'mainnet'/'devnet'/'localnet') alongside `url`.
|
|
97
|
+
|
|
98
|
+
### Use `@/lib/sui`, not the raw SDK
|
|
99
|
+
|
|
100
|
+
If you find yourself importing directly from `@mysten/sui/jsonRpc` outside `src/lib/sui.ts` or `src/components/pay/PayPage.tsx`, you are probably reinventing something. `getClient()` in `src/lib/sui.ts` returns the singleton; every Six-Verb function (`mark`, `warn`, `send`, `pay`, etc.) already exists. Two legitimate exceptions:
|
|
101
|
+
- `PayPage.tsx` — needs `getJsonRpcFullnodeUrl` for the dapp-kit `createNetworkConfig` call
|
|
102
|
+
- New contract tooling that reads types like `SuiTransactionBlockResponse`
|
|
103
|
+
|
|
104
|
+
### Defensive pattern: lazy-import `@/lib/sui` from hot routes
|
|
105
|
+
|
|
106
|
+
`src/pages/api/signal.ts` (applied 2026-04-18) imports `@/lib/sui` **dynamically inside the Sui-mirror try block** rather than at module scope:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
// Top of signal.ts: no @/lib/sui import
|
|
110
|
+
|
|
111
|
+
// Inside the POST handler, after TypeDB write:
|
|
112
|
+
try {
|
|
113
|
+
const { resolveUnit, send: suiSend } = await import('@/lib/sui')
|
|
114
|
+
// ...Sui mirror...
|
|
115
|
+
} catch {
|
|
116
|
+
// Sui not configured, SDK broken, or tx failed — TypeDB signal still recorded
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Why:** `/api/signal` is imported transitively by every page that routes a UI click. A top-level `import { ... } from '@/lib/sui'` means any Sui SDK type break bricks the entire API route (and thus every dependent page). Lazy import contains the blast radius to just the mirror step. Apply this same pattern to any other hot route that touches Sui only as fire-and-forget.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Works With /typedb — The Same Ontology, Two Deterministic Fires
|
|
125
|
+
|
|
126
|
+
`src/schema/sui.tql:1` already put it best: **"The same ontology. Two deterministic fires."** Move is the permanent, economic fire (path revenue, escrow, treasury — expensive to write, cheap to trust). TypeDB is the learning, classification fire (hypotheses, frontiers, tags — cheap to write, rich to query). The runtime is the fast nervous system between them. Both skills speak the same vocabulary by design — `strength`, `resistance`, `revenue`, `path`, `unit` — so the bridge is a **1:1 rename, not a translation**.
|
|
127
|
+
|
|
128
|
+
### Canonical crosswalk
|
|
129
|
+
|
|
130
|
+
`src/schema/sui.tql` (336 lines) is the Rosetta Stone — every Move struct has a matching TQL entity, every Move function has a matching TQL `fun`. Read it when names or shapes drift. The runtime schema is `src/schema/world.tql`; `sui.tql` is the parallel declaration that proves the two layers agree.
|
|
131
|
+
|
|
132
|
+
### Attribute mapping (Move struct ⇌ TypeDB attribute)
|
|
133
|
+
|
|
134
|
+
| Move field (`one.move`) | TQL attribute (`world.tql`) | Move type | TQL type | Direction |
|
|
135
|
+
|---------------------------------|--------------------------------|-------------|----------|-------------------------------|
|
|
136
|
+
| `Unit.id` (address) | `unit.sui-unit-id` | address | string | Sui → TQL on `mirrorActor()` |
|
|
137
|
+
| *derived by* `addressFor(uid)` | `unit.wallet` | address | string | Runtime → TQL on agent sync |
|
|
138
|
+
| `Unit.name` | `unit.name` | String | string | bidirectional |
|
|
139
|
+
| `Unit.balance` | `unit.balance` | u64 | double | Sui → TQL via `absorb()` |
|
|
140
|
+
| **`Path.strength`** | **`path.strength`** | u64 | double | bidirectional — load-bearing |
|
|
141
|
+
| **`Path.resistance`** | **`path.resistance`** | u64 | double | bidirectional — load-bearing |
|
|
142
|
+
| `Path.revenue` | `path.revenue` | u64 | double | Sui → TQL via `absorb()` |
|
|
143
|
+
| `Path.id` (address) | `path.sui-path-id` | address | string | Sui → TQL on mirror |
|
|
144
|
+
| `Highway.id` (address) | `path.sui-highway-id` | address | string | Sui → TQL on `mirrorHarden()` |
|
|
145
|
+
| `Signal.payload` (vector<u8>) | `signal.data` | bytes | string | one-way, usually TQL-only |
|
|
146
|
+
|
|
147
|
+
**Name drift to know about:** Move still has `struct Colony` (one.move:71). TypeDB moved to `entity group` per `docs/dictionary.md`, but the Move contract hasn't been migrated yet because that requires a package upgrade. When bridging, read Move `Colony` → TQL `group`.
|
|
148
|
+
|
|
149
|
+
**Load-bearing invariant:** `strength` and `resistance` share the same name in both layers. If you rename one, rename both — `bridge.ts` is a pass-through, there's no translation logic. Type-width (`u64` ↔ `double`) is handled by JSON serialization at the bridge; don't write logic that depends on sub-integer precision.
|
|
150
|
+
|
|
151
|
+
### Bridge contract (`src/engine/bridge.ts`, 479 lines)
|
|
152
|
+
|
|
153
|
+
| Function | Fires when | Maps |
|
|
154
|
+
|-----------------------------------|-----------------------------|------------------------------------------------------------------------|
|
|
155
|
+
| `mirrorMark(from, to, amount?)` | every `persist.mark()` | Runtime strength++ → Sui `mark_path()` |
|
|
156
|
+
| `mirrorWarn(from, to, amount?)` | every `persist.warn()` | Runtime resistance++ → Sui `warn_path()` |
|
|
157
|
+
| `mirrorPay(from, to, amount)` | L4 payment signal | Runtime payment → Sui `pay()` → `Path.revenue +=` |
|
|
158
|
+
| `mirrorHarden(from, to)` | L6 highway promotion | TQL harden → Sui `harden_path()` → Highway object created |
|
|
159
|
+
| `mirrorActor(uid, name)` | `/api/agents/register` | `addressFor(uid)` + `createUnit()` → writes `wallet` + `sui-unit-id` back |
|
|
160
|
+
| `resolve(uid)` | before any outbound Sui call | TQL lookup → `{ wallet, unitId }` — no on-chain twin? dissolve |
|
|
161
|
+
| `resolvePath(from, to)` | on-chain path ops | TQL `sui-path-id` lookup — memoized via edge cache |
|
|
162
|
+
| `absorb(cursor?)` | `/api/absorb` cron (1 min) | Sui events → TQL writes: UnitCreated, Marked, Warned, Paid, Hardened |
|
|
163
|
+
| `settleEscrow(...)` *(Phase 3)* | `releaseEscrow()` succeeds | on-chain settlement → TQL `path.revenue` + `path.strength` mark |
|
|
164
|
+
|
|
165
|
+
**Guarantee:** `mirror*` functions are fire-and-forget. They never block the TypeDB write or the runtime signal loop. If Sui is down, TypeDB still learns; pheromone re-converges when `absorb()` catches up.
|
|
166
|
+
|
|
167
|
+
### When to load /typedb alongside this skill
|
|
168
|
+
|
|
169
|
+
- Writing or reading any attribute prefixed with `sui-*` in TQL
|
|
170
|
+
- Querying `unit.wallet` — the value comes from `addressFor(uid)` in `src/lib/sui.ts`, not stored by default
|
|
171
|
+
- Editing `src/engine/bridge.ts` — every function there touches both worlds
|
|
172
|
+
- Adding a TQL entity that has a Move twin — name alignment is a maintenance contract
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Canonical Move Reference (move-book.com)
|
|
177
|
+
|
|
178
|
+
The Move Book (https://move-book.com — source `github.com/MystenLabs/move-book`) is the canonical learning source for Move on Sui. **Read it before adding to `one.move`.** Our existing structs and verbs already implement named patterns from the book; future work should keep names aligned so the contract reads idiomatically.
|
|
179
|
+
|
|
180
|
+
### Pattern crosswalk (`one.move` → Move Book chapter)
|
|
181
|
+
|
|
182
|
+
| What `one.move` does | Move Book chapter |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `Treasury` object gates protocol fee + balance mutation | `programmability/capability` — the object IS the permission token |
|
|
185
|
+
| `Marked`, `Warned`, `Paid`, `Hardened`, `UnitCreated` events | `programmability/events` — past tense; no sender/timestamp fields (framework adds them) |
|
|
186
|
+
| `Escrow` must settle in one tx (release or cancel — never dropped) | `programmability/hot-potato-pattern` — types without `drop` force settlement |
|
|
187
|
+
| `init(otw, ctx)` creates the singleton `Protocol` once at publish | `programmability/module-initializer` + `programmability/one-time-witness` |
|
|
188
|
+
| `Unit`, `Path`, `Highway`, `Escrow` are storable objects | `storage/key-ability`, `storage/store-ability`, `storage/uid-and-id` |
|
|
189
|
+
| `Unit` owned (fast path) · `Path` / `Protocol` shared (consensus) | `object/ownership`, `object/fast-path-and-consensus` |
|
|
190
|
+
| `Path.revenue` accumulated on `pay()` | `programmability/transaction-context` — split/merge `Coin<SUI>` via PTBs |
|
|
191
|
+
| Future: per-Path analytics without breaking layout | `programmability/dynamic-fields` — anchor pattern |
|
|
192
|
+
|
|
193
|
+
When `one.move` grows, name the pattern from the book in the function doc comment so reviewers can audit against a known shape rather than reading the whole module.
|
|
194
|
+
|
|
195
|
+
### Move 2024 syntax — required for new code
|
|
196
|
+
|
|
197
|
+
Our package is Move 2024 edition. The book's `guides/code-quality-checklist` lists the canonical style. Load-bearing items for `one.move`:
|
|
198
|
+
|
|
199
|
+
- `public struct`, never bare `struct` (2024 makes structs internal by default)
|
|
200
|
+
- Error constants: `EToxicPath` — PascalCase with leading `E`
|
|
201
|
+
- Regular constants: `MAX_FEE_BPS` — ALL_CAPS
|
|
202
|
+
- `public fun` or `entry fun`, never `public entry fun`
|
|
203
|
+
- Struct methods over module functions: `path.mark()`, not `path::mark(path)`
|
|
204
|
+
- Vector literals: `vector[a, b, c]`, not `vector::empty<T>()` + push loop
|
|
205
|
+
- Macros over while loops: `n.do!(|i| ...)`, `vec.do_ref!(|x| ...)`, `vec.fold!(init, |acc, x| ...)`
|
|
206
|
+
- Option: `opt.do!(|x| ...)` / `opt.destroy_or!(default)`, not branchy `is_some`/`borrow`
|
|
207
|
+
- Events named past tense (we already comply: `Marked`, `Warned`, `Hardened`)
|
|
208
|
+
- Capability structs end in `Cap` — `Treasury` is borderline because it also holds `Balance<SUI>`; document the dual role in the struct doc comment rather than rename
|
|
209
|
+
|
|
210
|
+
### Upgradeability — what `one.move` cannot change
|
|
211
|
+
|
|
212
|
+
`guides/upgradeability-practices` rules apply on every package upgrade:
|
|
213
|
+
|
|
214
|
+
- Modules cannot be removed
|
|
215
|
+
- **Public struct layouts are frozen** — every field in `Unit`, `Path`, `Escrow`, `Protocol`, `Highway`, `Signal` is permanent once published. Adding a field requires either a new struct or a dynamic field.
|
|
216
|
+
- **Public function signatures are frozen** — add new functions; never change `mark_path(path: &mut Path, ...)` parameters
|
|
217
|
+
- Private / `public(package)` functions and non-public dependencies can change freely
|
|
218
|
+
|
|
219
|
+
**Practical rule:** before adding a field to any public struct, design it as a dynamic field on the existing UID (`df::add(&mut path.id, key, value)`). New analytics like `Path.hits_per_epoch` should attach this way. The boundary in `src/move/one/sources/one.move` — the public structs — IS the upgrade contract.
|
|
220
|
+
|
|
221
|
+
### gRPC as alternative to JSON-RPC for the absorb loop
|
|
222
|
+
|
|
223
|
+
`github.com/MystenLabs/sui-apis` ships the protobuf gRPC interface for Sui (under `proto/`). Our current `absorb()` in `src/engine/bridge.ts` polls JSON-RPC `queryEvents` every minute. If event volume outgrows that budget — or we need lower-latency `Marked`/`Hardened` propagation — port the absorb loop to gRPC event streaming using the proto definitions. JSON-RPC is fine until then; sui-apis is the right reference when designing high-throughput indexing.
|
|
224
|
+
|
|
225
|
+
### Working examples to mine
|
|
226
|
+
|
|
227
|
+
| Repo | Useful for |
|
|
228
|
+
|---|---|
|
|
229
|
+
| `github.com/MystenLabs/move-book` (`packages/`) | Every chapter ships runnable code; cite a chapter file when arguing for a refactor |
|
|
230
|
+
| `github.com/MystenLabs/solitaire` | Owned-object game + native randomness API + dapp-kit integration; reference shape when designing a per-agent owned object (e.g. inbox, score sheet) |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Capabilities
|
|
235
|
+
|
|
236
|
+
### 1. Mirror to Sui (mark/warn auto-propagate)
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// From src/engine/bridge.ts
|
|
240
|
+
mirrorMark(from, to, strength) // Runtime → Sui: fire-and-forget
|
|
241
|
+
mirrorWarn(from, to, strength) // Runtime → Sui: fire-and-forget
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
- Called automatically by `persist.ts` on every `mark()` or `warn()`
|
|
245
|
+
- Creates Signal object on-chain, fires Marked event
|
|
246
|
+
- Zero latency (async, doesn't block signal loop)
|
|
247
|
+
- Graceful fallback (Sui down? Signal completes anyway)
|
|
248
|
+
|
|
249
|
+
### 2. Absorb from Sui (events → TypeDB)
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
// /api/absorb { cursor? }
|
|
253
|
+
absorb(cursor?) // Sui → TypeDB: poll events, write state
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
- Polls on-chain events (Marked, UnitCreated, SignalSent)
|
|
257
|
+
- Writes back to TypeDB (strength updates, new units)
|
|
258
|
+
- Cursor-based pagination (resume from last event)
|
|
259
|
+
- Runs every 1 min via `/grow` tick
|
|
260
|
+
|
|
261
|
+
**Events queryable:**
|
|
262
|
+
```typescript
|
|
263
|
+
queryEvents() // Returns all events since genesis
|
|
264
|
+
getPath(from, to) // Resolve TypeDB unit ↔ Sui path
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 3. Agent Wallet Derivation (Phase 2 — shipped)
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
// From src/lib/sui.ts (shipped 2026-04-18)
|
|
271
|
+
addressFor(uid) // UID → stable Sui address (Promise<string>)
|
|
272
|
+
deriveKeypair(uid) // UID → Ed25519 keypair (Promise<Ed25519Keypair>)
|
|
273
|
+
// Seed read from SUI_SEED env, never passed as arg
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
- Deterministic: same `SUI_SEED + uid` → same SHA-256 secret → same keypair, always
|
|
277
|
+
- No private key storage: derives on-the-fly per call
|
|
278
|
+
- `syncAgentWithIdentity()` in `src/engine/agent-md.ts` wires wallet into TypeDB unit on markdown sync
|
|
279
|
+
- Multi-chain-ready (same pattern could emit Ethereum/Solana addresses)
|
|
280
|
+
|
|
281
|
+
### 4. Payment Flow (Phase 3: escrow)
|
|
282
|
+
|
|
283
|
+
```move
|
|
284
|
+
// Move contract functions (one.move)
|
|
285
|
+
create_escrow(unit, receiver, amount) // Lock tokens, await settlement
|
|
286
|
+
release_escrow(escrow, result?) // Success: pay + mark + fee (atomic)
|
|
287
|
+
cancel_escrow(escrow) // Timeout: return tokens, warn path
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
- Atomic: fee + mark + transfer in single transaction
|
|
291
|
+
- Revenue: protocol collects `fee_bps` (50 = 0.5%)
|
|
292
|
+
- Idempotent: releasing same escrow twice fails safely
|
|
293
|
+
- Enables x402 workflow (402 → create escrow → execute → release)
|
|
294
|
+
|
|
295
|
+
### 5. Path Strength on-Chain (permanent learning)
|
|
296
|
+
|
|
297
|
+
```move
|
|
298
|
+
// Every path is a Sui object with:
|
|
299
|
+
Path {
|
|
300
|
+
from: address,
|
|
301
|
+
to: address,
|
|
302
|
+
strength: u64, // Marked increments
|
|
303
|
+
resistance: u64, // Warned increments
|
|
304
|
+
hits: u64, // Total signals
|
|
305
|
+
type: String, // "interaction", "payment", etc.
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- Strength = gas rewards (proportional to agent value)
|
|
310
|
+
- Resistance = slashing (accumulates from failures)
|
|
311
|
+
- Toxic when: `resistance >= 10 && resistance > 2x strength && (r+s) > 5`
|
|
312
|
+
- Read by `/api/highways` → mirrors to TypeDB → guides future signals
|
|
313
|
+
|
|
314
|
+
## Phase 2 — Shipped (2026-04-18)
|
|
315
|
+
|
|
316
|
+
Already exported from `src/lib/sui.ts`. **Do not reimplement.**
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { deriveKeypair, addressFor, platformKeypair } from '@/lib/sui'
|
|
320
|
+
|
|
321
|
+
// Deterministic Ed25519 keypair from SUI_SEED + uid (SHA-256 → 32-byte secret)
|
|
322
|
+
const kp = await deriveKeypair('marketing:creative')
|
|
323
|
+
const addr = await addressFor('marketing:creative') // stable forever
|
|
324
|
+
|
|
325
|
+
// Integrated into agent sync: syncAgentWithIdentity() in src/engine/agent-md.ts
|
|
326
|
+
// writes `wallet` attribute to TypeDB unit on markdown → TypeDB sync
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**Verified:** 14 tests pass — determinism + uniqueness + idempotency. Unblocks Phase 3 (escrow on-chain) and marketplace on-chain discovery. Browser-side wallet connect uses `@mysten/dapp-kit` `ConnectButton` + `WalletProvider` (see `src/components/pay/PayPage.tsx`).
|
|
330
|
+
|
|
331
|
+
## Phase 3 — Escrow (W3-W4 ready)
|
|
332
|
+
|
|
333
|
+
Transaction builders and high-level wrappers already in `src/lib/sui.ts`:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import { createEscrow, releaseEscrow, cancelEscrow, viewEscrow } from '@/lib/sui'
|
|
337
|
+
|
|
338
|
+
// Poster locks tokens
|
|
339
|
+
const { escrowId } = await createEscrow(posterUid, workerUnitId, amountMist, pathId)
|
|
340
|
+
|
|
341
|
+
// Worker settles (atomic: pay + mark + protocol fee)
|
|
342
|
+
await releaseEscrow(posterUid, escrowId, workerUnitId, pathId)
|
|
343
|
+
|
|
344
|
+
// Timeout path
|
|
345
|
+
await cancelEscrow(posterUid, escrowId, posterUnitId, pathId)
|
|
346
|
+
|
|
347
|
+
// Read current state
|
|
348
|
+
const view: EscrowView | null = await viewEscrow(escrowId)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Protocol fee: **50 bps (0.5%)** collected to treasury on every `releaseEscrow`. W3 wires the UI side (claim button → `ui:chat:claim` signal); W4 adds deterministic sandwich gates (isToxic → skip escrow creation).
|
|
352
|
+
|
|
353
|
+
## Real Examples (from Testnet)
|
|
354
|
+
|
|
355
|
+
### Agent Created on-Chain
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
// Scout was created with this call:
|
|
359
|
+
const unitId = await createUnit("scout", "agent")
|
|
360
|
+
// Sui object ID: 0x6fd45656222db69f81dbf61c70873fd466ebd8b157bf6694f81314e3e0c13af8
|
|
361
|
+
// TypeDB marked: sui-unit-id = "0x6fd4..."
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Signal Sent & Path Created
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
// Signal from scout → analyst using the exported `send` wrapper
|
|
368
|
+
import { send } from '@/lib/sui'
|
|
369
|
+
const { digest } = await send(
|
|
370
|
+
'scout', // sender uid (keypair derived)
|
|
371
|
+
scoutUnit.objectId,
|
|
372
|
+
analystUnit.objectId,
|
|
373
|
+
analystUnit.wallet,
|
|
374
|
+
'default', // task type
|
|
375
|
+
new TextEncoder().encode('hello from scout'),
|
|
376
|
+
0, // amount in MIST (0 = no payment attached)
|
|
377
|
+
)
|
|
378
|
+
// Sui Signal object created; Path (scout → analyst) strength += 1
|
|
379
|
+
// Absorb loop reads the event and writes strength delta back to TypeDB
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
*(The Phase 3 escrow example is in the "Phase 3 — Escrow (W3-W4 ready)" section above with the accurate 4-arg signature — don't duplicate it here.)*
|
|
383
|
+
|
|
384
|
+
## Safety (Deterministic Sandwich)
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
PRE: isToxic(edge)? → skip contract call (no Sui interaction)
|
|
388
|
+
PRE: capability exists? → TypeDB lookup → skip if missing
|
|
389
|
+
LLM: (if applicable) generates response
|
|
390
|
+
POST: success? → mark(). timeout? → neutral. dissolved? → warn(0.5).
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
- **No private keys in code** — use `$SUI_SEED` environment variable (derives on-the-fly)
|
|
394
|
+
- **Pre-flight checks** — isToxic(), capability exists? before contract call (prevents wasted gas)
|
|
395
|
+
- **Gas limits** — escrow functions must settle within gas budget
|
|
396
|
+
- **Auditability** — all math is deterministic; randomness only from LLM prompts
|
|
397
|
+
|
|
398
|
+
## Env & Setup
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# .env (required for Phase 2+)
|
|
402
|
+
SUI_NETWORK=testnet
|
|
403
|
+
SUI_SEED=<32 bytes base64> # Generates all agent keypairs
|
|
404
|
+
|
|
405
|
+
SUI_PACKAGE_ID=0xa5e6... # Published contract package
|
|
406
|
+
SUI_PROTOCOL_ID=0x... # Protocol object (treasury, fee_bps)
|
|
407
|
+
|
|
408
|
+
# Verify setup
|
|
409
|
+
sui client object $SUI_PROTOCOL_ID
|
|
410
|
+
# Output: Protocol { treasury: 0, fee_bps: 50 }
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## When This Skill Is Invoked
|
|
414
|
+
|
|
415
|
+
The `/sui` skill is a reading guide, not a CLI. When loaded, Claude should:
|
|
416
|
+
|
|
417
|
+
1. **Before writing any Sui code**, re-read "SDK Imports (Sui v2)" above — the v1 patterns in `node_modules/@mysten/sui/docs/migrations/sui-2.0/sui.md` have been removed from the SDK but linger in every older doc, blog post, and Anthropic-era training snapshot. Autocomplete will suggest them. **Do not use them.**
|
|
418
|
+
2. **Before adding a function to `@/lib/sui`**, check the "Exported API surface" table above. The Six Verbs plus escrow are already there; new work should compose them.
|
|
419
|
+
3. **Before importing from `@mysten/sui/jsonRpc` directly**, check whether `getClient()` + an existing wrapper already covers the use case. The only legitimate direct importers are `src/lib/sui.ts` and `src/components/pay/PayPage.tsx`.
|
|
420
|
+
4. **Before adding a top-level Sui import to any API route**, consider the lazy-import defense: if the route handles Sui as fire-and-forget (like `/api/signal`), `await import('@/lib/sui')` inside the relevant try block keeps the route resilient to SDK breakage.
|
|
421
|
+
5. **For contract work**, read `src/move/one/sources/one.move` — all 691 lines define six object types (Unit, Signal, Path, Escrow, Highway, Treasury) and the six on-chain verbs. New Move should fit this surface, not grow a parallel one.
|
|
422
|
+
6. **Before editing `one.move`**, cite the Move Book pattern your change implements (capability / hot-potato / OTW / dynamic-field / events) and check the upgradeability rules above — public struct layouts and function signatures are permanent once published.
|
|
423
|
+
|
|
424
|
+
## Reference
|
|
425
|
+
|
|
426
|
+
- **Live contract:** `src/move/one/sources/one.move`
|
|
427
|
+
- **Client API:** `src/lib/sui.ts` (always use this, never the raw SDK)
|
|
428
|
+
- **Bridge:** `src/engine/bridge.ts` (mirror/absorb/resolve)
|
|
429
|
+
- **Integration point:** `src/engine/persist.ts` (auto-mirror on mark/warn)
|
|
430
|
+
- **Schema:** `src/schema/world.tql` (sui-unit-id, sui-path-id, wallet attributes)
|
|
431
|
+
- **Testnet explorer:** `https://suiscan.xyz/testnet/object/{OBJECT_ID}`
|
|
432
|
+
- **Full roadmap:** `docs/SUI-todo.md` (phases 1-6, all tasks)
|
|
433
|
+
- **v2 migration guide:** `node_modules/@mysten/sui/docs/migrations/sui-2.0/sui.md`
|
|
434
|
+
- **dapp-kit reference:** `node_modules/@mysten/dapp-kit/docs/sui-client-provider.md`
|
|
435
|
+
- **Move language canon:** https://move-book.com — source: `github.com/MystenLabs/move-book`
|
|
436
|
+
- **Sui gRPC interface (alt to JSON-RPC):** `github.com/MystenLabs/sui-apis` — protobufs in `proto/`
|
|
437
|
+
- **Owned-object example:** `github.com/MystenLabs/solitaire` — owned objects, native randomness, dapp-kit + TS SDK integration
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
**ONE + Sui = agent wallets, envelope routing, pheromone as on-chain rewards, and deterministic contract security.**
|