@wowok/skills 3.0.4 → 3.1.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.
Files changed (47) hide show
  1. package/README.md +146 -122
  2. package/dist/cli.d.ts +6 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +223 -837
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +24 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/installer.d.ts +121 -0
  11. package/dist/installer.d.ts.map +1 -0
  12. package/dist/installer.js +802 -0
  13. package/dist/installer.js.map +1 -0
  14. package/dist/skills.d.ts +5 -2
  15. package/dist/skills.d.ts.map +1 -1
  16. package/dist/skills.js +86 -62
  17. package/dist/skills.js.map +1 -1
  18. package/dist/targets.d.ts +94 -0
  19. package/dist/targets.d.ts.map +1 -0
  20. package/dist/targets.js +421 -0
  21. package/dist/targets.js.map +1 -0
  22. package/dist/types.d.ts +5 -4
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/types.js +0 -32
  25. package/dist/types.js.map +1 -1
  26. package/package.json +5 -4
  27. package/scripts/install.js +21 -859
  28. package/wowok-arbitrator/SKILL.md +5 -12
  29. package/wowok-auditor/SKILL.md +5 -17
  30. package/wowok-collaborator/SKILL.md +5 -17
  31. package/wowok-governance/SKILL.md +10 -30
  32. package/wowok-machine/SKILL.md +5 -18
  33. package/wowok-market/SKILL.md +5 -21
  34. package/wowok-messenger/SKILL.md +32 -50
  35. package/wowok-onboard/SKILL.md +5 -22
  36. package/wowok-order/SKILL.md +6 -19
  37. package/wowok-output/SKILL.md +5 -10
  38. package/wowok-planner/SKILL.md +6 -20
  39. package/wowok-provider/SKILL.md +6 -18
  40. package/wowok-supplier/SKILL.md +5 -16
  41. package/examples/Insurance/Insurance.md +0 -1245
  42. package/examples/MyShop/MyShop.md +0 -2003
  43. package/examples/MyShop/myshop_machine_nodes.json +0 -93
  44. package/examples/MyShop_Advanced/MyShop_Advanced.md +0 -2880
  45. package/examples/ThreeBody_Signature/ThreeBody_Signature.md +0 -1831
  46. package/examples/Travel/Travel.md +0 -1849
  47. package/examples/Travel/calc-weather-timestamps.js +0 -12
