@wowok/skills 1.1.12 → 1.1.13

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.
@@ -23,10 +23,44 @@ This example demonstrates:
23
23
 
24
24
  Before running this example, ensure you have:
25
25
 
26
- 1. **Account Setup**: The `three_body_author` account with sufficient WOW tokens
26
+ 1. **Account Setup**: The `three_body_author` and `three_body_customer` accounts with sufficient WOW tokens
27
27
  2. **Minimum Balance**: At least 1000 WOW for gas fees and service creation
28
28
 
29
- ### Check Account Balance
29
+ ### Step 0a: Generate Accounts
30
+
31
+ If the accounts do not exist locally, generate them first.
32
+
33
+ **Request (generate author account)**:
34
+ ```json
35
+ {
36
+ "gen": {
37
+ "name": "three_body_author",
38
+ "replaceExistName": true
39
+ }
40
+ }
41
+ ```
42
+
43
+ **Request (generate customer account)**:
44
+ ```json
45
+ {
46
+ "gen": {
47
+ "name": "three_body_customer",
48
+ "replaceExistName": true
49
+ }
50
+ }
51
+ ```
52
+
53
+ **Expected Result**:
54
+ ```json
55
+ {
56
+ "gen": {
57
+ "address": "0x...",
58
+ "name": "three_body_author"
59
+ }
60
+ }
61
+ ```
62
+
63
+ ### Step 0b: Check Account Balance
30
64
 
31
65
  **Request**:
32
66
  ```json
@@ -41,15 +75,24 @@ Before running this example, ensure you have:
41
75
  **Expected Result** (if account has balance):
42
76
  ```json
43
77
  {
44
- "address": "0x...",
45
- "balance": {
46
- "coinType": "0x2::wow::WOW",
47
- "totalBalance": "1000000000"
78
+ "result": {
79
+ "query_type": "account_balance",
80
+ "result": {
81
+ "address": "0x...",
82
+ "name_or_address": "three_body_author",
83
+ "balance": {
84
+ "coinType": "0x2::wow::WOW",
85
+ "coinObjectCount": 3,
86
+ "totalBalance": "3000000000",
87
+ "lockedBalance": {},
88
+ "fundsInAddressBalance": "0"
89
+ }
90
+ }
48
91
  }
49
92
  }
50
93
  ```
51
94
 
52
- **If no balance, use Faucet**:
95
+ ### Step 0c: Fund Accounts via Faucet (If No Balance)
53
96
 
54
97
  **Request**:
55
98
  ```json
@@ -67,15 +110,31 @@ Before running this example, ensure you have:
67
110
  "faucet": {
68
111
  "name_or_address": "three_body_author",
69
112
  "result": [
70
- {"amount": 1000000000, "id": "0x..."},
71
- {"amount": 1000000000, "id": "0x..."},
72
- {"amount": 1000000000, "id": "0x..."}
113
+ {
114
+ "amount": 1000000000,
115
+ "id": "0x...",
116
+ "transferTxDigest": "..."
117
+ },
118
+ {
119
+ "amount": 1000000000,
120
+ "id": "0x...",
121
+ "transferTxDigest": "..."
122
+ },
123
+ {
124
+ "amount": 1000000000,
125
+ "id": "0x...",
126
+ "transferTxDigest": "..."
127
+ }
73
128
  ],
74
129
  "network": "testnet"
75
130
  }
76
131
  }
77
132
  ```
78
133
 
134
+ > **Note**: Each faucet result item includes a `transferTxDigest` field representing the on-chain transaction digest for the faucet transfer. This is useful for tracking and verifying the faucet transaction on a block explorer.
135
+
136
+ > **Important**: Repeat the faucet request for `three_body_customer` as well, since Test 2 requires a funded non-author account to attempt the blocked purchase.
137
+
79
138
  ---
80
139
 
81
140
  ## Step 1: Create Permission Object
@@ -100,19 +159,40 @@ Create a Permission object to manage the service.
100
159
  },
101
160
  "env": {
102
161
  "account": "three_body_author",
103
- "network": "testnet"
162
+ "network": "testnet",
163
+ "confirmed": true
104
164
  }
105
165
  }
106
166
  ```
107
167
 
