@wowok/skills 1.3.4 → 2.0.1

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.
@@ -1,389 +0,0 @@
1
- ---
2
- name: wowok-tools
3
- description: |
4
- WoWok MCP tool reference — canonical documentation for the single unified
5
- `wowok` tool and its 17 sub-tools. Covers schema-inexpressible constraints,
6
- business rules, interaction patterns, and design decisions not captured by
7
- JSON Schema.
8
-
9
- Core value: prevent common AI failures (wrong tool selection, incorrect
10
- parameter formats, missing structural wrappers, wrong discriminated unions).
11
- when_to_use:
12
- - AI needs to select or invoke any WoWok MCP tool
13
- - AI encounters tool errors and needs debugging
14
- - MCP tool schemas are not auto-available
15
- - User asks "how do I..." for any WoWok operation
16
- always: true
17
- ---
18
-
19
- # WoWok MCP Tool Reference
20
-
21
- Canonical reference for the single unified `wowok` tool and its 17 sub-tools. Covers patterns, constraints, and design decisions that **JSON Schema cannot express**. For detailed business workflows, see the Domain and Business Skills below.
22
-
23
- > **Domain Skills**: [wowok-guard](../wowok-guard/SKILL.md) (validation logic), [wowok-messenger](../wowok-messenger/SKILL.md) (encrypted messaging), [wowok-machine](../wowok-machine/SKILL.md) (workflows), [wowok-safety](../wowok-safety/SKILL.md) (safety & naming)
24
- > **Business Skills**: [wowok-order](../wowok-order/SKILL.md) (customer), [wowok-provider](../wowok-provider/SKILL.md) (merchant), [wowok-arbitrator](../wowok-arbitrator/SKILL.md) (dispute resolution)
25
-
26
- ---
27
-
28
- ## Single-Tool Interface (Schema-Gated Execution)
29
-
30
- MCP `tools/list` returns **only one tool**: `wowok`. All operations go through it.
31
-
32
- **Call pattern**: `wowok({ tool: "<sub-tool-name>", data: {<sub-tool params>} })`
33
-
34
- When any skill (including this one) says "Call `onchain_operations`" or "Use `schema_query`", translate it to:
35
- ```
36
- wowok({ tool: "onchain_operations", data: { operation_type: "service", ... } })
37
- wowok({ tool: "schema_query", data: { action: "get", name: "onchain_operations" } })
38
- ```
39
-
40
- **Schema-gated execution**: If `data` doesn't match the sub-tool's schema, the response includes:
41
- - `result.status = "schema_mismatch"` — validation failed
42
- - `result.errors` — specific field errors
43
- - `result.hint` — instructions to fix and retry
44
- - `schema.input` — the correct JSON schema for the sub-tool
45
- - `schema.tool` — which sub-tool this schema belongs to
46
-
47
- **Schema caching**: Each sub-tool has a different schema. When you receive a schema in a mismatch response, cache it in your context for future calls to the same sub-tool. You should only need to see each sub-tool's schema once per conversation.
48
-
49
- ---
50
-
51
- ## 🔴 Gas and Faucet
52
-
53
- On-chain operations require gas. Transactions will fail if the account has insufficient balance.
54
-
55
- ### For AI Assistant
56
-
57
- When assisting users with WoWok operations:
58
-
59
- - After a user creates a new account, proactively call `wowok({ tool: "account_operation", data: { faucet: { ... } } })` to claim test tokens
60
- - Before starting any on-chain workflow, check balance via `wowok({ tool: "query_toolkit", data: { query_type: "account_balance", ... } })`
61
- - If balance is below 1 WOW, automatically request faucet without asking the user
62
- - If a transaction fails due to gas, retry after claiming more tokens
63
-
64
- ### Tool Reference
65
-
66
- - **Claim tokens**: `wowok({ tool: "account_operation", data: { faucet: { ... } } })` (not `onchain_operations`)
67
- - **Check balance**: `wowok({ tool: "query_toolkit", data: { query_type: "account_balance", ... } })`
68
-
69
- Each faucet claim provides approximately 5 WOW, sufficient for dozens of transactions.
70
-
71
- ---
72
-
73
- ## Core Rules
74
-
75
- ### Structural Wrapper Rules
76
-
77
- Most `onchain_operations` branches use `{ operation_type, data: {...}, env?, submission? }`. Three exceptions:
78
-
79
- | Branch | Difference |
80
- |--------|-----------|
81
- | `gen_passport` | No `data` wrapper — `guard`/`info` at top level |
82
- | `payment`, `personal` | Has `data` but NO `submission` field |
83
-
84
- ### CREATE vs MODIFY
85
-
86
- > [wowok-safety](../wowok-safety/SKILL.md) §1.1 — **String** = REUSE existing object, **Object** = CREATE new one. SDK-enforced via `GetObjectExisted()`, not Move-level.
87
-
88
- ### Permission Index Model
89
-
90
- Every object creation requires a Permission object. **Strongly recommended**: reuse a single Permission across all services for centralized control. Custom indices range 1000–65535; built-in 0–999 are reserved. The SDK auto-creates a Permission if you pass an object shape.
91
-
92
- ### Witness Conversion (`convert_witness`)
93
-
94
- When a Guard queries a related object (e.g., Progress from an Order), `convert_witness` transforms a submitted ID to the target type. Type compatibility is validated at Guard creation time by the Move contract — mismatches cause creation failure.
95
-
96
- ### Immutability
97
-
98
- | Object | Locked When | Recovery |
99
- |--------|------------|----------|
100
- | Guard | After creation | Create new, update all refs |
101
- | Machine (nodes) | After publish | Create new Machine, rebind Service |
102
- | Service `machine`/`order_allocators`/`arbitrations` | After publish (SDK-locked) | Create new Service |
103
- | Service `buy_guard` | **NOT locked** — mutable after publish | Can modify directly |
104
- | Passport | After generation | Regenerate with `gen_passport` |
105
- | Payment | After transfer | Irreversible — no protocol refund |
106
-
107
- ### Submission Loop (Two-Phase)
108
-
109
- When an `onchain_operations` call requires Guard validation, the SDK returns a **submission prompt** — a structured request for the data the Guard needs to evaluate. This is a two-phase pattern:
110
-
111
- 1. **Phase 1**: Call `onchain_operations` **without** the `submission` field. If a Guard requires input, the response returns a submission prompt.
112
- 2. **Phase 2**: Present the prompt to the user, collect their inputs, then **re-call** the SAME `onchain_operations` with the `submission` field populated.
113
-
114
- This applies whenever `submission` is listed in the structural wrapper (i.e., all branches except `gen_passport`, `payment`, `personal`). For `gen_passport`, each Guard's submission is passed independently via `info`.
115
-
116
- ### First-Guard-Wins
117
-
118
- Ordered Guard evaluation where **the first Guard returning `true` wins** applies to:
119
- - `service`: `order_allocators[].allocators[]`
120
- - `allocation`: evaluated modes (Amount → Rate → Surplus)
121
- - `demand`: presenter submission filtering
122
-
123
- ### Object-Guard Circular Reference Pattern
124
-
125
- When an object and its Guard need to reference each other (Guard queries the object it protects), follow this **universal three-step pattern**:
126
-
127
- ```
128
- 1. CREATE object (without Guard)
129
- 2. CREATE Guard (reference object by NAME in table)
130
- 3. MODIFY object (bind Guard by name)
131
- ```
132
-
133
- **Applies to all:** Service, Machine, Reward, Repository, Treasury, Demand, Arbitration — any object with Guard fields.
134
-
135
- **Key point:** Guards are immutable and require the target object's address in their table. Use the object's **name** (string) as the table value; the SDK resolves it to the actual address at runtime.
136
-
137
- **Example (Reward):**
138
- ```
139
- Step 1: CREATE reward { name: "reward_v1" } // no guard
140
- Step 2: CREATE guard { table: [{ value: "reward_v1", ... }] } // name reference
141
- Step 3: MODIFY reward { object: "reward_v1", guard_add: [...] } // bind guard
142
- ```
143
-
144
- ---
145
-
146
- ## Sub-Tool Schema-Inexpressible Constraints
147
-
148
- > MCP schemas define field types/validation. The constraints below are business rules NOT expressible in schemas — AI must know them before calling.
149
-
150
- ### `onchain_operations` (18 sub-types)
151
-
152
- | `operation_type` | Key Constraints (not in schema) |
153
- |-----------------|----------------------------------|
154
- | `service` | `machine` must be **published**. Allocators: array order = priority (first-Guard-wins). **Publish locks 2 fields (L1 absolute)**: `machine`/`order_allocators` — MUST be set BEFORE `publish:true`. **TIME-LOCKED (L2, need pause + setting_lock_duration)**: `arbitrations` remove/clear, `rewards` remove/clear, `compensation_fund_withdraw`. **REMAIN MUTABLE (L3)**: `arbitrations`(add)/`rewards`(add)/`sales`/`discount`/`description`/`location`/`pause`/`repositories`/`compensation_fund_add`/`setting_lock_duration_add`/`customer_required`/`um`/`buy_guard`. To change L1-locked fields after publish, clone a new Service. |
155
- | `machine` | Nodes immutable after publish. Forward needs ≥1 of `namedOperator`/`permissionIndex` (both empty = SDK error). `""` = entry node. → [wowok-machine](../wowok-machine/SKILL.md) |
156
- | `progress` | CANONICAL form: `operate: {operation: {next_node_name, forward}, op: "next"\|"hold"\|"unhold"\|"adminUnhold", message?}`. LEGACY `hold: boolean` is auto-converted (`hold:true`→`op:'hold'`, `hold:false`→`op:'next'`). SDK auto-fetches Machine when resolving `object_address`. **⚠ Routing rule**: Use `progress.operate` ONLY for forwards with non-empty `namedOperator` or `permissionIndex`-only. For forwards with `namedOperator=""` (OrderHolder), use `order.progress` instead — direct `progress::next` aborts with Permission denied (code 5). |
157
- | `arbitration` | MAX 20 propositions, 520 voters. Verdict (2→3) **irreversible** — only customer can `order.arb_objection`. Non-Finished withdrawal = 30-day wait. → [wowok-arbitrator](../wowok-arbitrator/SKILL.md) |
158
- | `guard` | `root.type:"node"` (inline) or `"file"` (JSON/MD). MAX 4 `rely`. `rep:false` Guards excluded from others' `rely`. System addresses `0xaab`/`0xaaa` need table entries. → [wowok-guard](../wowok-guard/SKILL.md) |
159
- | `gen_passport` | MAX 20 Guards/call (AND-ed). Omit `info` to auto-fetch. Passport = frozen immutable credential. |
160
- | `order` | Agents can operate but **cannot withdraw** — only builder. `order.progress`+Guard requires Passport. **⚠ Routing rule**: `order.progress` works ONLY for forwards with `namedOperator=""` (OrderHolder) — uses `order.has_op_permission`. For non-empty `namedOperator` or `permissionIndex`-only forwards, use `progress.operate` on the Progress object directly. Arb via `order.arb_confirm`/`arb_objection` (not `arbitration` directly). `arb_claim_compensation` once-only. → [wowok-order](../wowok-order/SKILL.md) |
161
- | `payment` | TWO modes: (1) CREATE: `type_parameter` required, `revenue[]` + `info`. **Irreversible** — no refund. (2) RECEIVE: `{object: '<coinwrapper_id_or_name>', receive: true, type_parameter: '0x2::wow::WOW'}` — unwraps a CoinWrapper (created by Allocation's `alloc_by_guard`) to the caller's wallet via `payment::unwrap_to_myself`. **CoinWrapper DOES arrive** in recipient's wallet via `transfer::public_transfer` (as an owned object), but it is NOT spendable coins — recipient must call `payment receive` to unwrap it into actual coins. Find received CoinWrappers via `query_toolkit` with `query_type='onchain_received'`. |
162
- | `personal` | **Permanently public** — warn users before writing sensitive data. |
163
- | `demand` | Guard-gated: `guards` filter presenters. Separate from Service. |
164
- | `treasury` | Guardable deposits/withdrawals. Each entry creates Payment record for audit. |
165
- | `repository` | Composite key: `name + entity`. Guard validates writer + content. |
166
- | `reward` | `guard_add`: `Fixed` (equal) or `GuardU64Identifier` (dynamic). `guard_expiration_time` freezes Guard list; `null` removes. |
167
- | `allocation` | **Manual trigger** — `alloc_by_guard` does NOT auto-execute on Progress advance. After advancing Progress, call `allocation` with `{object: '<alloc_name>', alloc_by_guard: '<guard_name>'}` to release funds. Order: Amount → Rate → Surplus, first-Guard-wins per mode. Each trigger releases currently-available balance based on Guard validation. Also: `received_coins` unwraps CoinWrappers into the Allocation's pending balance for re-allocation. |
168
- | `contact` | Bridge: Service `um` ↔ Messenger `ims[]`. IM mutations need permission index 453; no events (poll `ims[]`). |
169
- | `permission` | 0–999 reserved; custom ≥1000. SDK rejects <1000. Reusable across objects. |
170
- | `proof` | Immutable (freeze_object). `proof_type=1` reserved for WTS; >100 for custom. Large data → Repository + `about_address`, not inline. |
171
- | `gen_proof` | Convenience wrapper: creates Proof without `namedNew`. Same immutability rules. Use `proof` with `namedNew` when naming is needed. |
172
-
173
- ### Customer Operation Routing (decision tree)
174
-
175
- ```
176
- forward.namedOperator?
177
- ├─ "" (empty = OrderHolder) → order.progress (NOT progress.operate)
178
- │ └─ progress::next aborts: "Permission denied" (code 5)
179
- │ └─ Needs Passport if forward has guard
180
- └─ "<non-empty>" or permissionIndex-only → progress.operate
181
- └─ Provider or named operator executes
182
- ```
183
-
184
- > **Invariant**: `namedOperator === ""` ⟹ MUST use `order.progress`. No exceptions.
185
-
186
- **WIP hash anti-bait**: Capture `sale.wip_hash` when browsing; pass in `buy.items[].wip_hash`. Two-layer: SDK verifies file hash off-chain, Move asserts on-chain. Merchant swap = order fails.
187
-
188
- ### Other Tools (compact)
189
-
190
- | Tool | Key Constraints |
191
- |------|----------------|
192
- | `query_toolkit` | `token_list` cached (first query populates). `account_balance`: `balance=true` for totals, `coin={cursor,limit}` for paginated. `onchain_objects` batches 50/req. `local_names` resolves accounts + marks. **To list all local accounts**: use `query_type='account_list'` (account_operation itself has no list action). **To find received CoinWrappers** (for payment receive): use `query_type='onchain_received'`. |
193
- | `onchain_table_data` | 12 types. Global (no `parent`): `entity_registrar`, `entity_linker`. `onchain_table_item_generic` = universal fallback. |
194
- | `account_operation` | `faucet` testnet/localnet only. Mainnet funding: `transfer` from existing account (1 WOW = 10^9 base units). `gen` with `messenger: true` enables Messenger. **Naming convention**: `<role>-<number>` (e.g. `shop-001`, `user-001`, `arb-001`) for easy filtering. `gen.replaceExistName:true` is DISCOURAGED — suspends old account; FORBIDDEN on default account (name=''). Private keys never leave device. **No `list` action** — to enumerate all local accounts, use `query_toolkit` with `query_type='account_list'`. |
195
- | `local_mark_operation` | Max 50 tags/entry (64 chars). `replaceExistName:true` steals names — prefer `_v1`/`_v2`. |
196
- | `local_info_operation` | Max 50 contents/entry, 300 chars each. |
197
- | `messenger_operation` | Stranger: 1 msg before reply (~480 chars). Guard block → rejection includes guard list; sender needs Passport. WTS: `generate` needs continuous sequences. → [wowok-messenger](../wowok-messenger/SKILL.md) |
198
- | `wip_file` | `verify`: hash → signatures stepwise. `wip2html`: single file or directory. |
199
- | `guard2file` | Read-only export to JSON/Markdown. |
200
- | `machineNode2file` | Read-only; exports complete topology. |
201
- | `onchain_events` | 6 event types; cursor `{eventSeq, txDigest}`. |
202
- | `wowok_buildin_info` | 5 info types. Guard instructions filter by `name`/`return_type`/`param_count`. **Never use Value type 19**. |
203
- | `schema_query` | `list` returns empty if schemas not generated → `npm run generate:schemas`. Actions: `list`, `get` (full schema), `get_field` (field-path query e.g. `field_path='data.node'`), `get_output` (output schema), `search`, `list_operations`, `get_guard_templates` (Guard creation templates + best practices + common errors). Use `output_file='.trae/tmp/schema.json'` to write large schemas to workspace temp files (accessible via Read tool). |
204
- | `project_operation` | Sub-tool for project lifecycle: `create_project`, `add_object`, `build_graph`, `evaluate_project`, `pre_evaluate_check`, `verify_deployment`, `create_version`, `get_project_detail`. See §"Project Operation Extended Actions" below for the two pre/post-publish verification actions. |
205
-
206
- ### Project Operation Extended Actions
207
-
208
- Two `project_operation` actions act as **pre-flight and post-flight verification** around `evaluate_project` / deployment. They never mutate on-chain state — they only query and report.
209
-
210
- #### `pre_evaluate_check` (Pre-evaluation Readiness)
211
-
212
- **Purpose**: Verify input data completeness BEFORE calling `evaluate_project`, so callers can fix missing/stale data without paying the cost of a full evaluation.
213
-
214
- **Call pattern**: `wowok({ tool: "project_operation", data: { action: "pre_evaluate_check", project_id: "..." } })`
215
-
216
- **Returns**:
217
- - `ready: boolean` — true if `evaluate_project` will produce meaningful results
218
- - `missing[]` — hard blockers (e.g., PE-01 empty project, PE-06 producer without Service)
219
- - `warnings[]` — soft issues (PE-02 no graph edges, PE-03 uncached objects, PE-04 stale cache >24h, PE-05 dangling edges, PE-07 all drafts)
220
- - `counts` — quick metrics: `objects`, `edges`, `uncached`, `stale`, `dangling_edges`, `drafts`
221
- - `summary` — one-line human-readable status
222
-
223
- **When to use**: Always call BEFORE `evaluate_project`. If `ready=false`, fix the listed `missing` issues first. If `warnings` exist, decide whether to refresh data (`refresh_objects`, `build_graph`) or proceed with caveats.
224
-
225
- #### `verify_deployment` (Post-deployment Drift Detection)
226
-
227
- **Purpose**: After deploying objects on-chain, verify the on-chain state matches what SQLite expects. Catches drift caused by manual edits, version bumps, or third-party modifications after initial deployment.
228
-
229
- **Call pattern**: `wowok({ tool: "project_operation", data: { action: "verify_deployment", project_id: "..." } })`
230
-
231
- **Returns per-object verification status**:
232
- - `matched` — on-chain state matches SQLite
233
- - `mismatched` — on-chain state differs (fields listed in `differences`)
234
- - `missing` — object no longer exists on-chain
235
- - `unreachable` — query failed (network error or rate limit)
236
-
237
- **Also checks critical bindings for Service objects**: `machine`, `permission`, `buy_guard`, `order_allocators` are all set to non-null on-chain if they were recorded as bound in SQLite.
238
-
239
- **When to use**: After every publish operation (Service publish, Machine publish). Periodically for production monitoring. When debugging "evaluation says bound but on-chain says unbound" discrepancies.
240
-
241
- ---
242
-
243
- ## Supporting Objects — When to Use
244
-
245
- > MCP handles risk assessment + confirmation rules automatically. This section covers business decisions NOT in schemas — WHEN and WHY to choose each object type.
246
-
247
- ### Proof vs WIP
248
-
249
- | Aspect | Proof (on-chain) | WIP (off-chain file) |
250
- |--------|-----------------|---------------------|
251
- | Purpose | Cryptographic attestation (merkle root, server signature, timestamp) | Product description + images for arbitration evidence |
252
- | Immutability | `freeze_object` — permanent on-chain record | File hash anchored on-chain; file stored off-chain |
253
- | Size | `MAX_PROOF_SIZE` (compact digests only) | Unlimited (file-based) |
254
- | Use when | Need on-chain timestamp + signature verification | Need product evidence for order disputes |
255
-
256
- `gen_proof` = convenience (no `namedNew` wrapper). `proof` with `namedNew` = named object for reuse by reference. For large data, store in Repository and set `about_address` to the Repository ID.
257
-
258
- ### Treasury vs Allocation
259
-
260
- | Aspect | Treasury | Allocation |
261
- |--------|----------|------------|
262
- | Purpose | Team fund management (deposit/withdraw with audit trail) | Order fund distribution (manual `alloc_by_guard` trigger after Progress advance) |
263
- | Trigger | Manual deposit/withdraw (Guard-gated) | Manual `alloc_by_guard` after Progress advance (NOT automatic) |
264
- | Guard | External guard on withdrawals | Allocation guard on distribution rules |
265
- | Use when | Holding pooled funds, compensation funds, team wallets | Splitting order payments among recipients |
266
-
267
- **Compensation fund ≠ Treasury**: `Service.compensation_fund` is `Balance<T>` stored inline on the Service object (per service.move:179), NOT a Treasury address. Treasury is an independent object. Funds are added via `compensation_fund_add` (joins Coin<T> into the balance) and withdrawn via `compensation_fund_receive` after pause + lock duration. Each Treasury entry creates a Payment record for audit; withdrawal requires Guard verification.
268
-
269
- ### Reward (Incentive Pools)
270
-
271
- Guard-gated claim pools: each entry in `Reward.guards[].guard` (array — see wowok-guard SKILL) verifies eligibility before payout. `guard_add` modes: `Fixed` (equal split among claimants) or `GuardU64Identifier` (dynamic amount from Guard table index). `guard_expiration_time` freezes the Guard list (set `null` to remove freeze). Use cases: customer loyalty rewards, referral bonuses, airdrop campaigns, attendance rewards. Query claim history via `query_toolkit` → `onchain_table_item_reward_record`.
272
-
273
- ### Demand (Customer-Posted Requests)
274
-
275
- Demand is the **inverse** of Service: customer posts a request + optional reward pool, providers submit offers. Guard-gated: each entry in `Demand.guards[].guard` (array — see wowok-guard SKILL) filters which providers can present. The `service_identifier` field on each ServiceGuard differentiates filtering roles (e.g., recommend vs. eligibility). Separate `operation_type: "demand"` — NOT `service`. Use when: customer needs competitive bids (custom work, bulk procurement, reverse-auction marketplace). Pair with Reward to incentivize providers.
276
-
277
- ### Repository (On-Chain Database)
278
-
279
- Composite key: `name + entity`. Guard validates writer identity + content integrity. `id_from_submission` (must be Address) and `data_from_submission` (must match Repository's `value_type`) extract structured data from Guard submissions. Use cases: supply-chain tracking, multi-party attestation, dynamic pricing data, KYC registries. MAX 50 policies per Repository, 100 IDs per operation. Guard design: see [wowok-guard](../wowok-guard/SKILL.md) §"Where Guards Attach".
280
-
281
- ### Contact (Service.um Bridge)
282
-
283
- Contact is the on-chain bridge: `Service.um` → `Contact` → `ims[]` (Messenger endpoints). Create BEFORE Service publish when `customer_required` is set. Contact can also bind to `Permission.um` (bidirectional dependency — clear `Permission.um` via `permission_um_set(null)` before deleting Contact). IM list mutations (`im_add`/`im_remove`) require permission index 453; no events emitted (poll `ims[]` field). Full Messenger integration: see [wowok-messenger](../wowok-messenger/SKILL.md).
284
-
285
- ---
286
-
287
- ## Decision Tree
288
-
289
- ```
290
- All calls via: wowok({ tool: "<sub-tool>", data: {<params>} })
291
-
292
- Write state? → tool: "onchain_operations" (choose operation_type in data)
293
- ├── No data wrapper? → only gen_passport
294
- ├── No submission? → only payment, personal
295
- └── String (MODIFY) vs Object (CREATE)? → safety §1.1
296
-
297
- Read state? → tool: "query_toolkit" / "onchain_table_data"
298
- Communicate? → tool: "messenger_operation" (encrypted)
299
- Local only? → tool: "account_operation" / "local_mark_operation" / "local_info_operation"
300
- Export? → tool: "guard2file" / "machineNode2file"
301
- Discover? → tool: "schema_query" / "wowok_buildin_info" / "onchain_events"
302
- ```
303
-
304
- ---
305
-
306
- ## Examples Reference
307
-
308
- 5 examples in `examples/` directory: **Insurance** (⭐ time-lock Guard), **MyShop** (⭐⭐ e-commerce, Messenger, discounts), **MyShop_Advanced** (⭐⭐⭐ 11+ nodes, dual-sig, Merkle Root, Reward), **Travel** (⭐⭐⭐ Repository Guard, supply chain), **ThreeBody_Signature** (⭐ Buy Guard). Each includes `*_TestResults.md` with real testnet data. Match user intent → example complexity → extract JSON patterns.
309
-
310
- ---
311
-
312
- ## Common Pitfalls
313
-
314
- | Trap | Fix |
315
- |------|-----|
316
- | **Calling sub-tool name directly** | MCP only exposes `wowok`. Use `wowok({ tool: "onchain_operations", data: {...} })`, not `onchain_operations({...})` |
317
- | **Schema validation error** | The response includes `schema.input` — read it, fix params, retry. Cache the schema for future calls to the same sub-tool. |
318
- | **Transaction fails, gas error** | → [Pre-Flight: Gas & Faucet](#pre-flight-gas--faucet). AI should auto-check balance + faucet. |
319
- | **Don't know how to build a service** | → [Examples Reference](#examples-reference). Match user intent → example, extract JSON templates. |
320
- | `gen_passport` called as standalone tool | It's not — use `wowok({ tool: "onchain_operations", data: { operation_type: "gen_passport", ... } })` |
321
- | Missing `data` wrapper | Only `gen_passport` omits it; `payment`/`personal` omit `submission` |
322
- | String `object` passed expecting CREATE | String = existing (MODIFY), Object = new (CREATE) → [safety §1.1](../wowok-safety/SKILL.md) |
323
- | Missing `submission` on Guard call | See [Submission Loop](#submission-loop-two-phase) — two-phase pattern: call without `submission` first, collect data, re-call with it |
324
- | Publishing before all deps ready | Guard/Machine immutable after create/publish. Test via `gen_passport` before finalizing |
325
- | `demand` via `service` operation_type | Separate `operation_type: "demand"` — Demand posts are not Services |
326
- | Arbitration called directly | Customer path: `order.arb_confirm` / `order.arb_objection`. Order is the interface |
327
-
328
- ---
329
-
330
- ## Cross-Network Name Management (testnet → mainnet)
331
-
332
- > Object addresses differ between testnet and mainnet. WoWok uses **local names** to bridge this gap — the same name resolves to different addresses on different networks.
333
-
334
- ### How Name Resolution Works
335
-
336
- - **Local names** are stored per-network in the local SQLite database (`LocalMark`).
337
- - When you create an object with `namedNew.name = "my_service"`, the name→address mapping is stored for the **current network** (specified in `env.network`).
338
- - When you reference `"my_service"` in a subsequent call, the SDK resolves it to the address **for the current network**.
339
- - Names are **NOT shared across networks** — testnet and mainnet have separate name registries.
340
-
341
- ### Testnet → Mainnet Migration Workflow
342
-
343
- 1. **Develop and test on testnet**: Create all objects with `replaceExistName: true` and consistent names (e.g., `myshop_permission`, `myshop_machine`, `myshop_service`).
344
- 2. **Record the JSON call sequence**: Save all `onchain_operations` calls (with their `data` and `env` fields) that worked on testnet.
345
- 3. **Switch `env.network` to `mainnet`**: Change `env.network` from `"testnet"` to `"mainnet"` in all calls. Also switch `env.account` to a mainnet-funded account.
346
- 4. **Re-run the same call sequence on mainnet**: With `replaceExistName: true` on all object creations, the same names will be re-registered to new mainnet addresses. All cross-references (e.g., `permission: "myshop_permission"` in Machine) will resolve to the new mainnet addresses automatically.
347
- 5. **Fund the mainnet account**: Use `account_operation` with `transfer` from a funded account (1 WOW = 10^9 base units).
348
-
349
- ### Key Rules
350
-
351
- | Rule | Detail |
352
- |------|--------|
353
- | `replaceExistName: true` | Re-creates the name→address mapping for the current network. Use on all object creations when re-deploying. |
354
- | Name consistency | Use the SAME names across testnet and mainnet. The SDK resolves names per-network, so `"my_service"` on testnet ≠ `"my_service"` on mainnet (different addresses). |
355
- | `env.network` | The ONLY field that changes between testnet and mainnet runs. All `data` fields (names, references, configs) stay the same. |
356
- | Object references | Always use names (strings), NOT hardcoded addresses (0x...). Hardcoded addresses break across networks. |
357
- | Account funding | `faucet` works only on testnet/localnet. Mainnet requires `transfer` from an existing funded account. |
358
-
359
- ### Example: Testnet → Mainnet
360
-
361
- ```json
362
- // testnet call (works)
363
- {
364
- "tool": "onchain_operations",
365
- "data": {
366
- "operation_type": "service",
367
- "data": { "object": { "name": "my_service", "permission": "my_permission", ... } },
368
- "env": { "account": "test_account", "network": "testnet", "confirmed": true }
369
- }
370
- }
371
-
372
- // mainnet call (same data, only env changes)
373
- {
374
- "tool": "onchain_operations",
375
- "data": {
376
- "operation_type": "service",
377
- "data": { "object": { "name": "my_service", "permission": "my_permission", ... } },
378
- "env": { "account": "main_account", "network": "mainnet", "confirmed": true }
379
- }
380
- }
381
- ```
382
-
383
- ### Common Mistakes
384
-
385
- - **Hardcoding addresses**: `"machine": "0xabc123..."` breaks on mainnet. Use `"machine": "my_machine"` instead.
386
- - **Forgetting `replaceExistName`**: Without it, re-deploying to a new network creates a name conflict if the name already exists locally.
387
- - **Mixing networks in one session**: All calls in a deployment sequence should use the same `env.network`. Mixing testnet and mainnet calls causes name resolution failures.
388
-
389
- ---