@@ -1,1849 +0,0 @@
1
- # Iceland Travel Service Example
2
-
3
- A complete example demonstrating how to create an Iceland travel service using WoWok protocol. This service integrates weather-dependent activities and multi-node workflow management. (Note: "Buy Insurance" is just the name of the first workflow node in this example — there is no real insurance sub-order mechanism.)
4
-
5
- ---
6
-
7
- ## ⚠️ Running Principle
8
-
9
- > **Run the example in full every time (repeatable).** This example uses `replaceExistName: true` on all object creations — each run generates new objects with new addresses. If you skip build steps, operations may silently act on orphaned objects from previous runs, producing incorrect results. Old objects' configurations do not reflect the current document version.
10
-
11
- - **Execution order**: Run all build/setup steps in sequence before testing any customer or order flow. Do not skip steps — each depends on objects created by prior steps.
12
- - **Prerequisites**: `travel_provider`, `weather_provider`, and `alice` (test customer) with sufficient WOW for gas. All on-chain operations require `env.confirmed: true`.
13
-
14
- ### 🔐 Two-Step Confirmation Flow (Production Safety)
15
-
16
- This example sets `env.confirmed: true` on irreversible operations (e.g., `publish: true` on Machine) for brevity. In real deployments, follow the two-step flow enforced by the ConfirmGate safety layer:
17
-
18
- 1. **Phase 1 — Preview**: Call the tool **without** `env.confirmed`. The server returns `{ status: "pending_confirmation", confirmation_text: "..." }` containing the full operation summary, risk assessment, and irreversible-action warnings.
19
- 2. **Phase 2 — Confirm**: Review `confirmation_text` with the user. Only after explicit user approval, call the tool again **with** `env.confirmed: true` to actually execute the on-chain transaction.
20
-
21
- > Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm.
22
-
23
- ---
24
-
25
- > **💡 Call Format**: All WoWok operations go through a single unified `wowok` tool. The AI calls `wowok({ tool: "<sub-tool>", data: {<params>} })`. If parameters don't match the schema, the response includes the correct schema for self-correction. See [Response Format](../../docs/response-format.md) for details.
26
-
27
- ## Core Requirements & Features
28
-
29
- | Requirement | Description | Implementation |
30
- |-------------|-------------|----------------|
31
- | **Weather Data Query** | Demonstrate querying weather Repository | Guard checks if weather data exists for a given date |
32
- | **Multi-Node Workflow** | Start -> Buy Insurance -> SPA -> Ice Scooting -> Complete | Machine with 5 nodes and conditional paths |
33
- | **Time-Lock Completion** | Prevent premature order completion | Guard using Order + convert_witness(TypeOrderProgress) |
34
- | **Cancellation Support** | Allow order cancellation from Ice Scooting node | Cancel forward with permission-based access |
35
- | **Arbitration** | Dispute resolution for order conflicts | Arbitration object bound to Service |
36
- | **Revenue Allocation** | Distribute funds based on progress state | Three allocation Guards for different refund scenarios |
37
-
38
- ---
39
-
40
- ## Prerequisites
41
-
42
- Before running this example, ensure you have:
43
-
44
- 1. An account named `travel_provider` with sufficient WOW tokens
45
- 2. An account named `weather_provider` with sufficient WOW tokens
46
- 3. An account named `alice` (test customer) with sufficient WOW tokens
47
- 4. Access to the WoWok MCP server
48
-
49
- ### Create Accounts
50
-
51
- **Prompt**: Create accounts for travel provider, weather provider, and test customer.
52
-
53
- ```json
54
- {
55
- "tool": "account_operation",
56
- "data": {
57
- "gen": {
58
- "name": "travel_provider",
59
- "replaceExistName": true
60
- }
61
- }
62
- }
63
- ```
64
-
65
- ```json
66
- {
67
- "tool": "account_operation",
68
- "data": {
69
- "gen": {
70
- "name": "weather_provider",
71
- "replaceExistName": true
72
- }
73
- }
74
- }
75
- ```
76
-
77
- ```json
78
- {
79
- "tool": "account_operation",
80
- "data": {
81
- "gen": {
82
- "name": "alice",
83
- "replaceExistName": true
84
- }
85
- }
86
- }
87
- ```
88
-
89
- ### Get Test Tokens
90
-
91
- **Prompt**: Request testnet WOW tokens for all accounts.
92
-
93
- ```json
94
- {
95
- "tool": "account_operation",
96
- "data": {
97
- "faucet": {
98
- "network": "testnet",
99
- "name_or_address": "travel_provider"
100
- }
101
- }
102
- }
103
- ```
104
-
105
- ```json
106
- {
107
- "tool": "account_operation",
108
- "data": {
109
- "faucet": {
110
- "network": "testnet",
111
- "name_or_address": "weather_provider"
112
- }
113
- }
114
- }
115
- ```
116
-
117
- ```json
118
- {
119
- "tool": "account_operation",
120
- "data": {
121
- "faucet": {
122
- "network": "testnet",
123
- "name_or_address": "alice"
124
- }
125
- }
126
- }
127
- ```
128
-
129
- ---
130
-
131
- ## Environment Parameters
132
-
133
- All on-chain operations in this example use the following `env` fields:
134
-
135
- | Field | Value | Purpose |
136
- |-------|-------|---------|
137
- | `network` | `"testnet"` | Target network |
138
- | `account` | Account name | Signer account for the transaction |
139
- | `no_cache` | `true` | Bypass local cache to avoid stale reads during sequential object creation. Without this, operations that depend on recently created objects may fail with "object not found". |
140
- | `confirmed` | `true` | Explicitly confirm the on-chain transaction (MCP ConfirmGate). Required for all write operations. |
141
-
142
- Additionally, `onChain: true` is required when an object's name needs to be resolved across different accounts (see Step 0.3).
143
-
144
- ---
145
-
146
- ## Step 0: Setup Weather Data
147
-
148
- Before creating the travel service, set up the weather Repository with the next 5 days of weather data. The weather data is keyed by timestamp, and the `weather_check_guard` (Step 3.1) will query this repository at runtime when the customer enters the "Ice Scooting" node (Step 7.3). You must use timestamps that are valid at the time you run this example.
149
-
150
- ### 0.1 Calculate Weather Timestamps
151
-
152
- The weather record `id` is a UTC timestamp (in milliseconds). It must be **aligned to UTC 00:00:00** so that the same timestamp can be reproduced and submitted later in Step 7.3. Run the following JavaScript (also available as `calc-weather-timestamps.js` in this example folder):
153
-
154
- ```js
155
- const DAY_MS = 86400000; // 24 * 60 * 60 * 1000
156
- const now = Date.now();
157
- // Align to UTC 00:00:00 of today, then compute the next 5 days.
158
- // Repository data is keyed by timestamp, so the submitted activity date
159
- // must match exactly the id used when adding weather data.
160
- const todayStart = Math.floor(now / DAY_MS) * DAY_MS;
161
- for (let i = 1; i <= 5; i++) {
162
- const ts = todayStart + i * DAY_MS;
163
- console.log(`Day ${i}: ${ts} (${new Date(ts).toISOString()})`);
164
- }
165
- ```
166
-
167
- **Sample output** (run on 2026-07-08 — re-run the script to get current values for your test time):
168
-
169
- ```
170
- Day 1: 1783555200000 (2026-07-09T00:00:00.000Z)
171
- Day 2: 1783641600000 (2026-07-10T00:00:00.000Z)
172
- Day 3: 1783728000000 (2026-07-11T00:00:00.000Z)
173
- Day 4: 1783814400000 (2026-07-12T00:00:00.000Z)
174
- Day 5: 1783900800000 (2026-07-13T00:00:00.000Z)
175
- ```
176
-
177
- > **Important**: Always re-run the script at test time — the timestamps depend on the current date. Copy the 5 printed values; they will be used in Step 0.4 (as repository data `id`) and Step 7.3 (as the submitted `activity_date`). The two must match exactly, otherwise the Guard query `repository.data has("Condition", convert_number_address(activity_date))` will return false.
178
-
179
- ### 0.2 Create Weather Permission
180
-
181
- **Prompt**: Create a Permission object named "weather_permission".
182
-
183
- ```json
184
- {
185
- "tool": "onchain_operations",
186
- "data": {
187
- "operation_type": "permission",
188
- "data": {
189
- "object": {
190
- "name": "weather_permission",
191
- "replaceExistName": true
192
- },
193
- "description": "Weather repository permission"
194
- },
195
- "env": {
196
- "account": "weather_provider",
197
- "network": "testnet",
198
- "no_cache": true,
199
- "confirmed": true
200
- }
201
- }
202
- }
203
- ```
204
-
205
- ### 0.3 Create Weather Repository with Policies
206
-
207
- **Prompt**: Create a Repository named "weather_repo" with "Condition" policy.
208
-
209
- ```json
210
- {
211
- "tool": "onchain_operations",
212
- "data": {
213
- "operation_type": "repository",
214
- "data": {
215
- "object": {
216
- "name": "weather_repo",
217
- "permission": "weather_permission",
218
- "replaceExistName": true,
219
- "onChain": true
220
- },
221
- "description": "Weather data repository for Iceland travel activities",
222
- "policies": {
223
- "op": "add",
224
- "policy": [
225
- {
226
- "name": "Condition",
227
- "description": "Weather condition policy for activity dates",
228
- "write_guard": [{ "guard": "weather_write_guard" }],
229
- "id_from": "None",
230
- "value_type": "String"
231
- }
232
- ]
233
- }
234
- },
235
- "env": {
236
- "account": "weather_provider",
237
- "network": "testnet",
238
- "no_cache": true,
239
- "confirmed": true
240
- }
241
- }
242
- }
243
- ```
244
-
245
- > **Note**: `onChain: true` is required here because `weather_repo` is created by the `weather_provider` account, but its name will be referenced in the Guard table (Step 3.1) by the `travel_provider` account. Without `onChain: true`, the name is stored locally only on `weather_provider`'s device and cannot be resolved by `travel_provider`. When `onChain: true` is set, the name is published on-chain and becomes publicly visible, allowing cross-account name resolution.
246
- >
247
- > The `write_guard` in the "Condition" policy points to `weather_write_guard` (created above). Because `id_from: "None"` lets the writer choose data ids, the contract mandates a Guard to authorize writes. `data_add` in Step 0.4 needs no Guard submission — the Guard is always-true with no submission fields.
248
-
249
- ### 0.4 Add Weather Data
250
-
251
- Add 5 days of weather data. The `weather_check_guard` (Step 3.1) only verifies that a record **exists** for the activity date (via `repository.data has`), so all 5 days will pass the Guard regardless of the condition value. The "rainy" value on Day 5 is informational only — to actually reject based on weather condition, you would need a Guard that queries `repository.data` and compares the value, which is more complex and not used in this example.
252
-
253
- **Prompt**: Add weather data to "weather_repo" with policy "Condition".
254
-
255
- ```json
256
- {
257
- "tool": "onchain_operations",
258
- "data": {
259
- "operation_type": "repository",
260
- "data": {
261
- "object": "weather_repo",
262
- "data_add": {
263
- "name": "Condition",
264
- "items": [
265
- {
266
- "data": [
267
- {"id": <DAY1_TIMESTAMP>, "data": "sunny"},
268
- {"id": <DAY2_TIMESTAMP>, "data": "sunny"},
269
- {"id": <DAY3_TIMESTAMP>, "data": "sunny"},
270
- {"id": <DAY4_TIMESTAMP>, "data": "sunny"},
271
- {"id": <DAY5_TIMESTAMP>, "data": "rainy"}
272
- ]
273
- }
274
- ]
275
- }
276
- },
277
- "env": {
278
- "account": "weather_provider",
279
- "network": "testnet",
280
- "no_cache": true,
281
- "confirmed": true
282
- }
283
- }
284
- }
285
- ```
286
-
287
- > **Note**: Replace `<DAY1_TIMESTAMP>` through `<DAY5_TIMESTAMP>` with the actual values from Step 0.1. The `id` field is the timestamp (as a number) that keys the weather record — it must **exactly match** the timestamp you submit later in Step 7.3.
288
-
289
- ---
290
-
291
- ## Step 1: Create Permission Object
292
-
293
- Create a Permission object to manage access control for the travel service. Add permission indices for the travel_provider account.
294
-
295
- **Prompt**: Create a Permission object named "travel_permission" for the travel service.
296
-
297
- ```json
298
- {
299
- "tool": "onchain_operations",
300
- "data": {
301
- "operation_type": "permission",
302
- "data": {
303
- "object": {
304
- "name": "travel_permission",
305
- "tags": ["travel", "iceland", "tourism"],
306
- "replaceExistName": true
307
- },
308
- "description": "Permission for Iceland travel service",
309
- "table": {
310
- "op": "add perm by entity",
311
- "entity": {"name_or_address": "travel_provider"},
312
- "index": [1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 306]
313
- }
314
- },
315
- "env": {
316
- "account": "travel_provider",
317
- "network": "testnet",
318
- "no_cache": true,
319
- "confirmed": true
320
- }
321
- }
322
- }
323
- ```
324
-
325
- > **Note**: Permission indices 1000-1009 are used for different workflow forwards. Index 306 is the built-in `SERVICE_MACHINE` permission — it governs binding or changing a Service's Machine (`service::machine_set`), and is required in Step 5 when the Service binds `travel_machine`. The travel_provider account is granted all these permissions.
326
-
327
- ---
328
-
329
- ## Step 1.5: Create Arbitration Permission
330
-
331
- Create a dedicated Permission object for the Arbitration. No special permission indices are needed — the creator (`travel_provider`) automatically becomes the admin of the new Permission.
332
-
333
- > **Why a separate Permission?** When a Service binds an Arbitration, the contract asserts `arbitration.permission != service.permission` (error `E_ARBITRATION_PERMISSION_CONFLICT`). If the Arbitration shared the Service's permission, the Service owner would control dispute resolution, breaking fairness. The Arbitration must therefore use an independent Permission object.
334
-
335
- **Prompt**: Create a Permission object named "travel_arbitration_permission" for the arbitration.
336
-
337
- ```json
338
- {
339
- "tool": "onchain_operations",
340
- "data": {
341
- "operation_type": "permission",
342
- "data": {
343
- "object": {
344
- "name": "travel_arbitration_permission",
345
- "tags": ["travel", "arbitration"],
346
- "replaceExistName": true
347
- },
348
- "description": "Independent permission for travel arbitration (must differ from the Service permission)"
349
- },
350
- "env": {
351
- "account": "travel_provider",
352
- "network": "testnet",
353
- "no_cache": true,
354
- "confirmed": true
355
- }
356
- }
357
- }
358
- ```
359
-
360
- ---
361
-
362
- ## Step 2: Create Arbitration Object
363
-
364
- Create an Arbitration object for dispute resolution. It uses the independent `travel_arbitration_permission` created in Step 1.5.
365
-
366
- **Prompt**: Create an Arbitration named "travel_arbitration".
367
-
368
- ```json
369
- {
370
- "tool": "onchain_operations",
371
- "data": {
372
- "operation_type": "arbitration",
373
- "data": {
374
- "object": {
375
- "name": "travel_arbitration",
376
- "permission": "travel_arbitration_permission",
377
- "replaceExistName": true
378
- },
379
- "description": "Arbitration for Iceland travel service disputes"
380
- },
381
- "env": {
382
- "account": "travel_provider",
383
- "network": "testnet",
384
- "no_cache": true,
385
- "confirmed": true
386
- }
387
- }
388
- }
389
- ```
390
-
391
- ---
392
-
393
- ## Step 2.5: Create Service (Unpublished)
394
-
395
- Create the Service without publishing to obtain its address for Guard creation. The Service address is required by the allocator Guards (Step 3.4–3.6) to verify `order.service == travel_service` (R-C3-05 cross-service theft protection).
396
-
397
- **Prompt**: Create Service "travel_service" with permission "travel_permission", do not publish.
398
-
399
- ```json
400
- {
401
- "tool": "onchain_operations",
402
- "data": {
403
- "operation_type": "service",
404
- "data": {
405
- "object": {
406
- "name": "travel_service",
407
- "permission": "travel_permission",
408
- "replaceExistName": true
409
- },
410
- "description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting.",
411
- "pause": false
412
- },
413
- "env": {
414
- "account": "travel_provider",
415
- "network": "testnet",
416
- "no_cache": true,
417
- "confirmed": true
418
- }
419
- }
420
- }
421
- ```
422
-
423
- **Record the Service address** - it will be needed for allocator Guard creation (Step 3.4–3.6) to bind `order.service` verification.
424
-
425
- ---
426
-
427
- ### Step 2.6: Create Treasury (Merchant Revenue Aggregation)
428
-
429
- Create a Treasury object to aggregate merchant revenue. The Treasury uses the **same Permission** as the Service (`travel_permission`) for consistency — a single permission organization governs both fund collection and service operations.
430
-
431
- **Prompt**: Create Treasury "travel_treasury" with permission "travel_permission", type parameter "0x2::wow::WOW".
432
-
433
- ```json
434
- {
435
- "tool": "onchain_operations",
436
- "data": {
437
- "operation_type": "treasury",
438
- "data": {
439
- "object": {
440
- "name": "travel_treasury",
441
- "type_parameter": "0x2::wow::WOW",
442
- "permission": "travel_permission",
443
- "replaceExistName": true
444
- },
445
- "description": "Treasury for aggregating travel service merchant revenue. Uses the same Permission as the Service (travel_permission) for consistency — a single permission organization governs both fund collection and service operations."
446
- },
447
- "env": {
448
- "account": "travel_provider",
449
- "network": "testnet",
450
- "no_cache": true,
451
- "confirmed": true
452
- }
453
- }
454
- }
455
- ```
456
-
457
- > **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance and MyShop_Advanced examples, merchant revenue flows to `travel_treasury` (not directly to the Service address). This:
458
- > 1. **Aggregates public funds** for operational distribution and accounting
459
- > 2. **Makes allocators inherently safe** (R-C3-06) — funds always flow to the fixed Treasury regardless of caller, so no Signer binding is needed in the Guard
460
- > 3. **Uses permission consistency** — Treasury and Service share `travel_permission`, ensuring unified governance
461
-
462
- ---
463
-
464
- ## Step 3: Create Guards
465
-
466
- Create all Guards needed for the workflow and fund allocation. Guards are immutable once created, so create them before the Machine and Service.
467
-
468
- > **Prerequisite**: The Service must be created (unpublished) in Step 2.5 first, because the allocator Guards (3.4–3.6) reference the Service address to verify `order.service == travel_service` (R-C3-05 cross-service theft protection).
469
-
470
- ### 3.1 Weather Check Guard
471
-
472
- Creates a Guard that verifies weather data exists for a given date. This Guard is bound to the "go_ice_scooting" forward (entering the weather-dependent Ice Scooting activity) to ensure the activity date has a weather record in the repository.
473
-
474
- **Guard Logic**:
475
- ```
476
- repository.data has("Condition", convert_number_address(activity_date))
477
- ```
478
-
479
- **Prompt**: Create a Guard named "weather_check_guard" for weather condition verification.
480
-
481
- ```json
482
- {
483
- "tool": "onchain_operations",
484
- "data": {
485
- "operation_type": "guard",
486
- "data": {
487
- "namedNew": {
488
- "name": "weather_check_guard",
489
- "tags": ["weather", "check", "travel"],
490
- "replaceExistName": true
491
- },
492
- "description": "Weather check guard for ice scooting activity. Checks if weather data exists for the activity date.",
493
- "table": [
494
- {
495
- "identifier": 0,
496
- "b_submission": false,
497
- "value_type": "Address",
498
- "value": "weather_repo",
499
- "name": "Weather Repository address"
500
- },
501
- {
502
- "identifier": 1,
503
- "b_submission": false,
504
- "value_type": "String",
505
- "value": "Condition",
506
- "name": "Repository policy name"
507
- },
508
- {
509
- "identifier": 2,
510
- "b_submission": true,
511
- "value_type": "U64",
512
- "name": "Activity date timestamp (submitted at runtime)"
513
- }
514
- ],
515
- "root": {
516
- "type": "query",
517
- "query": "repository.data has",
518
- "object": {"identifier": 0},
519
- "parameters": [
520
- {"type": "identifier", "identifier": 1},
521
- {
522
- "type": "convert_number_address",
523
- "node": {"type": "identifier", "identifier": 2}
524
- }
525
- ]
526
- }
527
- },
528
- "env": {
529
- "account": "travel_provider",
530
- "network": "testnet",
531
- "no_cache": true,
532
- "confirmed": true
533
- }
534
- }
535
- }
536
- ```
537
-
538
- **Guard Table**:
539
-
540
- | identifier | b_submission | value_type | value | Purpose |
541
- |------------|-------------|-----------|-------|---------|
542
- | 0 | false | Address | weather_repo | Weather Repository to query |
543
- | 1 | false | String | "Condition" | Repository policy name |
544
- | 2 | **true** | U64 | 0 (placeholder) | Activity date timestamp, submitted at runtime |
545
-
546
- ### 3.2 Travel Complete Guard (Time-Lock)
547
-
548
- Creates a Guard that verifies the time-lock condition for order completion.
549
-
550
- **Guard Logic**:
551
- ```
552
- clock > progress.current_time + 1000
553
- (progress accessed via Order + convert_witness="OrderProgress")
554
- ```
555
-
556
- **Prompt**: Create a Guard named "travel_complete_guard" for time-lock verification.
557
-
558
- ```json
559
- {
560
- "tool": "onchain_operations",
561
- "data": {
562
- "operation_type": "guard",
563
- "data": {
564
- "namedNew": {
565
- "name": "travel_complete_guard",
566
- "tags": ["travel", "time-lock", "complete"],
567
- "replaceExistName": true
568
- },
569
- "description": "Time-lock guard for travel order completion. Requires current clock > progress.current_time + 1000ms.",
570
- "table": [
571
- {
572
- "identifier": 0,
573
- "b_submission": true,
574
- "value_type": "Address",
575
- "name": "Order ID (submitted at runtime)"
576
- },
577
- {
578
- "identifier": 1,
579
- "b_submission": false,
580
- "value_type": "U64",
581
- "value": 1000,
582
- "name": "Time-lock duration in ms"
583
- }
584
- ],
585
- "root": {
586
- "type": "logic_as_u256_greater",
587
- "nodes": [
588
- {"type": "context", "context": "Clock"},
589
- {
590
- "type": "calc_number_add",
591
- "nodes": [
592
- {
593
- "type": "query",
594
- "query": "progress.current_time",
595
- "object": {"identifier": 0, "convert_witness": "OrderProgress"},
596
- "parameters": []
597
- },
598
- {"type": "identifier", "identifier": 1}
599
- ]
600
- }
601
- ]
602
- }
603
- },
604
- "env": {
605
- "account": "travel_provider",
606
- "network": "testnet",
607
- "no_cache": true,
608
- "confirmed": true
609
- }
610
- }
611
- }
612
- ```
613
-
614
- **Guard Table**:
615
-
616
- | identifier | b_submission | value_type | value | Purpose |
617
- |------------|-------------|-----------|-------|---------|
618
- | 0 | **true** | Address | 0x0...0 (placeholder) | Order ID submitted at runtime, converted to Progress via convert_witness |
619
- | 1 | false | U64 | 1000 | Time-lock duration in ms (1 second for testing) |
620
-
621
- > **Important**: `1000` ms (1 second) is for testing only. In production, set to a reasonable duration (e.g., 8 hours = 28800000 ms).
622
-
623
- ### 3.3 Travel Cancel Guard
624
-
625
- Creates a Guard that allows order cancellation. This Guard always passes (returns true), as cancellation is controlled by permission-based access.
626
-
627
- **Prompt**: Create a Guard named "travel_cancel_guard" for order cancellation.
628
-
629
- ```json
630
- {
631
- "tool": "onchain_operations",
632
- "data": {
633
- "operation_type": "guard",
634
- "data": {
635
- "namedNew": {
636
- "name": "travel_cancel_guard",
637
- "tags": ["travel", "cancel"],
638
- "replaceExistName": true
639
- },
640
- "description": "Cancel guard for travel orders. Always passes - cancellation is controlled by permission-based access.",
641
- "table": [
642
- {
643
- "identifier": 0,
644
- "b_submission": false,
645
- "value_type": "Bool",
646
- "value": true,
647
- "name": "Always true"
648
- }
649
- ],
650
- "root": {
651
- "type": "identifier",
652
- "identifier": 0
653
- }
654
- },
655
- "env": {
656
- "account": "travel_provider",
657
- "network": "testnet",
658
- "no_cache": true,
659
- "confirmed": true
660
- }
661
- }
662
- }
663
- ```
664
-
665
- ### 3.4 Merchant Victory Guard (100% to Treasury)
666
-
667
- Checks if order progress current node is "Complete" AND order belongs to this service. If passed, merchant (Treasury) receives 100% of funds.
668
-
669
- **Prompt**: Create Guard "merchant_victory_guard".
670
-
671
- ```json
672
- {
673
- "tool": "onchain_operations",
674
- "data": {
675
- "operation_type": "guard",
676
- "data": {
677
- "namedNew": {
678
- "name": "merchant_victory_guard",
679
- "tags": ["merchant", "victory", "complete", "level3-scene-combined"],
680
- "replaceExistName": true
681
- },
682
- "description": "Guard for merchant victory: checks if order progress current node is Complete AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) — funds always flow to the Treasury regardless of caller (R-C3-06 safe). Two-fold verification: (1) order at Complete node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
683
- "table": [
684
- {
685
- "identifier": 0,
686
- "b_submission": true,
687
- "value_type": "Address",
688
- "name": "Order ID (submitted at runtime)"
689
- },
690
- {
691
- "identifier": 1,
692
- "b_submission": false,
693
- "value_type": "String",
694
- "value": "Complete",
695
- "name": "Complete node name"
696
- },
697
- {
698
- "identifier": 2,
699
- "b_submission": false,
700
- "value_type": "Address",
701
- "value": "travel_service",
702
- "name": "Service address (this service)"
703
- }
704
- ],
705
- "root": {
706
- "type": "logic_and",
707
- "nodes": [
708
- {
709
- "type": "logic_equal",
710
- "nodes": [
711
- {
712
- "type": "query",
713
- "query": "progress.current",
714
- "object": {"identifier": 0, "convert_witness": "OrderProgress"},
715
- "parameters": []
716
- },
717
- {"type": "identifier", "identifier": 1}
718
- ]
719
- },
720
- {
721
- "type": "logic_equal",
722
- "nodes": [
723
- {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
724
- {"type": "identifier", "identifier": 2}
725
- ]
726
- }
727
- ]
728
- }
729
- },
730
- "env": {
731
- "account": "travel_provider",
732
- "network": "testnet",
733
- "no_cache": true,
734
- "confirmed": true
735
- }
736
- }
737
- }
738
- ```
739
-
740
- **Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
741
- - **Table Item 0**: Order address (submitted at runtime)
742
- - **Table Item 1**: Constant string "Complete" (merchant win node name)
743
- - **Table Item 2**: Constant address `travel_service` (this service's on-chain address)
744
- - **Condition 1 — Complete Node**: `logic_equal[query(progress.current, witness="OrderProgress"), identifier[1]]` — verifies the order is at the Complete node
745
- - **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[2]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
746
- - **root**: `logic_and` of both conditions — all must pass for allocation to proceed
747
-
748
- > **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
749
- > - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
750
- > - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the allocator uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address). Funds go to a fixed recipient regardless of caller, so **no Signer binding is needed**. This is the Level 3 scene-combined pattern.
751
-
752
- ### 3.5 No Ice Scooting Guard (80% Treasury, 20% Refund)
753
-
754
- Checks if progress current is "Cancel" or "Ice Scooting" AND order belongs to this service. If passed, merchant (Treasury) gets 80%, user gets 20% refund.
755
-
756
- **Prompt**: Create Guard "no_ice_scooting_guard".
757
-
758
- ```json
759
- {
760
- "tool": "onchain_operations",
761
- "data": {
762
- "operation_type": "guard",
763
- "data": {
764
- "namedNew": {
765
- "name": "no_ice_scooting_guard",
766
- "tags": ["user", "cancel", "ice_scooting", "level3-scene-combined"],
767
- "replaceExistName": true
768
- },
769
- "description": "Guard for user not participating in ice scooting: checks if progress current is Cancel or Ice Scooting AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) for merchant portion and sharing.who=GuardIdentifier(0) for customer refund (escrow to Order address). Two-fold verification: (1) order at Cancel/Ice Scooting node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
770
- "table": [
771
- {
772
- "identifier": 0,
773
- "b_submission": true,
774
- "value_type": "Address",
775
- "name": "Order ID (submitted at runtime)"
776
- },
777
- {
778
- "identifier": 1,
779
- "b_submission": false,
780
- "value_type": "String",
781
- "value": "Cancel",
782
- "name": "Cancel node name"
783
- },
784
- {
785
- "identifier": 2,
786
- "b_submission": false,
787
- "value_type": "String",
788
- "value": "Ice Scooting",
789
- "name": "Ice Scooting node name"
790
- },
791
- {
792
- "identifier": 3,
793
- "b_submission": false,
794
- "value_type": "Address",
795
- "value": "travel_service",
796
- "name": "Service address (this service)"
797
- }
798
- ],
799
- "root": {
800
- "type": "logic_and",
801
- "nodes": [
802
- {
803
- "type": "logic_or",
804
- "nodes": [
805
- {
806
- "type": "logic_equal",
807
- "nodes": [
808
- {
809
- "type": "query",
810
- "query": "progress.current",
811
- "object": {"identifier": 0, "convert_witness": "OrderProgress"},
812
- "parameters": []
813
- },
814
- {"type": "identifier", "identifier": 1}
815
- ]
816
- },
817
- {
818
- "type": "logic_equal",
819
- "nodes": [
820
- {
821
- "type": "query",
822
- "query": "progress.current",
823
- "object": {"identifier": 0, "convert_witness": "OrderProgress"},
824
- "parameters": []
825
- },
826
- {"type": "identifier", "identifier": 2}
827
- ]
828
- }
829
- ]
830
- },
831
- {
832
- "type": "logic_equal",
833
- "nodes": [
834
- {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
835
- {"type": "identifier", "identifier": 3}
836
- ]
837
- }
838
- ]
839
- }
840
- },
841
- "env": {
842
- "account": "travel_provider",
843
- "network": "testnet",
844
- "no_cache": true,
845
- "confirmed": true
846
- }
847
- }
848
- }
849
- ```
850
-
851
- **Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
852
- - **Table Item 0**: Order address (submitted at runtime)
853
- - **Table Items 1-2**: Constant strings "Cancel" and "Ice Scooting" (node names)
854
- - **Table Item 3**: Constant address `travel_service` (this service's on-chain address)
855
- - **Condition 1 — Cancel/Ice Scooting Node**: `logic_or` of two `logic_equal` checks against `query(progress.current, witness="OrderProgress")` — verifies the order is at Cancel or Ice Scooting node
856
- - **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[3]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** (R-C3-05)
857
- - **root**: `logic_and` of both conditions — all must pass for allocation to proceed
858
-
859
- > **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
860
- > - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
861
- > - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the merchant portion uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address), and the customer refund uses `"who": {"GuardIdentifier": 0}` (funds flow to the Order object's address as escrow). Neither portion flows to the caller's wallet, so **no Signer binding is needed**.
862
-
863
- ### 3.6 No SPA Guard (5% Treasury, 95% Refund)
864
-
865
- Checks if progress current is "SPA" AND order belongs to this service. If passed, merchant (Treasury) gets 5%, user gets 95% refund.
866
-
867
- **Prompt**: Create Guard "no_spa_guard".
868
-
869
- ```json
870
- {
871
- "tool": "onchain_operations",
872
- "data": {
873
- "operation_type": "guard",
874
- "data": {
875
- "namedNew": {
876
- "name": "no_spa_guard",
877
- "tags": ["user", "cancel", "spa", "level3-scene-combined"],
878
- "replaceExistName": true
879
- },
880
- "description": "Guard for user not participating in SPA: checks if progress current is SPA AND order belongs to travel_service. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (travel_treasury) for merchant portion and sharing.who=GuardIdentifier(0) for customer refund (escrow to Order address). Two-fold verification: (1) order at SPA node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
881
- "table": [
882
- {
883
- "identifier": 0,
884
- "b_submission": true,
885
- "value_type": "Address",
886
- "name": "Order ID (submitted at runtime)"
887
- },
888
- {
889
- "identifier": 1,
890
- "b_submission": false,
891
- "value_type": "String",
892
- "value": "SPA",
893
- "name": "SPA node name"
894
- },
895
- {
896
- "identifier": 2,
897
- "b_submission": false,
898
- "value_type": "Address",
899
- "value": "travel_service",
900
- "name": "Service address (this service)"
901
- }
902
- ],
903
- "root": {
904
- "type": "logic_and",
905
- "nodes": [
906
- {
907
- "type": "logic_equal",
908
- "nodes": [
909
- {
910
- "type": "query",
911
- "query": "progress.current",
912
- "object": {"identifier": 0, "convert_witness": "OrderProgress"},
913
- "parameters": []
914
- },
915
- {"type": "identifier", "identifier": 1}
916
- ]
917
- },
918
- {
919
- "type": "logic_equal",
920
- "nodes": [
921
- {"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
922
- {"type": "identifier", "identifier": 2}
923
- ]
924
- }
925
- ]
926
- }
927
- },
928
- "env": {
929
- "account": "travel_provider",
930
- "network": "testnet",
931
- "no_cache": true,
932
- "confirmed": true
933
- }
934
- }
935
- }
936
- ```
937
-
938
- **Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
939
- - **Table Item 0**: Order address (submitted at runtime)
940
- - **Table Item 1**: Constant string "SPA" (node name)
941
- - **Table Item 2**: Constant address `travel_service` (this service's on-chain address)
942
- - **Condition 1 — SPA Node**: `logic_equal[query(progress.current, witness="OrderProgress"), identifier[1]]` — verifies the order is at the SPA node
943
- - **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[2]]` — verifies the submitted Order's `service` field equals `travel_service`, **preventing cross-service theft** (R-C3-05)
944
- - **root**: `logic_and` of both conditions — all must pass for allocation to proceed
945
-
946
- > **Risk Elimination (R-C3-05 + R-C3-06) — Level 3 Scene-Combined Design**:
947
- > - **R-C3-05 (Cross-service theft)**: Eliminated by the Service Ownership check (Condition 2). An attacker cannot submit another service's order because `order.service` won't match `travel_service`.
948
- > - **R-C3-06 (Fund theft via Signer)**: Eliminated by the scene itself — the merchant portion uses `"who": {"Entity": {"name_or_address": "travel_treasury"}}` (funds flow to the fixed Treasury address), and the customer refund uses `"who": {"GuardIdentifier": 0}` (funds flow to the Order object's address as escrow). Neither portion flows to the caller's wallet, so **no Signer binding is needed**.
949
-
950
- ---
951
-
952
- ## Step 4: Create and Publish Machine
953
-
954
- Create a Machine to define the travel service workflow with all nodes and forwards. The Machine must be published before it can be bound to a Service.
955
-
956
- > **Important**: In the Machine node structure, each node's `pairs` define how to ENTER that node. The `prev_node` specifies the source node, and `forwards` are the operation names used to advance from `prev_node` to this node.
957
-
958
- **Prompt**: Create and publish a Machine named "travel_machine" with the complete travel workflow.
959
-
960
- ```json
961
- {
962
- "tool": "onchain_operations",
963
- "data": {
964
- "operation_type": "machine",
965
- "data": {
966
- "object": {
967
- "name": "travel_machine",
968
- "permission": "travel_permission",
969
- "replaceExistName": true
970
- },
971
- "description": "Iceland travel service workflow: (init) -> Buy Insurance -> SPA -> Ice Scooting -> Complete/Cancel",
972
- "node": {
973
- "op": "add",
974
- "bReplace": true,
975
- "nodes": [
976
- {
977
- "name": "Buy Insurance",
978
- "pairs": [
979
- {
980
- "prev_node": "",
981
- "threshold": 1,
982
- "forwards": [
983
- {
984
- "name": "buy_insurance",
985
- "weight": 1,
986
- "permissionIndex": 1000
987
- }
988
- ]
989
- }
990
- ]
991
- },
992
- {
993
- "name": "SPA",
994
- "pairs": [
995
- {
996
- "prev_node": "Buy Insurance",
997
- "threshold": 1,
998
- "forwards": [
999
- {
1000
- "name": "go_spa",
1001
- "weight": 1,
1002
- "permissionIndex": 1001
1003
- }
1004
- ]
1005
- }
1006
- ]
1007
- },
1008
- {
1009
- "name": "Ice Scooting",
1010
- "pairs": [
1011
- {
1012
- "prev_node": "SPA",
1013
- "threshold": 1,
1014
- "forwards": [
1015
- {
1016
- "name": "go_ice_scooting",
1017
- "weight": 1,
1018
- "permissionIndex": 1004,
1019
- "guard": {
1020
- "guard": "weather_check_guard",
1021
- "retained_submission": []
1022
- }
1023
- }
1024
- ]
1025
- }
1026
- ]
1027
- },
1028
- {
1029
- "name": "Complete",
1030
- "pairs": [
1031
- {
1032
- "prev_node": "Ice Scooting",
1033
- "threshold": 1,
1034
- "forwards": [
1035
- {
1036
- "name": "complete_trip",
1037
- "weight": 1,
1038
- "permissionIndex": 1002,
1039
- "guard": {
1040
- "guard": "travel_complete_guard",
1041
- "retained_submission": []
1042
- }
1043
- }
1044
- ]
1045
- }
1046
- ]
1047
- },
1048
- {
1049
- "name": "Cancel",
1050
- "pairs": [
1051
- {
1052
- "prev_node": "Ice Scooting",
1053
- "threshold": 1,
1054
- "forwards": [
1055
- {
1056
- "name": "cancel_trip",
1057
- "weight": 1,
1058
- "permissionIndex": 1003,
1059
- "guard": {
1060
- "guard": "travel_cancel_guard",
1061
- "retained_submission": []
1062
- }
1063
- }
1064
- ]
1065
- }
1066
- ]
1067
- }
1068
- ]
1069
- },
1070
- "publish": true
1071
- },
1072
- "env": {
1073
- "account": "travel_provider",
1074
- "network": "testnet",
1075
- "no_cache": true,
1076
- "confirmed": true
1077
- }
1078
- }
1079
- }
1080
- ```
1081
-
1082
- **Machine Workflow Diagram**:
1083
-
1084
- ```
1085
- ("") --buy_insurance--> [Buy Insurance] --go_spa--> [SPA] --go_ice_scooting--[weather_check]--> [Ice Scooting]
1086
- |
1087
- +--complete_trip--[time-lock]--> [Complete]
1088
- +--cancel_trip-------------> [Cancel]
1089
- ```
1090
-
1091
- **Node Pair Structure**:
1092
-
1093
- | Node | prev_node | Forward | Permission Index | Guard |
1094
- |------|-----------|---------|-----------------|-------|
1095
- | Buy Insurance | "" (entry) | buy_insurance | 1000 | - |
1096
- | SPA | Buy Insurance | go_spa | 1001 | - |
1097
- | Ice Scooting | SPA | go_ice_scooting | 1004 | weather_check_guard |
1098
- | Complete | Ice Scooting | complete_trip | 1002 | travel_complete_guard |
1099
- | Cancel | Ice Scooting | cancel_trip | 1003 | travel_cancel_guard |
1100
-
1101
- > **Note**: The `prev_node` field uses an empty string `""` to denote the entry point. Each node defines how to enter it from a previous node. The `threshold` field (optional, defaults to `0`) specifies the minimum forward weight needed to trigger node advancement.
1102
-
1103
- ---
1104
-
1105
- ## Step 5: Configure and Publish Service
1106
-
1107
- Configure the travel service (created unpublished in Step 2.5) with all bindings and publish it. The Service requires:
1108
- - Machine binding (must be published first)
1109
- - Sales items (product listing)
1110
- - Arbitration binding
1111
- - Order allocators (fund distribution rules — merchant funds flow to `travel_treasury`)
1112
- - `pause: false` and `publish: true` to make it active
1113
-
1114
- **Prompt**: Configure and publish the Service named "travel_service".
1115
-
1116
- ```json
1117
- {
1118
- "tool": "onchain_operations",
1119
- "data": {
1120
- "operation_type": "service",
1121
- "data": {
1122
- "object": "travel_service",
1123
- "description": "Iceland travel service: Blue Lagoon SPA + Glacier Ice Scooting.",
1124
- "machine": "travel_machine",
1125
- "sales": {
1126
- "op": "add",
1127
- "sales": [
1128
- {
1129
- "name": "Iceland Travel Package",
1130
- "price": "500000000",
1131
- "stock": "99",
1132
- "suspension": false,
1133
- "wip": "",
1134
- "wip_hash": ""
1135
- }
1136
- ]
1137
- },
1138
- "arbitrations": {
1139
- "op": "add",
1140
- "objects": ["travel_arbitration"]
1141
- },
1142
- "order_allocators": {
1143
- "description": "Travel order revenue allocation based on progress state",
1144
- "threshold": 0,
1145
- "allocators": [
1146
- {
1147
- "guard": "merchant_victory_guard",
1148
- "sharing": [
1149
- {
1150
- "who": {"Entity": {"name_or_address": "travel_treasury"}},
1151
- "sharing": 10000,
1152
- "mode": "Rate"
1153
- }
1154
- ]
1155
- },
1156
- {
1157
- "guard": "no_ice_scooting_guard",
1158
- "sharing": [
1159
- {
1160
- "who": {"Entity": {"name_or_address": "travel_treasury"}},
1161
- "sharing": 8000,
1162
- "mode": "Rate"
1163
- },
1164
- {
1165
- "who": {"GuardIdentifier": 0},
1166
- "sharing": 2000,
1167
- "mode": "Rate"
1168
- }
1169
- ]
1170
- },
1171
- {
1172
- "guard": "no_spa_guard",
1173
- "sharing": [
1174
- {
1175
- "who": {"Entity": {"name_or_address": "travel_treasury"}},
1176
- "sharing": 500,
1177
- "mode": "Rate"
1178
- },
1179
- {
1180
- "who": {"GuardIdentifier": 0},
1181
- "sharing": 9500,
1182
- "mode": "Rate"
1183
- }
1184
- ]
1185
- }
1186
- ]
1187
- },
1188
- "pause": false,
1189
- "publish": true
1190
- },
1191
- "env": {
1192
- "account": "travel_provider",
1193
- "network": "testnet",
1194
- "no_cache": true,
1195
- "confirmed": true
1196
- }
1197
- }
1198
- }
1199
- ```
1200
-
1201
- > **Note**: `object` uses a plain string reference (`"travel_service"`) so this call **configures the draft Service created in Step 2.5**. Passing a full object definition block (`{name, permission, replaceExistName}`) here would create a brand-new Service object instead — orders and allocator Guard bindings pointing at the old draft would then fail validation.
1202
-
1203
- **order_allocators Field Reference**:
1204
-
1205
- | Field | Type | Description |
1206
- |-------|------|-------------|
1207
- | `description` | string | Description of the allocation strategy |
1208
- | `threshold` | number | Minimum threshold for allocation (0 = no minimum) |
1209
- | `allocators` | array | Array of allocator configurations |
1210
- | `allocators[].guard` | string | Guard name/ID that must pass for this allocation |
1211
- | `allocators[].fix` | string | Fixed amount per recipient ("0" = none) |
1212
- | `allocators[].sharing` | array | Array of sharing rules |
1213
- | `allocators[].sharing[].who` | object | Recipient: `{"Entity": {...}}` for fixed address, `{"GuardIdentifier": N}` for Guard table index, `{"Signer": "signer"}` for caller |
1214
- | `allocators[].sharing[].sharing` | number | Amount in basis points (10000 = 100%) |
1215
- | `allocators[].sharing[].mode` | string | Allocation mode ("Rate" or "Amount") |
1216
-
1217
- **Recipient Types**:
1218
-
1219
- | Type | Syntax | Resolves To | Use Case |
1220
- |------|--------|-------------|----------|
1221
- | `Entity` | `{"Entity": {"name_or_address": "travel_treasury"}}` | The named Treasury address | Merchant receipts (Treasury object — Treasury-first rule) |
1222
- | `GuardIdentifier` | `{"GuardIdentifier": 0}` | Address from Guard table index 0 (submitted at runtime) | Customer refunds (Order ID submitted to Guard) |
1223
- | `Signer` | `{"Signer": "signer"}` | The caller of `alloc_by_guard` | When caller should receive all funds (**⚠️ R-C3-06 Risk**: unsafe without Guard Signer binding) |
1224
-
1225
- > **Important**: All allocation Guards (merchant_victory_guard, no_ice_scooting_guard, no_spa_guard) have `identifier: 0` as a submission field accepting the Order ID at runtime. `{"GuardIdentifier": 0}` resolves to this submitted Order ID, so funds are sent to the Order object — the customer (Order builder) can then withdraw.
1226
-
1227
- > **Treasury-First Rule**: Merchant funds flow to `travel_treasury` (not `travel_service`) following the fund-flow design pattern. This makes all allocators inherently safe (R-C3-06) — funds go to a fixed Treasury regardless of caller, so no Signer binding is needed in the Guards. Combined with the R-C3-05 service ownership check in each Guard, the allocators are protected against both cross-service theft and fund theft via Signer.
1228
-
1229
- **Allocation Logic**:
1230
-
1231
- | Guard | Condition | Treasury Receives | Customer Receives | Verifier Level |
1232
- |-------|-----------|-------------------|-------------------|----------------|
1233
- | merchant_victory_guard | Progress is "Complete" + order.service verified | 100% (Entity → travel_treasury) | 0% | Level 3 (scene-combined) |
1234
- | no_ice_scooting_guard | Progress is "Cancel" or "Ice Scooting" + order.service verified | 80% (Entity → travel_treasury) | 20% (GuardIdentifier: 0 → Order) | Level 3 (scene-combined) |
1235
- | no_spa_guard | Progress is "SPA" + order.service verified | 5% (Entity → travel_treasury) | 95% (GuardIdentifier: 0 → Order) | Level 3 (scene-combined) |
1236
-
1237
- ---
1238
-
1239
- ## Step 6: Place Order (Customer Purchase)
1240
-
1241
- The customer (Alice) purchases the travel package. This creates an Order, a Progress (initialized at the entry node ""), and an Allocation object automatically.
1242
-
1243
- **Prompt**: Alice purchases the Iceland Travel Package from the service.
1244
-
1245
- ```json
1246
- {
1247
- "tool": "onchain_operations",
1248
- "data": {
1249
- "operation_type": "service",
1250
- "data": {
1251
- "object": "travel_service",
1252
- "order_new": {
1253
- "buy": {
1254
- "items": [
1255
- {
1256
- "name": "Iceland Travel Package",
1257
- "stock": "1",
1258
- "wip_hash": ""
1259
- }
1260
- ],
1261
- "total_pay": {"balance": "500000000"}
1262
- },
1263
- "namedNewOrder": {
1264
- "name": "alice_travel_order",
1265
- "replaceExistName": true
1266
- },
1267
- "namedNewProgress": {
1268
- "name": "alice_travel_progress",
1269
- "replaceExistName": true
1270
- },
1271
- "namedNewAllocation": {
1272
- "name": "alice_travel_allocation",
1273
- "replaceExistName": true
1274
- }
1275
- }
1276
- },
1277
- "env": {
1278
- "account": "alice",
1279
- "network": "testnet",
1280
- "no_cache": true,
1281
- "confirmed": true
1282
- }
1283
- }
1284
- }
1285
- ```
1286
-
1287
- > **Note**: The `total_pay.balance` of `500000000` equals 0.5 WOW (1 WOW = 10^9 base units). The customer account must have sufficient balance. The operation creates three named objects: Order, Progress, and Allocation.
1288
-
1289
- ---
1290
-
1291
- ## Step 7: Progress Operations (Order Workflow)
1292
-
1293
- The service provider advances the Progress through the workflow nodes. Each operation moves the Progress from the current node to the next node via a specified forward.
1294
-
1295
- > **Important**: Add `"no_cache": true` to the `env` field for all Progress operations to avoid stale cache issues.
1296
-
1297
- ### 7.1 Progress to Buy Insurance
1298
-
1299
- Move from initial node ("") to "Buy Insurance" node.
1300
-
1301
- **Prompt**: Operate progress to move to Buy Insurance node.
1302
-
1303
- ```json
1304
- {
1305
- "tool": "onchain_operations",
1306
- "data": {
1307
- "operation_type": "progress",
1308
- "data": {
1309
- "object": "alice_travel_progress",
1310
- "operate": {
1311
- "operation": {
1312
- "next_node_name": "Buy Insurance",
1313
- "forward": "buy_insurance"
1314
- },
1315
- "op": "next"
1316
- }
1317
- },
1318
- "env": {
1319
- "account": "travel_provider",
1320
- "network": "testnet",
1321
- "no_cache": true
1322
- }
1323
- }
1324
- }
1325
- ```
1326
-
1327
- ### 7.2 Progress to SPA
1328
-
1329
- Move from "Buy Insurance" to "SPA" node.
1330
-
1331
- **Prompt**: Operate progress to move to SPA node.
1332
-
1333
- ```json
1334
- {
1335
- "tool": "onchain_operations",
1336
- "data": {
1337
- "operation_type": "progress",
1338
- "data": {
1339
- "object": "alice_travel_progress",
1340
- "operate": {
1341
- "operation": {
1342
- "next_node_name": "SPA",
1343
- "forward": "go_spa"
1344
- },
1345
- "op": "next"
1346
- }
1347
- },
1348
- "env": {
1349
- "account": "travel_provider",
1350
- "network": "testnet",
1351
- "no_cache": true
1352
- }
1353
- }
1354
- }
1355
- ```
1356
-
1357
- ### 7.3 Progress to Ice Scooting (with Weather Guard Submission)
1358
-
1359
- Move from "SPA" to "Ice Scooting" node. This forward has a Guard (`weather_check_guard`) that verifies weather data exists in the repository for the activity date. You must submit the activity date timestamp (one of the sunny-day timestamps from Step 0.1) at runtime.
1360
-
1361
- **Prompt**: Operate progress to move to Ice Scooting node with weather Guard submission.
1362
-
1363
- ```json
1364
- {
1365
- "tool": "onchain_operations",
1366
- "data": {
1367
- "operation_type": "progress",
1368
- "data": {
1369
- "object": "alice_travel_progress",
1370
- "operate": {
1371
- "operation": {
1372
- "next_node_name": "Ice Scooting",
1373
- "forward": "go_ice_scooting"
1374
- },
1375
- "op": "next"
1376
- }
1377
- },
1378
- "submission": {
1379
- "type": "submission",
1380
- "guard": [
1381
- {
1382
- "object": "weather_check_guard",
1383
- "impack": true
1384
- }
1385
- ],
1386
- "submission": [
1387
- {
1388
- "guard": "weather_check_guard",
1389
- "submission": [
1390
- {
1391
- "identifier": 2,
1392
- "b_submission": true,
1393
- "value_type": "U64",
1394
- "value": <ACTIVITY_DATE_TIMESTAMP>,
1395
- "name": "Activity date timestamp"
1396
- }
1397
- ]
1398
- }
1399
- ]
1400
- },
1401
- "env": {
1402
- "account": "travel_provider",
1403
- "network": "testnet",
1404
- "no_cache": true
1405
- }
1406
- }
1407
- }
1408
- ```
1409
-
1410
- > **Note**: Replace `<ACTIVITY_DATE_TIMESTAMP>` with one of the sunny-day timestamps from Step 0.1 (e.g., `1783555200000` for Day 1). The timestamp **must exactly match** the `id` used when adding weather data to the repository in Step 0.4 — Repository data is keyed by timestamp, and the Guard queries `repository.data has("Condition", convert_number_address(activity_date))`.
1411
- >
1412
- > **Key**: Only `identifier: 2` (the activity date) is submitted at runtime. Identifiers 0 (weather_repo) and 1 ("Condition") are fixed in the Guard table and do not need to be submitted. The `submission` field is at the **top level** of the input (alongside `data` and `env`), NOT inside `data`.
1413
-
1414
- ### 7.4 Complete Trip (with Guard Submission)
1415
-
1416
- Move from "Ice Scooting" to "Complete" node. This forward has a Guard (`travel_complete_guard`) that requires the Order ID to be submitted for time-lock verification.
1417
-
1418
- **Prompt**: Operate progress to complete the trip with Guard submission.
1419
-
1420
- ```json
1421
- {
1422
- "tool": "onchain_operations",
1423
- "data": {
1424
- "operation_type": "progress",
1425
- "data": {
1426
- "object": "alice_travel_progress",
1427
- "operate": {
1428
- "operation": {
1429
- "next_node_name": "Complete",
1430
- "forward": "complete_trip"
1431
- },
1432
- "op": "next"
1433
- }
1434
- },
1435
- "submission": {
1436
- "type": "submission",
1437
- "guard": [
1438
- {
1439
- "object": "travel_complete_guard",
1440
- "impack": true
1441
- }
1442
- ],
1443
- "submission": [
1444
- {
1445
- "guard": "travel_complete_guard",
1446
- "submission": [
1447
- {
1448
- "identifier": 0,
1449
- "b_submission": true,
1450
- "value_type": "Address",
1451
- "value": "<ORDER_OBJECT_ID>",
1452
- "name": "Order ID"
1453
- }
1454
- ]
1455
- }
1456
- ]
1457
- },
1458
- "env": {
1459
- "account": "travel_provider",
1460
- "network": "testnet",
1461
- "no_cache": true
1462
- }
1463
- }
1464
- }
1465
- ```
1466
-
1467
- > **Note**: Replace `<ORDER_OBJECT_ID>` with the actual Order object ID (a 64-hex-character string starting with `0x`). You can query the Progress object to find the `task` field which contains the Order ID.
1468
- >
1469
- > **Key**: The `submission` field is at the **top level** of the input (alongside `data` and `env`), NOT inside `data`. The `impack: true` means the Guard verification result affects the final outcome.
1470
-
1471
- ### 7.5 Cancel Trip (Alternative Path)
1472
-
1473
- > **Note**: This is an **alternative** to Step 7.4. Once the trip is Completed, it cannot be Cancelled (and vice versa). Use this path only if cancelling from the "Ice Scooting" node.
1474
-
1475
- **Prompt**: Operate progress to cancel the trip with Guard submission.
1476
-
1477
- ```json
1478
- {
1479
- "tool": "onchain_operations",
1480
- "data": {
1481
- "operation_type": "progress",
1482
- "data": {
1483
- "object": "alice_travel_progress",
1484
- "operate": {
1485
- "operation": {
1486
- "next_node_name": "Cancel",
1487
- "forward": "cancel_trip"
1488
- },
1489
- "op": "next"
1490
- }
1491
- },
1492
- "submission": {
1493
- "type": "submission",
1494
- "guard": [
1495
- {
1496
- "object": "travel_cancel_guard",
1497
- "impack": true
1498
- }
1499
- ],
1500
- "submission": [
1501
- {
1502
- "guard": "travel_cancel_guard",
1503
- "submission": []
1504
- }
1505
- ]
1506
- },
1507
- "env": {
1508
- "account": "travel_provider",
1509
- "network": "testnet",
1510
- "no_cache": true
1511
- }
1512
- }
1513
- }
1514
- ```
1515
-
1516
- > **Note**: The `travel_cancel_guard` always passes (returns true), so no submission data is needed. The empty `submission: []` is sufficient.
1517
-
1518
- **Progress Operation Structure**:
1519
-
1520
- | Field | Type | Description |
1521
- |-------|------|-------------|
1522
- | `data.object` | string | Progress object name/ID |
1523
- | `data.operate.operation.next_node_name` | string | Target node name to move to |
1524
- | `data.operate.operation.forward` | string | Forward name defined in Machine |
1525
- | `data.operate.op` | string | **Required.** Operation type: `"next"` (advance the forward), `"hold"`, `"unhold"`, or `"adminUnhold"` |
1526
- | `submission` | object | Guard verification data (top-level, required when forward has Guard) |
1527
- | `env.no_cache` | boolean | Set to `true` to avoid stale cache issues |
1528
-
1529
- ---
1530
-
1531
- ## Step 8: Execute Fund Allocation
1532
-
1533
- After the Progress reaches a terminal state (Complete or Cancel), execute the fund allocation. This operation verifies the allocation Guard and distributes funds according to the `order_allocators` configured in Step 5.
1534
-
1535
- **Anyone can call this operation** — the caller does not need to be the merchant or the customer. The Guard verification determines which allocator's sharing rules apply, and funds are distributed to the recipients defined in those rules.
1536
-
1537
- ### 8.1 Query the Order ID
1538
-
1539
- The allocation Guard requires the Order ID as a submission (identifier: 0). Query the Progress object to find the `task` field, which contains the Order ID.
1540
-
1541
- **Prompt**: Query the Progress object to get the Order ID.
1542
-
1543
- ```json
1544
- {
1545
- "tool": "query_toolkit",
1546
- "data": {
1547
- "query_type": "onchain_objects",
1548
- "objects": ["alice_travel_progress"],
1549
- "network": "testnet",
1550
- "no_cache": true
1551
- }
1552
- }
1553
- ```
1554
-
1555
- > **Note**: Use `query_toolkit` (not `onchain_operations`) for read-only lookups — queries consume no gas and never mutate state. The response includes a `task` field containing the Order object ID. Copy this value for the allocation submission.
1556
-
1557
- ### 8.2 Execute Allocation (Merchant Victory Path)
1558
-
1559
- When the Progress is "Complete", the `merchant_victory_guard` passes, and 100% of funds go to the Treasury (`travel_treasury`).
1560
-
1561
- **Prompt**: Execute fund allocation with the merchant_victory_guard, submitting the Order ID.
1562
-
1563
- ```json
1564
- {
1565
- "tool": "onchain_operations",
1566
- "data": {
1567
- "operation_type": "allocation",
1568
- "data": {
1569
- "object": "alice_travel_allocation",
1570
- "alloc_by_guard": "merchant_victory_guard"
1571
- },
1572
- "submission": {
1573
- "type": "submission",
1574
- "guard": [
1575
- {
1576
- "object": "merchant_victory_guard",
1577
- "impack": true
1578
- }
1579
- ],
1580
- "submission": [
1581
- {
1582
- "guard": "merchant_victory_guard",
1583
- "submission": [
1584
- {
1585
- "identifier": 0,
1586
- "b_submission": true,
1587
- "value_type": "Address",
1588
- "value": "<ORDER_OBJECT_ID>",
1589
- "name": "Order ID"
1590
- }
1591
- ]
1592
- }
1593
- ]
1594
- },
1595
- "env": {
1596
- "account": "travel_provider",
1597
- "network": "testnet",
1598
- "no_cache": true
1599
- }
1600
- }
1601
- }
1602
- ```
1603
-
1604
- > **Note**: Replace `<ORDER_OBJECT_ID>` with the actual Order object ID from Step 8.1.
1605
- >
1606
- > **Two-phase submission**: If the first call returns a submission prompt (without executing), re-call with the `submission` field populated as shown above.
1607
-
1608
- ### 8.3 Execute Allocation (Refund Paths)
1609
-
1610
- For refund scenarios (Cancel or SPA), use the corresponding Guard. The same submission structure applies — the Order ID is submitted to identifier 0.
1611
-
1612
- **Cancel/Ice Scooting path** (80% Treasury, 20% Order (escrow, claimable by the order owner)):
1613
-
1614
- ```json
1615
- {
1616
- "tool": "onchain_operations",
1617
- "data": {
1618
- "operation_type": "allocation",
1619
- "data": {
1620
- "object": "alice_travel_allocation",
1621
- "alloc_by_guard": "no_ice_scooting_guard"
1622
- },
1623
- "submission": {
1624
- "type": "submission",
1625
- "guard": [{"object": "no_ice_scooting_guard", "impack": true}],
1626
- "submission": [{
1627
- "guard": "no_ice_scooting_guard",
1628
- "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "<ORDER_OBJECT_ID>", "name": "Order ID"}]
1629
- }]
1630
- },
1631
- "env": {"account": "travel_provider", "network": "testnet", "no_cache": true, "confirmed": true}
1632
- }
1633
- }
1634
- ```
1635
-
1636
- **SPA path** (5% Treasury, 95% Order (escrow, claimable by the order owner)):
1637
-
1638
- ```json
1639
- {
1640
- "tool": "onchain_operations",
1641
- "data": {
1642
- "operation_type": "allocation",
1643
- "data": {
1644
- "object": "alice_travel_allocation",
1645
- "alloc_by_guard": "no_spa_guard"
1646
- },
1647
- "submission": {
1648
- "type": "submission",
1649
- "guard": [{"object": "no_spa_guard", "impack": true}],
1650
- "submission": [{
1651
- "guard": "no_spa_guard",
1652
- "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "<ORDER_OBJECT_ID>", "name": "Order ID"}]
1653
- }]
1654
- },
1655
- "env": {"account": "travel_provider", "network": "testnet", "no_cache": true, "confirmed": true}
1656
- }
1657
- }
1658
- ```
1659
-
1660
- ### 8.4 Verify Allocation Result
1661
-
1662
- After allocation, query the Allocation and Payment objects to verify the fund distribution.
1663
-
1664
- **Prompt**: Query the Allocation object to verify the balance and payment records.
1665
-
1666
- ```json
1667
- {
1668
- "tool": "query_toolkit",
1669
- "data": {
1670
- "query_type": "onchain_objects",
1671
- "objects": ["alice_travel_allocation"],
1672
- "network": "testnet",
1673
- "no_cache": true
1674
- }
1675
- }
1676
- ```
1677
-
1678
- > **Expected result**: The Allocation `balance` should be 0 (all funds distributed), and the `payment` array should contain the Payment object ID(s) created by the allocation.
1679
-
1680
- **Allocation Operation Structure**:
1681
-
1682
- | Field | Type | Description |
1683
- |-------|------|-------------|
1684
- | `data.object` | string | Allocation object name/ID |
1685
- | `data.alloc_by_guard` | string | Guard name/ID to verify (determines which allocator's rules apply) |
1686
- | `submission` | object | Guard submission data (Order ID at identifier 0) |
1687
- | `env.no_cache` | boolean | Set to `true` to avoid stale cache issues |
1688
-
1689
- > **Important**: `alloc_by_guard` accepts Guard names (e.g., `"merchant_victory_guard"`) or Guard object IDs. The Guard must exist in the Allocation's `allocators` list. Only the first Guard that passes (first-Guard-wins) triggers fund distribution.
1690
-
1691
- ### 8.5 Claim Allocated Funds (Unwrap CoinWrapper)
1692
-
1693
- Allocation does not deposit spendable coins directly. `alloc_by_guard` distributes **CoinWrapper objects** to each recipient address — these must be claimed/unwrapped before the funds are spendable:
1694
-
1695
- - **Treasury share** (`Entity` → `travel_treasury`): the CoinWrapper is sent to the Treasury object address. The travel provider deposits it into the Treasury balance via the Treasury `receive` operation.
1696
- - **Customer share** (`GuardIdentifier: 0` → the Order object address submitted at runtime, i.e. escrow): the CoinWrapper is sent to the Order object address. The order owner (Alice) claims it via the Order `receive` operation, which unwraps it and transfers the coins to her wallet.
1697
-
1698
- **Prompt**: Alice claims the customer share escrowed to the Order (refund paths only).
1699
-
1700
- ```json
1701
- {
1702
- "tool": "onchain_operations",
1703
- "data": {
1704
- "operation_type": "order",
1705
- "data": {
1706
- "object": "alice_travel_order",
1707
- "receive": "recently"
1708
- },
1709
- "env": {
1710
- "account": "alice",
1711
- "network": "testnet",
1712
- "no_cache": true,
1713
- "confirmed": true
1714
- }
1715
- }
1716
- }
1717
- ```
1718
-
1719
- **Prompt**: The travel provider deposits the Treasury's share into the Treasury balance.
1720
-
1721
- ```json
1722
- {
1723
- "tool": "onchain_operations",
1724
- "data": {
1725
- "operation_type": "treasury",
1726
- "data": {
1727
- "object": "travel_treasury",
1728
- "receive": "recently"
1729
- },
1730
- "env": {
1731
- "account": "travel_provider",
1732
- "network": "testnet",
1733
- "no_cache": true,
1734
- "confirmed": true
1735
- }
1736
- }
1737
- }
1738
- ```
1739
-
1740
- > **Note**: `"receive": "recently"` auto-queries and claims all recently received CoinWrapper objects. For the Order, `receive` unwraps them and transfers the coins to the order owner (Alice); for the Treasury, `receive` deposits the unwrapped coins into the Treasury's balance. In the merchant-victory path (100% to Treasury) only the Treasury claim is needed; the Order claim applies only to refund paths (8.3) where the customer has a share.
1741
-
1742
- ---
1743
-
1744
- ## Best Practices
1745
-
1746
- ### 1. Guard Root Format
1747
-
1748
- Guards use a direct GuardNode as the `root` field — no wrapper needed:
1749
- ```json
1750
- "root": {
1751
- "type": "logic_equal",
1752
- "nodes": [...]
1753
- }
1754
- ```
1755
-
1756
- ### 2. Machine Node Structure
1757
-
1758
- Each node's `pairs` define how to **enter** that node. The `prev_node` specifies the source, and `forwards` are the operations to advance:
1759
- ```json
1760
- {
1761
- "name": "TargetNode",
1762
- "pairs": [{
1763
- "prev_node": "SourceNode",
1764
- "threshold": 1,
1765
- "forwards": [{"name": "forward_name", "weight": 1, "permissionIndex": 1000}]
1766
- }]
1767
- }
1768
- ```
1769
-
1770
- - Use `prev_node` (not `prior_node`)
1771
- - `threshold` is required for every pair
1772
- - Consolidate forwards with the same `prev_node` into one pair
1773
-
1774
- ### 3. Machine Publish Before Service
1775
-
1776
- The Machine must be published (`"publish": true`) before binding it to a Service. Unpublished Machines cannot be referenced by Services.
1777
-
1778
- ### 4. Service Creation in One Step
1779
-
1780
- Create the Service with all configurations — including `pause: false` and `publish: true` — in a single operation:
1781
- ```json
1782
- {
1783
- "pause": false,
1784
- "publish": true,
1785
- "order_allocators": {...},
1786
- "sales": {...},
1787
- "machine": "...",
1788
- "arbitrations": {...}
1789
- }
1790
- ```
1791
-
1792
- ### 5. Guard Submission for Progress
1793
-
1794
- When a forward has a Guard, the Progress operation requires a `submission` field at the **top level** (not inside `data`):
1795
- ```json
1796
- {
1797
- "tool": "onchain_operations",
1798
- "data": {
1799
- "operation_type": "progress",
1800
- "data": {...},
1801
- "submission": {
1802
- "type": "submission",
1803
- "guard": [{"object": "guard_name", "impack": true}],
1804
- "submission": [{
1805
- "guard": "guard_name",
1806
- "submission": [{"identifier": 0, "b_submission": true, "value_type": "Address", "value": "0x...", "name": "Order ID"}]
1807
- }]
1808
- },
1809
- "env": {"no_cache": true, ...}
1810
- }
1811
- }
1812
- ```
1813
-
1814
- ### 6. Cache Management
1815
-
1816
- Add `"no_cache": true` to the `env` field for all Progress operations and queries after mutations to avoid stale cache issues.
1817
-
1818
- ### 7. Weather Data Timestamps
1819
-
1820
- Weather data in the Repository is keyed by timestamp (`id`). The `weather_check_guard` queries `repository.data has("Condition", convert_number_address(activity_date))` — the `activity_date` submitted at runtime in Step 7.3 **must exactly match** the `id` used when adding data in Step 0.4.
1821
-
1822
- - Always align timestamps to UTC 00:00:00 (`Math.floor(now / DAY_MS) * DAY_MS`) so they are reproducible.
1823
- - Re-run `calc-weather-timestamps.js` at test time — the values depend on the current date.
1824
- - The Guard only checks data **existence**, not the condition value. A "rainy" day will still pass. To reject by condition value, use a Guard querying `repository.data` with a value comparison.
1825
-
1826
- ### 8. Order Placement
1827
-
1828
- Customers place orders using the `order_new` field in the Service operation. This automatically creates Order, Progress, and Allocation objects:
1829
- ```json
1830
- {
1831
- "tool": "onchain_operations",
1832
- "data": {
1833
- "operation_type": "service",
1834
- "data": {
1835
- "object": "service_name",
1836
- "order_new": {
1837
- "buy": {
1838
- "items": [{"name": "Product", "stock": "1", "wip_hash": ""}],
1839
- "total_pay": {"balance": "price_amount"}
1840
- },
1841
- "namedNewOrder": {"name": "order_name", "replaceExistName": true},
1842
- "namedNewProgress": {"name": "progress_name", "replaceExistName": true},
1843
- "namedNewAllocation": {"name": "allocation_name", "replaceExistName": true}
1844
- }
1845
- },
1846
- "env": {"account": "customer", "network": "testnet", "no_cache": true, "confirmed": true}
1847
- }
1848
- }
1849
- ```