168
+ > **Permission Index Explanation**:
169
+ > - **`1000`–`1009`**: User-defined permission indexes (starting from `USER_DEFINED_PERM_INDEX_START = 1000`). In this example, `1000` is used for the "Confirm Delivery" forward and `1001` for the "Complete Signature" forward in the Machine workflow (see Step 3). The remaining indexes (`1002`–`1009`) are reserved for future workflow extensions.
170
+ > - **`306`**: The built-in `SERVICE_MACHINE` permission (Service module permission index `306`), which authorizes binding a Machine to a Service. This is required in Step 5 (Configure Machine) where the Machine is bound to the Service.
171
+ >
172
+ > See `BuiltinPermissionIndex` in `ts-sdk/packages/wowok/src/w/call/permission.ts` for the full list of built-in permission indexes.
173
+
174
+ > **Important**: `env.confirmed: true` is required because `replaceExistName: true` triggers a confirmation prompt (it unbinds any existing name). Without `confirmed: true`, the operation will be blocked pending user confirmation. This applies to all subsequent steps using `replaceExistName: true` or `publish: true`.
175
+
108
176
  **Expected Result**:
109
177
  ```json
110
- [{
111
- "type": "Permission",
112
- "object": "0x...",
113
- "version": "...",
114
- "change": "created"
115
- }]
178
+ [
179
+ {
180
+ "type": "Permission",
181
+ "type_raw": "0x2::permission::Permission",
182
+ "object": "0x...",
183
+ "version": "...",
184
+ "owner": {"Shared": {"initial_shared_version": "..."}},
185
+ "change": "created"
186
+ },
187
+ {
188
+ "type": "TableItem_PermissionPerm",
189
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::parent_linked_table::Node<address, vector<u16>>>",
190
+ "object": "0x...",
191
+ "version": "...",
192
+ "owner": {"ObjectOwner": "0x..."},
193
+ "change": "created"
194
+ }
195
+ ]
116
196
  ```
117
197
 
118
198
  ---
@@ -157,21 +237,28 @@ Create a Guard that verifies the buyer is the service creator (author). This ens
157
237
  },
158
238
  "env": {
159
239
  "account": "three_body_author",
160
- "network": "testnet"
240
+ "network": "testnet",
241
+ "confirmed": true
161
242
  }
162
243
  }
163
244
  ```
164
245
 
165
246
  > **Note**: The Guard uses a `table` to define constant values with identifiers, then references them in the `root` logic using `identifier` node type. The `root` is a direct GuardNode (no wrapper).
166
247
 
248
+ > **Important**: `env.confirmed: true` is required because `replaceExistName: true` triggers a confirmation prompt.
249
+
167
250
  **Expected Result**:
168
251
  ```json
169
- [{
170
- "type": "Guard",
171
- "object": "0x...",
172
- "version": "...",
173
- "change": "created"
174
- }]
252
+ [
253
+ {
254
+ "type": "Guard",
255
+ "type_raw": "0x2::guard::Guard",
256
+ "object": "0x...",
257
+ "version": "...",
258
+ "owner": "Immutable",
259
+ "change": "created"
260
+ }
261
+ ]
175
262
  ```
176
263
 
177
264
  ---
@@ -234,19 +321,50 @@ Create a Machine to define the service workflow: Book Delivery → Signature Com
234
321
  },
235
322
  "env": {
236
323
  "account": "three_body_author",
237
- "network": "testnet"
324
+ "network": "testnet",
325
+ "confirmed": true
238
326
  }
239
327
  }
240
328
  ```
241
329
 
330
+ > **Important**: `env.confirmed: true` is required because `replaceExistName: true` triggers a confirmation prompt. Additionally, `publish: true` on the Machine is an irreversible operation.
331
+
242
332
  **Expected Result**:
243
333
  ```json
244
- [{
245
- "type": "Machine",
246
- "object": "0x...",
247
- "version": "...",
248
- "change": "created"
249
- }]
334
+ [
335
+ {
336
+ "type": "TableItem_MachineNode",
337
+ "type_raw": "0x2::dynamic_field::Field<0x1::string::String, 0x2::parent_linked_table::Node<0x1::string::String, vector<0x2::machine::NodePair>>>",
338
+ "object": "0x...",
339
+ "version": "...",
340
+ "owner": {"ObjectOwner": "0x..."},
341
+ "change": "created"
342
+ },
343
+ {
344
+ "type": "TableItem_MachineNode",
345
+ "type_raw": "0x2::dynamic_field::Field<0x1::string::String, 0x2::parent_linked_table::Node<0x1::string::String, vector<0x2::machine::NodePair>>>",
346
+ "object": "0x...",
347
+ "version": "...",
348
+ "owner": {"ObjectOwner": "0x..."},
349
+ "change": "created"
350
+ },
351
+ {
352
+ "type": "Machine",
353
+ "type_raw": "0x2::machine::Machine",
354
+ "object": "0x...",
355
+ "version": "...",
356
+ "owner": {"Shared": {"initial_shared_version": "..."}},
357
+ "change": "created"
358
+ },
359
+ {
360
+ "type": "TableItem_EntityLinker",
361
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
362
+ "object": "0x...",
363
+ "version": "...",
364
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
365
+ "change": "created"
366
+ }
367
+ ]
250
368
  ```
251
369
 
252
370
  ---
@@ -271,19 +389,34 @@ Create the Three-Body signature service without publishing. The Service must be
271
389
  },
272
390
  "env": {
273
391
  "account": "three_body_author",
274
- "network": "testnet"
392
+ "network": "testnet",
393
+ "confirmed": true
275
394
  }
276
395
  }
277
396
  ```
278
397
 
398
+ > **Important**: `env.confirmed: true` is required because `replaceExistName: true` triggers a confirmation prompt.
399
+
279
400
  **Expected Result**:
280
401
  ```json
281
- [{
282
- "type": "Service",
283
- "object": "0x...",
284
- "version": "...",
285
- "change": "created"
286
- }]
402
+ [
403
+ {
404
+ "type": "TableItem_EntityLinker",
405
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
406
+ "object": "0x...",
407
+ "version": "...",
408
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
409
+ "change": "mutated"
410
+ },
411
+ {
412
+ "type": "Service",
413
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
414
+ "object": "0x...",
415
+ "version": "...",
416
+ "owner": {"Shared": {"initial_shared_version": "..."}},
417
+ "change": "created"
418
+ }
419
+ ]
287
420
  ```
288
421
 
289
422
  ---
@@ -309,12 +442,24 @@ Bind the published Machine to the Service. **Important**: The Service must be un
309
442
 
310
443
  **Expected Result**:
311
444
  ```json
312
- [{
313
- "type": "Service",
314
- "object": "0x...",
315
- "version": "...",
316
- "change": "mutated"
317
- }]
445
+ [
446
+ {
447
+ "type": "Service",
448
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
449
+ "object": "0x...",
450
+ "version": "...",
451
+ "owner": {"Shared": {"initial_shared_version": "..."}},
452
+ "change": "mutated"
453
+ },
454
+ {
455
+ "type": "TableItem_EntityLinker",
456
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
457
+ "object": "0x...",
458
+ "version": "...",
459
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
460
+ "change": "created"
461
+ }
462
+ ]
318
463
  ```
319
464
 
320
465
  ---
@@ -340,12 +485,24 @@ Configure the Buy Guard to restrict purchases to the author only.
340
485
 
341
486
  **Expected Result**:
342
487
  ```json
343
- [{
344
- "type": "Service",
345
- "object": "0x...",
346
- "version": "...",
347
- "change": "mutated"
348
- }]
488
+ [
489
+ {
490
+ "type": "Service",
491
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
492
+ "object": "0x...",
493
+ "version": "...",
494
+ "owner": {"Shared": {"initial_shared_version": "..."}},
495
+ "change": "mutated"
496
+ },
497
+ {
498
+ "type": "TableItem_EntityLinker",
499
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
500
+ "object": "0x...",
501
+ "version": "...",
502
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
503
+ "change": "created"
504
+ }
505
+ ]
349
506
  ```
350
507
 
351
508
  ---
@@ -389,12 +546,16 @@ Set up fund allocation: 100% to the author upon order completion.
389
546
 
390
547
  **Expected Result**:
391
548
  ```json
392
- [{
393
- "type": "Service",
394
- "object": "0x...",
395
- "version": "...",
396
- "change": "mutated"
397
- }]
549
+ [
550
+ {
551
+ "type": "Service",
552
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
553
+ "object": "0x...",
554
+ "version": "...",
555
+ "owner": {"Shared": {"initial_shared_version": "..."}},
556
+ "change": "mutated"
557
+ }
558
+ ]
398
559
  ```
399
560
 
400
561
  ---
@@ -426,19 +587,26 @@ Add sales items and publish the service to make it available for orders.
426
587
  },
427
588
  "env": {
428
589
  "account": "three_body_author",
429
- "network": "testnet"
590
+ "network": "testnet",
591
+ "confirmed": true
430
592
  }
431
593
  }
432
594
  ```
433
595
 
596
+ > **Important**: `env.confirmed: true` is **critical** here because `publish: true` is an irreversible operation that locks the `machine` and `order_allocators` fields. The server will block the transaction with a "Publish confirmation (irreversible lock)" prompt until `confirmed: true` is provided.
597
+
434
598
  **Expected Result**:
435
599
  ```json
436
- [{
437
- "type": "Service",
438
- "object": "0x...",
439
- "version": "...",
440
- "change": "mutated"
441
- }]
600
+ [
601
+ {
602
+ "type": "Service",
603
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
604
+ "object": "0x...",
605
+ "version": "...",
606
+ "owner": {"Shared": {"initial_shared_version": "..."}},
607
+ "change": "mutated"
608
+ }
609
+ ]
442
610
  ```
443
611
 
444
612
  ---
@@ -464,12 +632,16 @@ Unpause the service to allow order creation.
464
632
 
465
633
  **Expected Result**:
466
634
  ```json
467
- [{
468
- "type": "Service",
469
- "object": "0x...",
470
- "version": "...",
471
- "change": "mutated"
472
- }]
635
+ [
636
+ {
637
+ "type": "Service",
638
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
639
+ "object": "0x...",
640
+ "version": "...",
641
+ "owner": {"Shared": {"initial_shared_version": "..."}},
642
+ "change": "mutated"
643
+ }
644
+ ]
473
645
  ```
474
646
 
475
647
  ---
@@ -491,28 +663,76 @@ Query the service to verify all configurations.
491
663
  **Expected Result**:
492
664
  ```json
493
665
  {
494
- "object": "three_body_signature_service",
495
- "type": "Service",
496
- "description": "Three-Body author book signature service. Provide a message up to 10 characters, and the author will sign your book. Process: 1.Book Delivery 2.Signature Completion. Fee: 888.",
497
- "sales": [
498
- {
499
- "name": "Three-Body Book Signature",
500
- "stock": "100",
501
- "suspension": false,
502
- "price": "888",
503
- "wip": "",
504
- "wip_hash": ""
666
+ "result": {
667
+ "query_type": "onchain_objects",
668
+ "result": {
669
+ "objects": [
670
+ {
671
+ "object": "0x...",
672
+ "type": "Service",
673
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
674
+ "owner": {"Shared": {"initial_shared_version": "..."}},
675
+ "version": "...",
676
+ "previousTransaction": "...",
677
+ "description": "Three-Body author book signature service. Provide a message up to 10 characters, and the author will sign your book. Process: 1.Book Delivery 2.Signature Completion. Fee: 888.",
678
+ "location": "",
679
+ "sales": [
680
+ {
681
+ "name": "Three-Body Book Signature",
682
+ "stock": "100",
683
+ "suspension": false,
684
+ "price": "888",
685
+ "wip": "",
686
+ "wip_hash": ""
687
+ }
688
+ ],
689
+ "repositories": [],
690
+ "buy_guard": "0x...",
691
+ "machine": "0x...",
692
+ "bPublished": true,
693
+ "bPaused": false,
694
+ "customer_required": ["phone", "email", "shipping_address"],
695
+ "arbitrations": [],
696
+ "compensation_fund": "0",
697
+ "paused_time": null,
698
+ "setting_lock_duration": "2592000000",
699
+ "order_allocators": {
700
+ "description": "Three-Body signature service fund allocation - 100% to author",
701
+ "threshold": "0",
702
+ "allocators": [
703
+ {
704
+ "guard": "0x...",
705
+ "sharing": [
706
+ {
707
+ "who": {"Signer": null},
708
+ "sharing": "10000",
709
+ "mode": 1
710
+ }
711
+ ],
712
+ "fix": "0",
713
+ "max": null
714
+ }
715
+ ]
716
+ },
717
+ "rewards": [],
718
+ "um": null,
719
+ "permission": "0x...",
720
+ "cache_expire": 1234567890,
721
+ "query_name": "three_body_signature_service"
722
+ }
723
+ ]
505
724
  }
506
- ],
507
- "buy_guard": "three_body_buy_guard",
508
- "machine": "three_body_machine",
509
- "bPublished": true,
510
- "bPaused": false,
511
- "customer_required": ["phone", "email", "shipping_address"],
512
- "permission": "three_body_permission"
725
+ }
513
726
  }
514
727
  ```
515
728
 
729
+ > **Field Reference**:
730
+ > - **`buy_guard`**, **`machine`**, **`permission`**: Return **on-chain object IDs** (not names). The on-chain data stores raw object IDs; resolving them back to local mark names requires a separate reverse lookup that is not performed by `onchain_objects` queries.
731
+ > - **`query_name`**: The original name string passed in the query request (here, `"three_body_signature_service"`). This is automatically populated by the SDK from the input `objects` array, so you can identify which queried name corresponds to which returned object.
732
+ > - **`order_allocators.allocators[].sharing[].who`**: `{"Signer": null}` indicates the recipient is the order signer (the buyer). The `null` value is the on-chain representation; the input used `"signer"` as a placeholder.
733
+ > - **`order_allocators.allocators[].sharing[].mode`**: `1` is the numeric enum for `Rate` mode (input accepts the string `"Rate"`, output returns the numeric `1`).
734
+ > - **`order_allocators.allocators[].fix`** and **`max`**: Additional fields returned on-chain (default `"0"` and `null` respectively) that are not part of the input schema but are present in the on-chain data structure.
735
+
516
736
  ---
517
737
 
518
738
  ## Testing the Buy Guard
@@ -565,26 +785,78 @@ The author (`three_body_author`) should be able to purchase the service.
565
785
  ```json
566
786
  [
567
787
  {
568
- "type": "Progress",
569
- "object": "three_body_progress",
788
+ "type": "Service",
789
+ "type_raw": "0x2::service::Service<0x2::wow::WOW>",
790
+ "object": "0x...",
791
+ "version": "...",
792
+ "owner": {"Shared": {"initial_shared_version": "..."}},
793
+ "change": "mutated"
794
+ },
795
+ {
796
+ "type": "TableItem_EntityLinker",
797
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
798
+ "object": "0x...",
799
+ "version": "...",
800
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
801
+ "change": "mutated"
802
+ },
803
+ {
804
+ "type": "TableItem_EntityLinker",
805
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
806
+ "object": "0x...",
807
+ "version": "...",
808
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
809
+ "change": "mutated"
810
+ },
811
+ {
812
+ "type": "TableItem_EntityLinker",
813
+ "type_raw": "0x2::dynamic_field::Field<address, 0x2::registrar::Votes>",
814
+ "object": "0x...",
815
+ "version": "...",
816
+ "owner": {"ObjectOwner": "0x0000000000000000000000000000000000000000000000000000000000000aaa"},
817
+ "change": "created"
818
+ },
819
+ {
820
+ "type": "Allocation",
821
+ "type_raw": "0x2::allocation::Allocation<0x2::wow::WOW>",
822
+ "object": "0x...",
570
823
  "version": "...",
824
+ "owner": {"Shared": {"initial_shared_version": "..."}},
571
825
  "change": "created"
572
826
  },
573
827
  {
574
828
  "type": "Order",
575
- "object": "three_body_order",
829
+ "type_raw": "0x2::order::Order",
830
+ "object": "0x...",
576
831
  "version": "...",
832
+ "owner": {"Shared": {"initial_shared_version": "..."}},
577
833
  "change": "created"
578
834
  },
579
835
  {
580
- "type": "Allocation",
581
- "object": "three_body_allocation",
836
+ "type": "Progress",
837
+ "type_raw": "0x2::progress::Progress",
838
+ "object": "0x...",
582
839
  "version": "...",
840
+ "owner": {"Shared": {"initial_shared_version": "..."}},
583
841
  "change": "created"
584
842
  }
585
843
  ]
586
844
  ```
587
845
 
846
+ > **Why So Many Objects? (Information Injection Design)**
847
+ >
848
+ > The `order_new` operation intentionally returns ALL objects affected by the transaction, not just the primary created objects. This is a deliberate "information injection" design so callers get a complete view of the state changes:
849
+ >
850
+ > 1. **`Service` (mutated)**: The service's inventory/stock is decremented as a side effect of the purchase.
851
+ > 2. **`TableItem_EntityLinker` ×3 (mutated/created)**: The order process links the buyer, the service, and the buy_guard entities via the on-chain `EntityLinker` registrar (owner `0xaaa`). These are the entity-graph edges created/updated by the order.
852
+ > 3. **`Allocation` (created)**: The fund allocation object that will distribute the payment according to `order_allocators`.
853
+ > 4. **`Order` (created)**: The primary order object tracking the purchase.
854
+ > 5. **`Progress` (created)**: The workflow progress object tracking the order through the Machine nodes.
855
+ >
856
+ > The returned objects use **on-chain object IDs** (not the names assigned via `namedNewOrder`/`namedNewProgress`/`namedNewAllocation`). To resolve an object ID back to its local mark name, use the `query_toolkit` with `query_type: "local_names"` and pass the addresses array.
857
+ >
858
+ > The return order reflects the transaction's execution order: Service (inventory update) → EntityLinker (entity graph edges) → Allocation → Order → Progress, following the dependency chain of object creation.
859
+
588
860
  ---
589
861
 
590
862
  ### Test 2: Non-Author Purchase (Should Fail)
@@ -620,11 +892,23 @@ Any other account attempting to purchase should fail with Buy Guard verification
620
892
  ```
621
893
 
622
894
  **Expected Result** (Error):
623
- ```json
624
- {
625
- "error": "Transaction resolution failed: MoveAbort in 8th command, abort code: 7 (Verify failed), in '0x2::passport::result_for_guard'"
626
- }
627
895
  ```
896
+ Error: Error Description: Verification failed
897
+ Transaction resolution failed: MoveAbort in 8th command, abort code: 7 (Verify failed), in '0x0000000000000000000000000000000000000000000000000000000000000002::passport::result_for_guard' (instruction 17)
898
+ ```
899
+
900
+ > **Error Format Explained (Information Injection Design)**
901
+ >
902
+ > The error response is intentionally enriched with detailed diagnostic information via the `enrichMoveError` function in the SDK. This is a deliberate "information injection" design so callers can precisely diagnose failures without needing to replay the transaction:
903
+ >
904
+ > - **`Error: ` prefix**: Added by the MCP handler (`handler.ts`) to mark the response as an error.
905
+ > - **`Error Description: Verification failed`**: A human-readable classification of the error category, generated by the `classifyError` logic.
906
+ > - **`Transaction resolution failed: MoveAbort in 8th command`**: The raw Sui SDK error indicating which transaction command (8th) aborted.
907
+ > - **`abort code: 7 (Verify failed)`**: The Move abort code (7) translated to its semantic meaning (`Verify failed`).
908
+ > - **`0x0000...0002::passport::result_for_guard`**: The fully-qualified module path using the 64-character hex address form (the Sui SDK returns the full canonical form, not the short `0x2` shorthand).
909
+ > - **`(instruction 17)`**: The specific instruction index within the Move function where the abort occurred.
910
+ >
911
+ > The error is returned as a **plain text string** (not a JSON object), because it combines multiple layers of diagnostic information from different sources (Sui SDK, Move VM, MCP handler). Callers detecting errors should check for the `Error:` prefix or use the `isError` flag on the MCP response.
628
912
 
629
913
  ---
630
914
 
@@ -651,19 +935,34 @@ The author confirms the book has been delivered.
651
935
  },
652
936
  "env": {
653
937
  "account": "three_body_author",
654
- "network": "testnet"
938
+ "network": "testnet",
939
+ "no_cache": true
655
940
  }
656
941
  }
657
942
  ```
658
943
 
944
+ > **Tip**: Although `no_cache: true` is most critical for the second Progress operation (Node 2), it is recommended to use it for **all** sequential Progress operations on the same object to ensure the SDK always reads the latest on-chain state.
945
+
659
946
  **Expected Result**:
660
947
  ```json
661
- [{
662
- "type": "Progress",
663
- "object": "three_body_progress",
664
- "version": "...",
665
- "change": "mutated"
666
- }]
948
+ [
949
+ {
950
+ "type": "Progress",
951
+ "type_raw": "0x2::progress::Progress",
952
+ "object": "0x...",
953
+ "version": "...",
954
+ "owner": {"Shared": {"initial_shared_version": "..."}},
955
+ "change": "mutated"
956
+ },
957
+ {
958
+ "type": "TableItem_ProgressHistory",
959
+ "type_raw": "0x2::dynamic_field::Field<u64, 0x2::progress::History>",
960
+ "object": "0x...",
961
+ "version": "...",
962
+ "owner": {"ObjectOwner": "0x..."},
963
+ "change": "created"
964
+ }
965
+ ]
667
966
  ```
668
967
 
669
968
  ### Node 2: Signature Completed
@@ -695,12 +994,24 @@ The author completes the signature.
695
994
 
696
995
  **Expected Result**:
697
996
  ```json
698
- [{
699
- "type": "Progress",
700
- "object": "three_body_progress",
701
- "version": "...",
702
- "change": "mutated"
703
- }]
997
+ [
998
+ {
999
+ "type": "Progress",
1000
+ "type_raw": "0x2::progress::Progress",
1001
+ "object": "0x...",
1002
+ "version": "...",
1003
+ "owner": {"Shared": {"initial_shared_version": "..."}},
1004
+ "change": "mutated"
1005
+ },
1006
+ {
1007
+ "type": "TableItem_ProgressHistory",
1008
+ "type_raw": "0x2::dynamic_field::Field<u64, 0x2::progress::History>",
1009
+ "object": "0x...",
1010
+ "version": "...",
1011
+ "owner": {"ObjectOwner": "0x..."},
1012
+ "change": "created"
1013
+ }
1014
+ ]
704
1015
  ```
705
1016
 
706
1017
  ---
@@ -764,6 +1075,15 @@ Each node transition requires the author's confirmation, ensuring accountability
764
1075
  - Configure Service (add machine, buy_guard, order_allocators)
765
1076
  - Publish Service (LAST - once published, many changes are blocked)
766
1077
 
767
- 3. **Use `no_cache: true` for Sequential Operations**: When performing multiple operations on the same object in sequence (especially Progress workflow advancement), always set `no_cache: true` in the `env` to ensure the SDK reads the latest on-chain state.
1078
+ 3. **Use `confirmed: true` for Irreversible/Destructive Operations**: The MCP server enforces a two-phase confirmation for safety. You MUST add `"confirmed": true` to the `env` for:
1079
+ - Any operation using `replaceExistName: true` (unbinds existing names)
1080
+ - Any `publish: true` operation (irreversible lock on Machine/Service)
1081
+ Without `confirmed: true`, the server returns a `Confirmation required` warning and blocks the transaction.
1082
+
1083
+ 4. **Use `no_cache: true` for Sequential Operations**: When performing multiple operations on the same object in sequence (especially Progress workflow advancement), always set `no_cache: true` in the `env` to ensure the SDK reads the latest on-chain state.
1084
+
1085
+ 5. **Query Toolkit is Your Best Friend**: Use queries constantly to verify objects exist, check configurations, debug issues, and confirm state changes.
1086
+
1087
+ 6. **Object IDs vs Names in Responses**: On-chain query responses return **object IDs** (e.g., `0x8202...`) for cross-object references like `buy_guard`, `machine`, `permission`. The `query_name` field in the response echoes back the original query input name. To resolve object IDs back to local mark names, use `query_toolkit` with `query_type: "local_names"`.
768
1088
 
769
- 4. **Query Toolkit is Your Best Friend**: Use queries constantly to verify objects exist, check configurations, debug issues, and confirm state changes.
1089
+ 7. **Information Injection in Transaction Responses**: Mutation/creation operations return ALL objects affected by the transaction (including side effects like `TableItem_EntityLinker` and `TableItem_ProgressHistory`), not just the primary target. This is a deliberate design for transparency. The return order reflects the transaction's execution order.