@wowok/skills 3.0.3 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -122
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +223 -837
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts +121 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +802 -0
- package/dist/installer.js.map +1 -0
- package/dist/skills.d.ts +5 -2
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +86 -62
- package/dist/skills.js.map +1 -1
- package/dist/targets.d.ts +94 -0
- package/dist/targets.d.ts.map +1 -0
- package/dist/targets.js +421 -0
- package/dist/targets.js.map +1 -0
- package/dist/types.d.ts +5 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -32
- package/dist/types.js.map +1 -1
- package/package.json +7 -4
- package/scripts/install.js +21 -858
- package/wowok-arbitrator/SKILL.md +5 -12
- package/wowok-auditor/SKILL.md +5 -17
- package/wowok-collaborator/SKILL.md +5 -17
- package/wowok-governance/SKILL.md +95 -0
- package/wowok-machine/SKILL.md +5 -18
- package/wowok-market/SKILL.md +82 -0
- package/wowok-messenger/SKILL.md +5 -18
- package/wowok-onboard/SKILL.md +5 -22
- package/wowok-order/SKILL.md +5 -18
- package/wowok-output/SKILL.md +5 -10
- package/wowok-planner/SKILL.md +5 -19
- package/wowok-provider/SKILL.md +5 -17
- package/wowok-supplier/SKILL.md +5 -16
- package/examples/Insurance/Insurance.md +0 -1245
- package/examples/MyShop/MyShop.md +0 -2003
- package/examples/MyShop/myshop_machine_nodes.json +0 -93
- package/examples/MyShop_Advanced/MyShop_Advanced.md +0 -2874
- package/examples/ThreeBody_Signature/ThreeBody_Signature.md +0 -1831
- package/examples/Travel/Travel.md +0 -1849
- package/examples/Travel/calc-weather-timestamps.js +0 -12
|
@@ -1,2874 +0,0 @@
|
|
|
1
|
-
# MyShop Advanced E-Commerce Example
|
|
2
|
-
|
|
3
|
-
An advanced e-commerce example demonstrating escrow with multiple order fund allocation modes, multi-party allocation, arbitration with voting guards, and WIP-based product verification.
|
|
4
|
-
|
|
5
|
-
> **Complete Example**: This document contains all necessary JSON examples for setting up the MyShop Advanced e-commerce system.
|
|
6
|
-
|
|
7
|
-
***
|
|
8
|
-
|
|
9
|
-
## ⚠️ Running Principle
|
|
10
|
-
|
|
11
|
-
> **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.
|
|
12
|
-
|
|
13
|
-
- **Execution order**: Part 1 (read) → Part 2 Steps 1–14 (build all) → Part 3 (customer flow) → Part 4 (fund allocation). Do not skip steps — each depends on objects created by prior steps.
|
|
14
|
-
- **Prerequisites**: `myshop_merchant` ≥ 0.05 WOW (gas), `myshop_customer` ≥ 0.15 WOW (gas + order payment). All on-chain operations require `env.confirmed: true`.
|
|
15
|
-
|
|
16
|
-
### 🔐 Two-Step Confirmation Flow (Production Safety)
|
|
17
|
-
|
|
18
|
-
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:
|
|
19
|
-
|
|
20
|
-
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.
|
|
21
|
-
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.
|
|
22
|
-
|
|
23
|
-
> Skipping Phase 1 means the user never sees the risk summary before gas is spent. Always preview first, then confirm.
|
|
24
|
-
|
|
25
|
-
***
|
|
26
|
-
|
|
27
|
-
> **💡 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.
|
|
28
|
-
|
|
29
|
-
## Core Requirements & Features
|
|
30
|
-
|
|
31
|
-
| Requirement | Description | Implementation |
|
|
32
|
-
| ------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
33
|
-
| **WIP-Verified Product** | Single product with WIP file hash verification | `three_body.wip` integrated into Service sales |
|
|
34
|
-
| **Milestone-Based Workflow** | Order progress tracked through Machine workflow nodes | Multi-path workflow with delivery confirmation, wonderful rating, and return handling |
|
|
35
|
-
| **Simplified Fund Allocation** | Clear fund distribution model with reward incentives | 100% to merchant on completion/wonderful, 100% to customer on lost/return |
|
|
36
|
-
| **Reward System** | Incentive mechanism for excellent service and lost compensation | Reward pool with guard-based verification |
|
|
37
|
-
| **Messenger-Based Logistics** | Privacy-preserving shipping info exchange via Messenger + Merkle Root | Tracking numbers shared privately; only Merkle Root submitted on-chain |
|
|
38
|
-
| **Multi-Path Returns** | Support for non-receipt return, receipt return, and lost package handling | Different return paths based on delivery status |
|
|
39
|
-
|
|
40
|
-
### Key Design Decisions
|
|
41
|
-
|
|
42
|
-
1. **Single Product Model**: Only one WIP-verified product to simplify the example while demonstrating full capabilities
|
|
43
|
-
2. **Privacy-Preserving Logistics**: Merchant handles logistics independently using any logistics provider. Tracking numbers are shared privately via Messenger (not on-chain), with only Merkle Root submitted on-chain as proof of communication
|
|
44
|
-
3. **Reward Incentive Model**: Additional reward pool for excellent service (Wonderful reward) and compensation for lost packages
|
|
45
|
-
4. **Multi-Path Workflow**: Order can complete through normal delivery, wonderful rating, or various return paths
|
|
46
|
-
5. **Dual-Signature Returns**: Receipt return processes require both customer and merchant confirmation (threshold=2). Non-receipt returns (customer never received goods) require only merchant confirmation of goods recovery (threshold=1), since the customer has nothing to return and their non-receipt was already confirmed when entering the Non-receipt Return node.
|
|
47
|
-
|
|
48
|
-
### Important Design Principle: "Who Completes the Key Action, Who Submits the Proof"
|
|
49
|
-
|
|
50
|
-
To ensure accountability and prevent disputes, the party who completes the critical action must submit the on-chain proof:
|
|
51
|
-
|
|
52
|
-
- **Merchant Shipping**: Merchant receives customer's shipping address via Messenger and sends back tracking number → **Merchant submits Merkle Root** proving communication completed
|
|
53
|
-
- **Customer Return**: Customer sends return tracking number to merchant via Messenger → **Customer submits Merkle Root** proving communication completed
|
|
54
|
-
- **Lost Confirmation**: Both parties confirm lost package through dual-signature mechanism
|
|
55
|
-
|
|
56
|
-
This principle ensures that the party responsible for the action bears the responsibility of recording it on-chain, creating a clear audit trail for potential arbitration.
|
|
57
|
-
|
|
58
|
-
***
|
|
59
|
-
|
|
60
|
-
## Overview
|
|
61
|
-
|
|
62
|
-
This advanced example demonstrates an enterprise-grade e-commerce system with:
|
|
63
|
-
|
|
64
|
-
- **Single WIP-Verified Product**: One product listing ("The Three-Body Problem + Author Signature") with WIP file verification
|
|
65
|
-
- **Multi-Path Workflow**: Order progress with delivery confirmation, wonderful rating, lost handling, and multiple return paths
|
|
66
|
-
- **Dual-Signature Returns**: Receipt returns require both customer and merchant confirmation; non-receipt returns require only merchant confirmation of goods recovery
|
|
67
|
-
- **Reward Incentive System**: Reward pool for excellent service and compensation for lost packages
|
|
68
|
-
- **Time-Based Auto-Completion**: Orders auto-complete after time thresholds
|
|
69
|
-
|
|
70
|
-
***
|
|
71
|
-
|
|
72
|
-
## Architecture
|
|
73
|
-
|
|
74
|
-
### System Components
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
78
|
-
│ MyShop Advanced E-Commerce System │
|
|
79
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
80
|
-
│ │
|
|
81
|
-
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
|
|
82
|
-
│ │ Merchant System │ │ Customer System │ │
|
|
83
|
-
│ ├─────────────────────────┤ ├─────────────────────────┤ │
|
|
84
|
-
│ │ • Permission │ │ • Place Order │ │
|
|
85
|
-
│ │ • Machine (Milestone) │ │ • Track Progress │ │
|
|
86
|
-
│ │ • Service (WIP Catalog) │◄──►│ • Confirm Delivery │ │
|
|
87
|
-
│ │ • Allocation (Escrow) │ │ • Rate Wonderful │ │
|
|
88
|
-
│ │ • Guards (Verification) │ │ • Request Return │ │
|
|
89
|
-
│ │ • Reward Pool │ │ • Submit Arbitration │ │
|
|
90
|
-
│ └─────────────────────────┘ └─────────────────────────┘ │
|
|
91
|
-
│ │
|
|
92
|
-
│ Fund Flow: Merchant + Reward Pool (Incentives) │
|
|
93
|
-
│ │
|
|
94
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Order Workflow (Multi-Path Milestone-Based)
|
|
98
|
-
|
|
99
|
-
```mermaid
|
|
100
|
-
graph TD
|
|
101
|
-
classDef initial fill:#e1f5ff,stroke:#3399ff,stroke-width:2px;
|
|
102
|
-
classDef merchant fill:#fff3cd,stroke:#ffc107,stroke-width:2px;
|
|
103
|
-
classDef customer fill:#d4edda,stroke:#28a745,stroke-width:2px;
|
|
104
|
-
classDef dualsig fill:#f8d7da,stroke:#dc3545,stroke-width:2px;
|
|
105
|
-
classDef start fill:#999,stroke:#666,stroke-width:2px;
|
|
106
|
-
|
|
107
|
-
START(( )):::start
|
|
108
|
-
|
|
109
|
-
OC["Order Confirmed (Merchant)"]:::initial
|
|
110
|
-
OR["Order Cancel (Merchant)"]:::initial
|
|
111
|
-
|
|
112
|
-
SH["Shipping (Merchant)"]:::merchant
|
|
113
|
-
|
|
114
|
-
DC["Delivery Complete (Customer)"]:::customer
|
|
115
|
-
WO["Wonderful (Customer)"]:::customer
|
|
116
|
-
OC2["Order Complete (Merchant)<br/>Time >= 10 days"]:::merchant
|
|
117
|
-
LO["Lost (Dual-Sig)<br/>Threshold = 2"]:::dualsig
|
|
118
|
-
|
|
119
|
-
OC3["Order Complete (Merchant)"]:::merchant
|
|
120
|
-
NR["Non-receipt Return (Dual-Sig)<br/>Threshold = 2"]:::dualsig
|
|
121
|
-
|
|
122
|
-
RR["Receipt Return (Dual-Sig)<br/>Threshold = 2"]:::dualsig
|
|
123
|
-
RF["Return Fail (Merchant)<br/>Time >= 10 days"]:::merchant
|
|
124
|
-
RC["Return Complete<br/>From Receipt: Dual-Sig (threshold=2)<br/>From Non-receipt: Merchant only (threshold=1)"]:::dualsig
|
|
125
|
-
|
|
126
|
-
START --> OC
|
|
127
|
-
OC --> OR
|
|
128
|
-
OC --> SH
|
|
129
|
-
SH --> DC
|
|
130
|
-
DC --> WO
|
|
131
|
-
SH --> OC2
|
|
132
|
-
SH --> LO
|
|
133
|
-
|
|
134
|
-
DC --> OC3
|
|
135
|
-
SH --> NR
|
|
136
|
-
|
|
137
|
-
DC --> RR
|
|
138
|
-
RR --> RF
|
|
139
|
-
RR --> RC
|
|
140
|
-
NR --> RC
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
#### Fund Allocation
|
|
144
|
-
|
|
145
|
-
- **Merchant 100%**: Order Complete | Wonderful | Return Fail
|
|
146
|
-
- **Customer 100%**: Lost | Return Complete
|
|
147
|
-
|
|
148
|
-
#### Reward Compensation
|
|
149
|
-
|
|
150
|
-
- **Wonderful Node**: 10000 reward
|
|
151
|
-
- **Lost Node**: 20000 compensation
|
|
152
|
-
- **Shipping Timeout (>2 days)**: 20000 compensation
|
|
153
|
-
|
|
154
|
-
> **⚠️ Units Note (BalanceType)**: The reward/compensation amounts above (and the `amount.value` numbers in Step 13) are **raw BalanceType values in the SMALLEST unit** of WOW. WOW has 9 decimals (1 WOW = 10⁹ smallest units), so 10000 = 0.00001 WOW and 20000 = 0.00002 WOW — far below gas cost. Treat them as **symbolic/test values** that keep the flow executable on any balance; for production amounts use either larger smallest-unit values (e.g. `20000000000` = 20 WOW) or the display format (e.g. `"20WOW"`), both accepted by `BalanceTypeSchema`. Note the different semantics of `"sharing": 10000, "mode": "Rate"` in the order_allocators (Step 10): that is **basis points (100.00%)**, not a WOW amount.
|
|
155
|
-
|
|
156
|
-
***
|
|
157
|
-
|
|
158
|
-
## Part 1: Build Order and Rationale
|
|
159
|
-
|
|
160
|
-
Understanding the correct order for creating WoWok objects is crucial for a successful deployment. This section explains the dependency chain and why objects must be created in a specific sequence.
|
|
161
|
-
|
|
162
|
-
### Object Dependency Graph
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
166
|
-
│ Object Creation Dependencies │
|
|
167
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
168
|
-
│ │
|
|
169
|
-
│ Phase 1: Foundation │
|
|
170
|
-
│ ═══════════════════════════════════════════════ │
|
|
171
|
-
│ │
|
|
172
|
-
│ ┌─────────────────┐ ┌─────────────────┐ │
|
|
173
|
-
│ │ Permission │ │ Accounts │ │
|
|
174
|
-
│ │ (myshop_perm_ │ │ (myshop_merchant│ │
|
|
175
|
-
│ │ v2) │ │ myshop_customer)│ │
|
|
176
|
-
│ └────────┬────────┘ └─────────────────┘ │
|
|
177
|
-
│ │ │
|
|
178
|
-
│ ▼ │
|
|
179
|
-
│ ┌─────────────────┐ │
|
|
180
|
-
│ │ Add Permission │◄─── Grant indexes 1000, 1001 to merchant │
|
|
181
|
-
│ │ Indexes │ Required for Machine operations │
|
|
182
|
-
│ └────────┬────────┘ │
|
|
183
|
-
│ │ │
|
|
184
|
-
│ ▼ │
|
|
185
|
-
│ ┌─────────────────┐ │
|
|
186
|
-
│ │ Service │◄─── Requires: Permission │
|
|
187
|
-
│ │(three_body_sig │ Publish: FALSE (get name first) │
|
|
188
|
-
│ │ _service_v2) │ │
|
|
189
|
-
│ └────────┬────────┘ │
|
|
190
|
-
│ │ │
|
|
191
|
-
│ ▼ │
|
|
192
|
-
│ ┌─────────────────┐ │
|
|
193
|
-
│ │ Treasury │◄─── Requires: Permission (same as Service) │
|
|
194
|
-
│ │(myshop_treasury │ Aggregates merchant revenue │
|
|
195
|
-
│ │ _v2) │ Referenced by order_allocators (Phase 6) │
|
|
196
|
-
│ └────────┬────────┘ │
|
|
197
|
-
│ │ │
|
|
198
|
-
│ ▼ │
|
|
199
|
-
│ Phase 2: Guard Creation │
|
|
200
|
-
│ ═══════════════════════ │
|
|
201
|
-
│ │
|
|
202
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
203
|
-
│ │ machine_merkle_ │ │ machine_service_│ │ machine_time_ │ │
|
|
204
|
-
│ │ root_v2 │ │ order_v2 │ │ 10d_v2 │ │
|
|
205
|
-
│ └─────────────────┘ └────────┬────────┘ └─────────────────┘ │
|
|
206
|
-
│ │ │
|
|
207
|
-
│ ▼ │
|
|
208
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
209
|
-
│ │ service_merchant│ │ service_customer│ │ machine_time_2d │ │
|
|
210
|
-
│ │ _win_v2 │ │ _win_v2 │ │ _v2 │ │
|
|
211
|
-
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
|
212
|
-
│ │
|
|
213
|
-
│ Phase 2b: Reward System (Empty Object First) │
|
|
214
|
-
│ ════════════════════════════════════════════ │
|
|
215
|
-
│ │
|
|
216
|
-
│ ┌─────────────────┐ │
|
|
217
|
-
│ │ Empty Reward │◄─── Create empty reward object first │
|
|
218
|
-
│ │myshop_reward_v2 │ Guards will reference this object │
|
|
219
|
-
│ └────────┬────────┘ │
|
|
220
|
-
│ │ │
|
|
221
|
-
│ ▼ │
|
|
222
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
|
|
223
|
-
│ │ reward_wonderful│ │ reward_lost │ │ reward_shipping │ │
|
|
224
|
-
│ │ _v2 │ │ _v2 │ │ _timeout_v2 │ │
|
|
225
|
-
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
|
|
226
|
-
│ │
|
|
227
|
-
│ Phase 3: Machine Creation │
|
|
228
|
-
│ ═══════════════════════════════════════ │
|
|
229
|
-
│ │
|
|
230
|
-
│ ┌─────────────────┐ │
|
|
231
|
-
│ │ Machine │◄─── Requires: Permission + Guards │
|
|
232
|
-
│ │(myshop_advanced │ All nodes with guards for verification │
|
|
233
|
-
│ │ _machine_v2) │ │
|
|
234
|
-
│ └────────┬────────┘ │
|
|
235
|
-
│ │ │
|
|
236
|
-
│ ▼ │
|
|
237
|
-
│ Phase 4: Machine Binding │
|
|
238
|
-
│ ═══════════════════════════════════════ │
|
|
239
|
-
│ │
|
|
240
|
-
│ ┌─────────────────┐ │
|
|
241
|
-
│ │ Bind Machine │◄─── Requires: Service + Machine │
|
|
242
|
-
│ │ to Service │ Must be done before publishing Service │
|
|
243
|
-
│ └────────┬────────┘ │
|
|
244
|
-
│ │ │
|
|
245
|
-
│ ▼ │
|
|
246
|
-
│ Phase 5: Arbitration Creation │
|
|
247
|
-
│ ═══════════════════════════════════════ │
|
|
248
|
-
│ │
|
|
249
|
-
│ ┌─────────────────┐ │
|
|
250
|
-
│ │ Arbitration │◄─── Independent, but needs Service binding │
|
|
251
|
-
│ │myshop_arbitration│ │
|
|
252
|
-
│ │ _v2 │ │
|
|
253
|
-
│ └────────┬────────┘ │
|
|
254
|
-
│ │ │
|
|
255
|
-
│ ▼ │
|
|
256
|
-
│ Phase 6: Service Configuration │
|
|
257
|
-
│ ═════════════════════════════════════════ │
|
|
258
|
-
│ │
|
|
259
|
-
│ ┌─────────────────┐ │
|
|
260
|
-
│ │ Update Service │◄─── Add: order_allocators, sales, arbitrations │
|
|
261
|
-
│ │ and Publish │ Requires: All Guards, Arbitration │
|
|
262
|
-
│ └─────────────────┘ │
|
|
263
|
-
│ │
|
|
264
|
-
│ Phase 7: Reward Pool Configuration │
|
|
265
|
-
│ ═══════════════════════════════════════════ │
|
|
266
|
-
│ │
|
|
267
|
-
│ ┌─────────────────┐ │
|
|
268
|
-
│ │ Add Guards to │◄─── Add reward guards with store_from_id │
|
|
269
|
-
│ │ Reward │ Enables double-claim protection │
|
|
270
|
-
│ │myshop_reward_v2 │ │
|
|
271
|
-
│ └─────────────────┘ │
|
|
272
|
-
│ │
|
|
273
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
### Why This Order Matters
|
|
277
|
-
|
|
278
|
-
| Phase | Object | Dependencies | Reason |
|
|
279
|
-
| ----- | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
280
|
-
| 1 | **Permission** | None | Permission is the foundation. Machine and Service both reference a permission object for access control. |
|
|
281
|
-
| 1b | **Permission Indexes** | Permission | Grant permission indexes 1000 and 1001 to merchant. Required for Machine node operations. |
|
|
282
|
-
| 2 | **Service (Empty)** | Permission | Create Service without publishing first to obtain its name. This name is used in Guard verification. |
|
|
283
|
-
| 2b | **Treasury** | Permission | Treasury aggregates merchant revenue. Uses same Permission as Service. Referenced by order\_allocators in Phase 7. |
|
|
284
|
-
| 3 | **Guards** | Service Name | Guards must verify that orders belong to the correct Service. They query Service name and Progress state. |
|
|
285
|
-
| 4 | **Machine** | Permission, Guards | Machine requires guards for node verification. Guards need Service name which is now available. |
|
|
286
|
-
| 5 | **Machine Binding** | Service, Machine | Bind Machine to Service before publishing. Once published, Machine cannot be bound. |
|
|
287
|
-
| 6 | **Arbitration** | Own Permission | Arbitration is independent but needs to be bound to Service. ⚠️ It MUST use a DIFFERENT Permission than the Service — the Service contract asserts `arbitration.permission != service.permission` when binding. Create before Service update. |
|
|
288
|
-
| 7 | **Service (Update)** | Guards, Arb, Machine | Update Service with order\_allocators, sales, arbitrations, machine binding. Then publish. |
|
|
289
|
-
| 8 | **Empty Reward** | None | Create empty reward object first. This object is referenced by reward guards for double-claim protection. |
|
|
290
|
-
| 9 | **Reward Guards** | Reward (by name) | Create reward guards that reference the reward object by name. Guards verify order node + no prior claim. |
|
|
291
|
-
| 10 | **Add Guards to Reward** | Reward, Guards | Add reward guards to the reward object with store\_from\_id set. This enables order-based double-claim protection. |
|
|
292
|
-
| 11 | **Deposit to Reward** | Reward | Deposit WOW tokens to reward pool for claim distribution. |
|
|
293
|
-
|
|
294
|
-
### Key Design Decisions
|
|
295
|
-
|
|
296
|
-
1. **Permission First**: Every major object (Machine, Service) requires a permission object. Create this first.
|
|
297
|
-
2. **Permission Indexes**: Grant permission indexes 1000 and 1001 to merchant account. These are used in Machine node forwards.
|
|
298
|
-
3. **Service Before Guards**: Create Service without publishing to get its name. Guards use Service name to verify orders belong to the correct service.
|
|
299
|
-
3b. **Treasury for Fund Aggregation**: Create Treasury with the same Permission as the Service. Merchant revenue flows to the Treasury (not the Service address), making allocators inherently safe (R-C3-06) and aggregating public funds for operational distribution.
|
|
300
|
-
4. **Guards Before Machine**: Machine nodes reference guards for verification. Create all guards first, then create Machine with guard references.
|
|
301
|
-
5. **Machine Binding Before Publish**: Bind Machine to Service before publishing. Once published, Machine cannot be bound.
|
|
302
|
-
6. **Arbitration Before Service Update**: Arbitration must be created before Service update so it can be bound to Service.
|
|
303
|
-
7. **Service Publishing Last**: Only publish Service after all guards, machine, and arbitration are ready.
|
|
304
|
-
8. **Empty Reward Before Reward Guards**: Create an empty reward object first. Reward guards reference this object by name to verify no double-claiming.
|
|
305
|
-
9. **Reward Guards Before Adding to Reward**: Create reward guards that check both order node and no prior claim, then add them to the reward object with store_from_id set.
|
|
306
|
-
|
|
307
|
-
### Simplified Build Sequence
|
|
308
|
-
|
|
309
|
-
```
|
|
310
|
-
Phase 1: Foundation
|
|
311
|
-
└── 1. Create Permission (myshop_perm_v2)
|
|
312
|
-
└── Add permission indexes (1000 for Order Confirmed/Cancel, 1001 for other operations)
|
|
313
|
-
|
|
314
|
-
Phase 2: Service Creation
|
|
315
|
-
└── 2. Create Service (three_body_signature_service_v2)
|
|
316
|
-
├── Publish: FALSE
|
|
317
|
-
└── Record the Service address for Guard creation
|
|
318
|
-
|
|
319
|
-
Phase 2b: Treasury Creation
|
|
320
|
-
└── 2b. Create Treasury (myshop_treasury_v2)
|
|
321
|
-
├── Permission: myshop_perm_v2 (same as Service)
|
|
322
|
-
├── Type parameter: 0x2::wow::WOW
|
|
323
|
-
└── Aggregates merchant revenue; referenced by order_allocators (Phase 7)
|
|
324
|
-
|
|
325
|
-
Phase 3: Guard Creation (Machine Guards)
|
|
326
|
-
└── 3. Create Machine Guards (4 guards)
|
|
327
|
-
├── machine_merkle_root_v2 (verify string length = 66)
|
|
328
|
-
├── machine_service_order_v2 (verify order service + node — illustrative variant, not wired into the Machine; see Step 4 note)
|
|
329
|
-
├── machine_time_10d_v2 (on-chain time >= 10 days on current node)
|
|
330
|
-
└── machine_time_2d_v2 (on-chain time >= 2 days — illustrative variant, not wired into the Machine; see Step 4 note)
|
|
331
|
-
|
|
332
|
-
Phase 3b: Service Guards
|
|
333
|
-
└── 3b. Create Service Guards (2 guards)
|
|
334
|
-
├── service_merchant_win_v2 (verify node in [Order Complete, Wonderful, Return Fail])
|
|
335
|
-
└── service_customer_win_v2 (verify node in [Lost, Return Complete])
|
|
336
|
-
|
|
337
|
-
Phase 4: Machine Creation
|
|
338
|
-
└── 4. Create Machine (myshop_advanced_machine_v2)
|
|
339
|
-
└── Add all nodes with guards (Order Confirmed, Order Cancel, Shipping,
|
|
340
|
-
Delivery Complete, Wonderful, Order Complete, Lost,
|
|
341
|
-
Non-receipt Return, Receipt Return, Return Fail, Return Complete)
|
|
342
|
-
|
|
343
|
-
Phase 5: Machine Binding
|
|
344
|
-
└── 5. Bind Machine to Service
|
|
345
|
-
└── Must be done before publishing Service
|
|
346
|
-
|
|
347
|
-
Phase 6: Arbitration Creation
|
|
348
|
-
└── 6. Create Arbitration (myshop_arbitration_v2)
|
|
349
|
-
└── Final dispute resolution mechanism
|
|
350
|
-
|
|
351
|
-
Phase 7: Service Configuration
|
|
352
|
-
└── 7. Update and Publish Service
|
|
353
|
-
├── Add order_allocators (service_merchant_win_v2, service_customer_win_v2)
|
|
354
|
-
├── Add sales (Three-Body Problem product)
|
|
355
|
-
├── Add arbitrations binding
|
|
356
|
-
└── Publish service
|
|
357
|
-
|
|
358
|
-
Phase 8: Reward Pool Setup
|
|
359
|
-
└── 8. Create Empty Reward (myshop_reward_v2)
|
|
360
|
-
└── Create empty reward object first (guards will reference it)
|
|
361
|
-
|
|
362
|
-
Phase 9: Reward Guards Creation
|
|
363
|
-
└── 9. Create Reward Guards (3 guards)
|
|
364
|
-
├── reward_wonderful_v2 (verify Wonderful node + no prior claim)
|
|
365
|
-
├── reward_lost_v2 (verify Lost node + no prior claim)
|
|
366
|
-
└── reward_shipping_timeout_v2 (verify Shipping node + no prior claim)
|
|
367
|
-
|
|
368
|
-
Phase 10: Reward Guards Configuration
|
|
369
|
-
└── 10. Add Guards to Reward Object
|
|
370
|
-
├── Add reward_wonderful_v2 (amount: 10000, store_from_id: 0)
|
|
371
|
-
├── Add reward_lost_v2 (amount: 20000, store_from_id: 0)
|
|
372
|
-
└── Add reward_shipping_timeout_v2 (amount: 20000, store_from_id: 0)
|
|
373
|
-
|
|
374
|
-
Phase 11: Deposit to Reward Pool
|
|
375
|
-
└── 11. Deposit WOW tokens to reward pool
|
|
376
|
-
└── Add sufficient balance for all reward payments
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
***
|
|
380
|
-
|
|
381
|
-
## Part 2: Merchant System Setup
|
|
382
|
-
|
|
383
|
-
### Prerequisites
|
|
384
|
-
|
|
385
|
-
Reuse existing accounts from basic MyShop:
|
|
386
|
-
|
|
387
|
-
- Account: `myshop_merchant` (store owner)
|
|
388
|
-
- Account: `myshop_customer` (customer)
|
|
389
|
-
|
|
390
|
-
> **Mandatory**: Ensure both accounts (`myshop_merchant` and `myshop_customer`) exist as local marks BEFORE proceeding. The Permission object (Step 2) grants indexes to `myshop_merchant` by name — if the account does not exist when the permission is created, the grant will silently fail or target the wrong account, causing "Permission denied" errors in later steps.
|
|
391
|
-
|
|
392
|
-
Ensure both accounts have sufficient mainnet WOW tokens.
|
|
393
|
-
|
|
394
|
-
***
|
|
395
|
-
|
|
396
|
-
### Step 1: Create Permission Object
|
|
397
|
-
|
|
398
|
-
Create a new permission object for the advanced shop.
|
|
399
|
-
|
|
400
|
-
**Prompt**: Create permission object "myshop\_perm\_v2".
|
|
401
|
-
|
|
402
|
-
```json
|
|
403
|
-
{
|
|
404
|
-
"tool": "onchain_operations",
|
|
405
|
-
"data": {
|
|
406
|
-
"operation_type": "permission",
|
|
407
|
-
"data": {
|
|
408
|
-
"object": {
|
|
409
|
-
"name": "myshop_perm_v2",
|
|
410
|
-
"replaceExistName": true
|
|
411
|
-
},
|
|
412
|
-
"description": "Permission object for MyShop Advanced e-commerce system"
|
|
413
|
-
},
|
|
414
|
-
"env": {
|
|
415
|
-
"account": "myshop_merchant",
|
|
416
|
-
"network": "mainnet",
|
|
417
|
-
"no_cache": true
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
***
|
|
424
|
-
|
|
425
|
-
### Step 2: Add Custom Permissions
|
|
426
|
-
|
|
427
|
-
Add custom permission indexes for advanced operations.
|
|
428
|
-
|
|
429
|
-
**Permission Index 1000**: Order Confirmed + Order Cancel (Merchant operations for order confirmation/cancellation)
|
|
430
|
-
|
|
431
|
-
```json
|
|
432
|
-
{
|
|
433
|
-
"tool": "onchain_operations",
|
|
434
|
-
"data": {
|
|
435
|
-
"operation_type": "permission",
|
|
436
|
-
"data": {
|
|
437
|
-
"object": "myshop_perm_v2",
|
|
438
|
-
"remark": {
|
|
439
|
-
"op": "set",
|
|
440
|
-
"index": 1000,
|
|
441
|
-
"remark": "Order Confirmed and Order Cancel - Merchant confirms or cancels order"
|
|
442
|
-
},
|
|
443
|
-
"table": {
|
|
444
|
-
"op": "add perm by index",
|
|
445
|
-
"index": 1000,
|
|
446
|
-
"entity": {
|
|
447
|
-
"entities": [{"name_or_address": "myshop_merchant"}]
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
},
|
|
451
|
-
"env": {
|
|
452
|
-
"account": "myshop_merchant",
|
|
453
|
-
"network": "mainnet",
|
|
454
|
-
"no_cache": true
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
**Permission Index 1001**: Shipping + Order Complete + Lost + Return (Merchant logistics operations)
|
|
461
|
-
|
|
462
|
-
```json
|
|
463
|
-
{
|
|
464
|
-
"tool": "onchain_operations",
|
|
465
|
-
"data": {
|
|
466
|
-
"operation_type": "permission",
|
|
467
|
-
"data": {
|
|
468
|
-
"object": "myshop_perm_v2",
|
|
469
|
-
"remark": {
|
|
470
|
-
"op": "set",
|
|
471
|
-
"index": 1001,
|
|
472
|
-
"remark": "Shipping, Order Complete, Lost, Return operations - Merchant logistics operations"
|
|
473
|
-
},
|
|
474
|
-
"table": {
|
|
475
|
-
"op": "add perm by index",
|
|
476
|
-
"index": 1001,
|
|
477
|
-
"entity": {
|
|
478
|
-
"entities": [{"name_or_address": "myshop_merchant"}]
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
},
|
|
482
|
-
"env": {
|
|
483
|
-
"account": "myshop_merchant",
|
|
484
|
-
"network": "mainnet",
|
|
485
|
-
"no_cache": true
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
***
|
|
492
|
-
|
|
493
|
-
### Step 3: Create Service (Unpublished)
|
|
494
|
-
|
|
495
|
-
Create the Service without publishing to obtain its address for Guard creation.
|
|
496
|
-
|
|
497
|
-
**Prompt**: Create Service "three\_body\_signature\_service\_v2" with permission "myshop\_perm\_v2", do not publish.
|
|
498
|
-
|
|
499
|
-
```json
|
|
500
|
-
{
|
|
501
|
-
"tool": "onchain_operations",
|
|
502
|
-
"data": {
|
|
503
|
-
"operation_type": "service",
|
|
504
|
-
"data": {
|
|
505
|
-
"object": {
|
|
506
|
-
"name": "three_body_signature_service_v2",
|
|
507
|
-
"replaceExistName": true,
|
|
508
|
-
"permission": "myshop_perm_v2"
|
|
509
|
-
},
|
|
510
|
-
"description": "Three-Body Problem Signature Edition - Limited collector's item with WIP verification",
|
|
511
|
-
"pause": false
|
|
512
|
-
},
|
|
513
|
-
"env": {
|
|
514
|
-
"account": "myshop_merchant",
|
|
515
|
-
"network": "mainnet",
|
|
516
|
-
"no_cache": true
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
**Record the Service address** - it will be needed for Guard creation.
|
|
523
|
-
|
|
524
|
-
***
|
|
525
|
-
|
|
526
|
-
### Step 3b: Create Treasury (Merchant Revenue Aggregation)
|
|
527
|
-
|
|
528
|
-
Create a Treasury object to aggregate merchant revenue. The Treasury uses the **same Permission** as the Service (`myshop_perm_v2`) for consistency — a single permission organization governs both fund collection and service operations.
|
|
529
|
-
|
|
530
|
-
**Prompt**: Create Treasury "myshop\_treasury\_v2" with permission "myshop\_perm\_v2", type parameter "0x2::wow::WOW".
|
|
531
|
-
|
|
532
|
-
```json
|
|
533
|
-
{
|
|
534
|
-
"tool": "onchain_operations",
|
|
535
|
-
"data": {
|
|
536
|
-
"operation_type": "treasury",
|
|
537
|
-
"data": {
|
|
538
|
-
"object": {
|
|
539
|
-
"name": "myshop_treasury_v2",
|
|
540
|
-
"type_parameter": "0x2::wow::WOW",
|
|
541
|
-
"permission": "myshop_perm_v2",
|
|
542
|
-
"replaceExistName": true
|
|
543
|
-
},
|
|
544
|
-
"description": "Treasury for aggregating MyShop merchant revenue. Uses the same Permission as the Service (myshop_perm_v2) for consistency — a single permission organization governs both fund collection and service operations."
|
|
545
|
-
},
|
|
546
|
-
"env": {
|
|
547
|
-
"account": "myshop_merchant",
|
|
548
|
-
"network": "mainnet",
|
|
549
|
-
"no_cache": true
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
```
|
|
554
|
-
|
|
555
|
-
> **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance example, merchant revenue flows to `myshop_treasury_v2` (not directly to the Service address). This:
|
|
556
|
-
> 1. **Aggregates public funds** for operational distribution and accounting
|
|
557
|
-
> 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
|
|
558
|
-
> 3. **Uses permission consistency** — Treasury and Service share `myshop_perm_v2`, ensuring unified governance
|
|
559
|
-
|
|
560
|
-
***
|
|
561
|
-
|
|
562
|
-
### Step 4: Create Guards (Machine Guards)
|
|
563
|
-
|
|
564
|
-
Create Guards using the Service address. Guards verify order state and service ownership.
|
|
565
|
-
|
|
566
|
-
> **Pre-Query Step**: Before designing Guards, query available Guard instructions via `wowok_buildin_info` to confirm correct query IDs, parameter types, and return types. This is mandatory per the skill framework.
|
|
567
|
-
>
|
|
568
|
-
> ```json
|
|
569
|
-
> {
|
|
570
|
-
> "tool": "wowok_buildin_info",
|
|
571
|
-
> "data": {
|
|
572
|
-
> "info": "guard instructions",
|
|
573
|
-
> "filter": { "scope": "all" }
|
|
574
|
-
> }
|
|
575
|
-
> }
|
|
576
|
-
> ```
|
|
577
|
-
>
|
|
578
|
-
> Key instructions used in this example:
|
|
579
|
-
> - Query ID 1563 (`order.service`): Returns the Service address of an Order — used to verify order belongs to this service
|
|
580
|
-
> - Query ID 1253 (`progress.current`): Returns current node name — used to verify order at specific workflow node
|
|
581
|
-
|
|
582
|
-
**Guard 1: machine_merkle_root_v2** - Verify Merkle Root string length = 66 (0x prefix + 64 hex chars)
|
|
583
|
-
|
|
584
|
-
```json
|
|
585
|
-
{
|
|
586
|
-
"tool": "onchain_operations",
|
|
587
|
-
"data": {
|
|
588
|
-
"operation_type": "guard",
|
|
589
|
-
"data": {
|
|
590
|
-
"namedNew": {
|
|
591
|
-
"name": "machine_merkle_root_v2",
|
|
592
|
-
"replaceExistName": true
|
|
593
|
-
},
|
|
594
|
-
"description": "Verify Merkle Root string length is 66 characters (0x prefix + 64 hex)",
|
|
595
|
-
"table": [
|
|
596
|
-
{"identifier": 0, "b_submission": true, "value_type": "String"},
|
|
597
|
-
{"identifier": 1, "b_submission": false, "value_type": "U64", "value": "66"}
|
|
598
|
-
],
|
|
599
|
-
"root": {
|
|
600
|
-
"type": "logic_as_u256_equal",
|
|
601
|
-
"nodes": [
|
|
602
|
-
{"type": "calc_string_length", "node": {"type": "identifier", "identifier": 0}},
|
|
603
|
-
{"type": "identifier", "identifier": 1}
|
|
604
|
-
]
|
|
605
|
-
}
|
|
606
|
-
},
|
|
607
|
-
"env": {
|
|
608
|
-
"account": "myshop_merchant",
|
|
609
|
-
"network": "mainnet",
|
|
610
|
-
"no_cache": true
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
**Guard 1b: machine_messenger_proof_v2** - Strict-mode privacy delivery (alternative to Guard 1)
|
|
617
|
-
|
|
618
|
-
> **Two standard modes for "privacy info delivered via Messenger but not suitable for on-chain publication":**
|
|
619
|
-
>
|
|
620
|
-
> | Mode | Guard | Submission | Verification | Trust model |
|
|
621
|
-
> |------|-------|-----------|-------------|-------------|
|
|
622
|
-
> | **Broad** | `machine_merkle_root_v2` (Guard 1) | String (Merkle Root) | Length == 66 | Trusts submitter honesty; counterparty disputes via own Messenger log. Arbitration basis. |
|
|
623
|
-
> | **Strict** | `machine_messenger_proof_v2` (Guard 1b) | Proof addr + Order addr | Signer==proof.signer ∧ proof.time>order.time ∧ order.service==service | Submitter accountability (谁得利谁举证); no content verification. |
|
|
624
|
-
>
|
|
625
|
-
> Machine forwards may reference **either** Guard 1 or Guard 1b — choose before publishing (Forward.guard is immutable). The same strict Guard can be reused across all forwards that need Merkle-Root verification (shipping, lost, returns, etc.).
|
|
626
|
-
|
|
627
|
-
```json
|
|
628
|
-
{
|
|
629
|
-
"tool": "onchain_operations",
|
|
630
|
-
"data": {
|
|
631
|
-
"operation_type": "guard",
|
|
632
|
-
"data": {
|
|
633
|
-
"namedNew": {
|
|
634
|
-
"name": "machine_messenger_proof_v2",
|
|
635
|
-
"replaceExistName": true
|
|
636
|
-
},
|
|
637
|
-
"description": "Strict-mode privacy delivery: verify Signer==proof.signer AND proof.time>order.time AND order.service==service (verifier submits Proof+Order object addresses)",
|
|
638
|
-
"table": [
|
|
639
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "Proof object from submitChainProof"},
|
|
640
|
-
{"identifier": 1, "b_submission": true, "value_type": "Address", "name": "Order object submitted by verifier"},
|
|
641
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
642
|
-
],
|
|
643
|
-
"root": {
|
|
644
|
-
"type": "logic_and",
|
|
645
|
-
"nodes": [
|
|
646
|
-
{
|
|
647
|
-
"type": "logic_equal",
|
|
648
|
-
"nodes": [
|
|
649
|
-
{"type": "context", "context": "Signer"},
|
|
650
|
-
{"type": "query", "query": "proof.signer", "object": {"identifier": 0}, "parameters": []}
|
|
651
|
-
]
|
|
652
|
-
},
|
|
653
|
-
{
|
|
654
|
-
"type": "logic_as_u256_greater",
|
|
655
|
-
"nodes": [
|
|
656
|
-
{"type": "query", "query": "proof.time", "object": {"identifier": 0}, "parameters": []},
|
|
657
|
-
{"type": "query", "query": "order.time", "object": {"identifier": 1}, "parameters": []}
|
|
658
|
-
]
|
|
659
|
-
},
|
|
660
|
-
{
|
|
661
|
-
"type": "logic_equal",
|
|
662
|
-
"nodes": [
|
|
663
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 1}, "parameters": []},
|
|
664
|
-
{"type": "identifier", "identifier": 2}
|
|
665
|
-
]
|
|
666
|
-
}
|
|
667
|
-
]
|
|
668
|
-
}
|
|
669
|
-
},
|
|
670
|
-
"env": {
|
|
671
|
-
"account": "myshop_merchant",
|
|
672
|
-
"network": "mainnet",
|
|
673
|
-
"no_cache": true
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
**Three conditions (logic_and):**
|
|
680
|
-
1. **Submitter accountability** — `logic_equal[context(Signer), query("proof.signer", obj=proof)]`: the transaction signer must be the Proof's signer (the party who generated the Proof via `submitChainProof`). Suppresses R-C3-01.
|
|
681
|
-
2. **Freshness** — `logic_as_u256_greater[query("proof.time", obj=proof), query("order.time", obj=order)]`: the Proof was created after the order, preventing stale-proof replay. (`proof.time` has invariant `clock_derived`, always > 0.)
|
|
682
|
-
3. **Project binding** — `logic_equal[query("order.service", obj=order), identifier[2]]`: the submitted Order belongs to `three_body_signature_service_v2`. Suppresses R-C3-05 (cross-project bypass).
|
|
683
|
-
|
|
684
|
-
**Generating the Proof (provider side, before submitting to the forward):**
|
|
685
|
-
```text
|
|
686
|
-
// SDK call: messenger.submitChainProof(env, peerAddress, description?)
|
|
687
|
-
// - about_address is set to peerAddress (the customer's address)
|
|
688
|
-
// - pass the order_id in description to associate the Proof with the order
|
|
689
|
-
// Returns: { proofAddress, txHash }
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
**Runtime submission (verifier side, advancing the Machine forward):**
|
|
693
|
-
- Broad mode (Guard 1): submit one String identifier — the Merkle Root.
|
|
694
|
-
- Strict mode (Guard 1b): submit two Address identifiers — the Proof object address (identifier 0) and the Order object address (identifier 1).
|
|
695
|
-
|
|
696
|
-
> No content verification is performed in either mode — only submission responsibility. The counterparty can dispute a fraudulent claim by checking their own Messenger conversation for the alleged dialogue. This follows the 谁得利谁举证 (whoever benefits bears the burden of proof) principle.
|
|
697
|
-
|
|
698
|
-
**Guard 2: machine_time_10d_v2** - Verify 10-day timeout (864000000 ms)
|
|
699
|
-
|
|
700
|
-
> **Secure time-lock pattern**: identifier 0 is the **Progress object submitted at runtime (Address)** — the Guard reads its current-node entry timestamp on-chain via `query("progress.current_time")` (GUARDQUERY id 1272). NEVER declare the start time as a caller-submitted U64: a submitter could pass 0 and bypass the lock entirely. The threshold stays a creation-time constant (identifier 1).
|
|
701
|
-
|
|
702
|
-
```json
|
|
703
|
-
{
|
|
704
|
-
"tool": "onchain_operations",
|
|
705
|
-
"data": {
|
|
706
|
-
"operation_type": "guard",
|
|
707
|
-
"data": {
|
|
708
|
-
"namedNew": {
|
|
709
|
-
"name": "machine_time_10d_v2",
|
|
710
|
-
"replaceExistName": true
|
|
711
|
-
},
|
|
712
|
-
"description": "Verify time elapsed on the current node >= 10 days (864000000 ms): Clock - progress.current_time >= 864000000. The Progress object is submitted at runtime (Address identifier 0); the start time is read on-chain via query 1272, so the caller cannot forge it.",
|
|
713
|
-
"table": [
|
|
714
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "progress_id"},
|
|
715
|
-
{"identifier": 1, "b_submission": false, "value_type": "U64", "value": "864000000"}
|
|
716
|
-
],
|
|
717
|
-
"root": {
|
|
718
|
-
"type": "logic_as_u256_greater_or_equal",
|
|
719
|
-
"nodes": [
|
|
720
|
-
{
|
|
721
|
-
"type": "calc_number_subtract",
|
|
722
|
-
"nodes": [
|
|
723
|
-
{"type": "context", "context": "Clock"},
|
|
724
|
-
{"type": "query", "query": "progress.current_time", "object": {"identifier": 0}, "parameters": []}
|
|
725
|
-
]
|
|
726
|
-
},
|
|
727
|
-
{"type": "identifier", "identifier": 1}
|
|
728
|
-
]
|
|
729
|
-
}
|
|
730
|
-
},
|
|
731
|
-
"env": {
|
|
732
|
-
"account": "myshop_merchant",
|
|
733
|
-
"network": "mainnet",
|
|
734
|
-
"no_cache": true
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
```
|
|
739
|
-
|
|
740
|
-
**Guard 3: machine_time_2d_v2** - Verify 2-day timeout (172800000 ms)
|
|
741
|
-
|
|
742
|
-
```json
|
|
743
|
-
{
|
|
744
|
-
"tool": "onchain_operations",
|
|
745
|
-
"data": {
|
|
746
|
-
"operation_type": "guard",
|
|
747
|
-
"data": {
|
|
748
|
-
"namedNew": {
|
|
749
|
-
"name": "machine_time_2d_v2",
|
|
750
|
-
"replaceExistName": true
|
|
751
|
-
},
|
|
752
|
-
"description": "Verify time elapsed on the current node >= 2 days (172800000 ms): Clock - progress.current_time >= 172800000. The Progress object is submitted at runtime (Address identifier 0); the start time is read on-chain via query 1272, so the caller cannot forge it.",
|
|
753
|
-
"table": [
|
|
754
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "progress_id"},
|
|
755
|
-
{"identifier": 1, "b_submission": false, "value_type": "U64", "value": "172800000"}
|
|
756
|
-
],
|
|
757
|
-
"root": {
|
|
758
|
-
"type": "logic_as_u256_greater_or_equal",
|
|
759
|
-
"nodes": [
|
|
760
|
-
{
|
|
761
|
-
"type": "calc_number_subtract",
|
|
762
|
-
"nodes": [
|
|
763
|
-
{"type": "context", "context": "Clock"},
|
|
764
|
-
{"type": "query", "query": "progress.current_time", "object": {"identifier": 0}, "parameters": []}
|
|
765
|
-
]
|
|
766
|
-
},
|
|
767
|
-
{"type": "identifier", "identifier": 1}
|
|
768
|
-
]
|
|
769
|
-
}
|
|
770
|
-
},
|
|
771
|
-
"env": {
|
|
772
|
-
"account": "myshop_merchant",
|
|
773
|
-
"network": "mainnet",
|
|
774
|
-
"no_cache": true
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
> **⚠️ Not wired into this Machine**: `machine_time_2d_v2` (and `machine_service_order_v2` below) are **illustrative/optional variants — no forward in `myshop_advanced_machine_v2` references them**. The "Shipping Timeout (>2 days) → 20000 compensation" path promised in [Reward Compensation](#reward-compensation) is NOT a Machine transition: the order must **remain at the Shipping node** for the claim to pass, so the 2-day condition is enforced inside the `reward_shipping_timeout_v2` Guard itself (Step 12, same Clock − `progress.current_time` pattern), not by a forward Guard. Keep these Guards for reference or adapt them in your own workflow; this example's flow does not depend on them.
|
|
781
|
-
|
|
782
|
-
***
|
|
783
|
-
|
|
784
|
-
**Guard 4: service_merchant_win_v2** - Verify order at merchant win nodes AND order belongs to this service
|
|
785
|
-
|
|
786
|
-
```json
|
|
787
|
-
{
|
|
788
|
-
"tool": "onchain_operations",
|
|
789
|
-
"data": {
|
|
790
|
-
"operation_type": "guard",
|
|
791
|
-
"data": {
|
|
792
|
-
"namedNew": {
|
|
793
|
-
"name": "service_merchant_win_v2",
|
|
794
|
-
"tags": ["order", "merchant-win", "level3-scene-combined"],
|
|
795
|
-
"replaceExistName": true
|
|
796
|
-
},
|
|
797
|
-
"description": "Verify order at merchant win nodes (Order Complete, Wonderful, Return Fail) AND order belongs to three_body_signature_service_v2. VERIFIER CONSTRAINT LEVEL 3 (scene-combined): No Signer binding needed because the allocator uses sharing.who=Entity (myshop_treasury_v2) — funds always flow to the Treasury regardless of caller (R-C3-06 safe). Two-fold verification: (1) order at merchant win node, (2) order belongs to this service (prevents cross-service theft, R-C3-05).",
|
|
798
|
-
"table": [
|
|
799
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
800
|
-
{"identifier": 1, "b_submission": false, "value_type": "String", "value": "Order Complete"},
|
|
801
|
-
{"identifier": 2, "b_submission": false, "value_type": "String", "value": "Wonderful"},
|
|
802
|
-
{"identifier": 3, "b_submission": false, "value_type": "String", "value": "Return Fail"},
|
|
803
|
-
{"identifier": 4, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
804
|
-
],
|
|
805
|
-
"root": {
|
|
806
|
-
"type": "logic_and",
|
|
807
|
-
"nodes": [
|
|
808
|
-
{
|
|
809
|
-
"type": "logic_or",
|
|
810
|
-
"nodes": [
|
|
811
|
-
{
|
|
812
|
-
"type": "logic_string_nocase_equal",
|
|
813
|
-
"nodes": [
|
|
814
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
815
|
-
{"type": "identifier", "identifier": 1}
|
|
816
|
-
]
|
|
817
|
-
},
|
|
818
|
-
{
|
|
819
|
-
"type": "logic_string_nocase_equal",
|
|
820
|
-
"nodes": [
|
|
821
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
822
|
-
{"type": "identifier", "identifier": 2}
|
|
823
|
-
]
|
|
824
|
-
},
|
|
825
|
-
{
|
|
826
|
-
"type": "logic_string_nocase_equal",
|
|
827
|
-
"nodes": [
|
|
828
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
829
|
-
{"type": "identifier", "identifier": 3}
|
|
830
|
-
]
|
|
831
|
-
}
|
|
832
|
-
]
|
|
833
|
-
},
|
|
834
|
-
{
|
|
835
|
-
"type": "logic_equal",
|
|
836
|
-
"nodes": [
|
|
837
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
838
|
-
{"type": "identifier", "identifier": 4}
|
|
839
|
-
]
|
|
840
|
-
}
|
|
841
|
-
]
|
|
842
|
-
}
|
|
843
|
-
},
|
|
844
|
-
"env": {
|
|
845
|
-
"account": "myshop_merchant",
|
|
846
|
-
"network": "mainnet",
|
|
847
|
-
"no_cache": true
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
```
|
|
852
|
-
|
|
853
|
-
**Guard Explanation (Two-fold Verification — Level 3 Scene-Combined):**
|
|
854
|
-
- **Table Item 0**: Order address (submitted at runtime)
|
|
855
|
-
- **Table Items 1-3**: Constant strings "Order Complete", "Wonderful", "Return Fail" (merchant win node names)
|
|
856
|
-
- **Table Item 4**: Constant address `three_body_signature_service_v2` (this service's on-chain address)
|
|
857
|
-
- **Condition 1 — Merchant Win Node**: `logic_or` of three `logic_string_nocase_equal` checks against `query("progress.current", witness="OrderProgress")` — verifies the order is at one of the merchant win nodes
|
|
858
|
-
- **Condition 2 — Service Ownership**: `logic_equal[query("order.service"), identifier[4]]` — verifies the submitted Order's `service` field equals `three_body_signature_service_v2`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
|
|
859
|
-
- **root**: `logic_and` of both conditions — all must pass for allocation to proceed
|
|
860
|
-
|
|
861
|
-
> **Risk Elimination (R-C3-06) — Level 3 Scene-Combined Design**: The allocator uses `"who": {"Entity": {"name_or_address": "myshop_treasury_v2"}}` (funds flow to the fixed Treasury address). This is inherently safe because funds go to a fixed recipient regardless of caller — **no Signer binding is needed**. The scene itself (Entity sharing to Treasury) ensures fund-flow safety, which is the Level 3 scene-combined pattern. Removing the Signer binding also eliminates R-C4-04 (Level 1 strict binding convenience warning) and avoids the lock-in risk of binding to a fixed merchant address.
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
**Guard 4 — Alternative Shorthand Form (VecString + vec_contains_string_nocase)**
|
|
865
|
-
|
|
866
|
-
The `logic_or` of three `logic_string_nocase_equal` checks above can be collapsed into a single `vec_contains_string_nocase` over a `VecString` constant. Both forms are **semantically equivalent** (verified by `guard-examples-lint.spec.ts` → "Semantic Equivalence" tests: identical risk diagnostics, identical `root_type`, identical `errors`/`ready` state). The shorthand is preferred when the candidate set has ≥ 2 entries — it scales linearly with the vector length instead of duplicating the query node N times.
|
|
867
|
-
|
|
868
|
-
```json
|
|
869
|
-
{
|
|
870
|
-
"tool": "onchain_operations",
|
|
871
|
-
"data": {
|
|
872
|
-
"operation_type": "guard",
|
|
873
|
-
"data": {
|
|
874
|
-
"namedNew": {
|
|
875
|
-
"name": "service_merchant_win_v2",
|
|
876
|
-
"tags": ["order", "merchant-win", "level3-scene-combined"],
|
|
877
|
-
"replaceExistName": true
|
|
878
|
-
},
|
|
879
|
-
"description": "Verify order at merchant win nodes (Order Complete, Wonderful, Return Fail) AND order belongs to three_body_signature_service_v2. SHORTHAND: collapses three String constants + logic_or[logic_string_nocase_equal x 3] into a single VecString + vec_contains_string_nocase. Semantically equivalent to the original form (see guard-examples-lint 'Semantic Equivalence' tests).",
|
|
880
|
-
"table": [
|
|
881
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
882
|
-
{"identifier": 1, "b_submission": false, "value_type": "VecString", "value": ["Order Complete", "Wonderful", "Return Fail"], "name": "merchant_win_nodes"},
|
|
883
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
884
|
-
],
|
|
885
|
-
"root": {
|
|
886
|
-
"type": "logic_and",
|
|
887
|
-
"nodes": [
|
|
888
|
-
{
|
|
889
|
-
"type": "vec_contains_string_nocase",
|
|
890
|
-
"nodes": [
|
|
891
|
-
{"type": "identifier", "identifier": 1},
|
|
892
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []}
|
|
893
|
-
]
|
|
894
|
-
},
|
|
895
|
-
{
|
|
896
|
-
"type": "logic_equal",
|
|
897
|
-
"nodes": [
|
|
898
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
899
|
-
{"type": "identifier", "identifier": 2}
|
|
900
|
-
]
|
|
901
|
-
}
|
|
902
|
-
]
|
|
903
|
-
}
|
|
904
|
-
},
|
|
905
|
-
"env": {
|
|
906
|
-
"account": "myshop_merchant",
|
|
907
|
-
"network": "mainnet",
|
|
908
|
-
"no_cache": true
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
```
|
|
913
|
-
|
|
914
|
-
**Shorthand Equivalence Explanation:**
|
|
915
|
-
|
|
916
|
-
| Aspect | Original Form | Shorthand Form |
|
|
917
|
-
|---|---|---|
|
|
918
|
-
| `table` count | 5 entries (1 Address + 3 String + 1 Address) | 3 entries (1 Address + 1 VecString + 1 Address) |
|
|
919
|
-
| Condition 1 node | `logic_or` of 3 × `logic_string_nocase_equal` | `vec_contains_string_nocase` (single node) |
|
|
920
|
-
| Condition 2 node | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
|
|
921
|
-
| `root` type | `logic_and` | `logic_and` (identical) |
|
|
922
|
-
| Risk diagnostics (R-C3-*) | identical | identical (security-equivalent) |
|
|
923
|
-
| Lint diagnostics (LE-04, SG-01, SG-03) | identical | identical |
|
|
924
|
-
| SH-03 warnings (missing `name`) | 3 (the 3 unnamed String constants) | 0 (the VecString is named `merchant_win_nodes`) |
|
|
925
|
-
| Total warnings | 5 | 2 (3 fewer — the eliminated SH-03s) |
|
|
926
|
-
|
|
927
|
-
**Why the shorthand is preferred:**
|
|
928
|
-
- **Fewer table entries**: 3 vs 5 (40% reduction). Adding a new merchant-win node is a one-line edit to the `value` array instead of a new identifier + new `logic_string_nocase_equal` branch.
|
|
929
|
-
- **No SH-03 nits**: The single `VecString` entry is naturally named (`merchant_win_nodes`), eliminating the 3 missing-name warnings.
|
|
930
|
-
- **Linear scaling**: For N candidate nodes, the original grows as O(N) identifiers + O(N) `logic_string_nocase_equal` branches under one `logic_or` (capped at 8 children). The shorthand stays at 1 identifier + 1 `vec_contains_string_nocase` node regardless of N.
|
|
931
|
-
- **Same security posture**: Risk-layer diagnostics are byte-identical (R-C3-05, R-C3-06, etc. all evaluate the same), so the Level 3 scene-combined design and R-C3-06 suppression are preserved.
|
|
932
|
-
|
|
933
|
-
**Equivalence verification**: See `d:\wowok\agent\mcp\src\knowledge\__tests__\guard-examples-lint.spec.ts` → describe block `"Semantic Equivalence — Shorthand vs Original (VecString + vec_contains_string_nocase)"`. The 8-test suite verifies: identical `root_type`, identical `errors`/`ready`, identical risk diagnostic codes, identical lint diagnostic codes (excluding SH-03), fewer SH-03 warnings, reduced `table_count`, no SDK syntax errors, and complete `risk_assessment`.
|
|
934
|
-
|
|
935
|
-
**Guard 5: machine_service_order_v2** - Verify order belongs to this Service
|
|
936
|
-
|
|
937
|
-
```json
|
|
938
|
-
{
|
|
939
|
-
"tool": "onchain_operations",
|
|
940
|
-
"data": {
|
|
941
|
-
"operation_type": "guard",
|
|
942
|
-
"data": {
|
|
943
|
-
"namedNew": {
|
|
944
|
-
"name": "machine_service_order_v2",
|
|
945
|
-
"replaceExistName": true
|
|
946
|
-
},
|
|
947
|
-
"description": "Verify order belongs to three_body_signature_service_v2",
|
|
948
|
-
"table": [
|
|
949
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
950
|
-
{"identifier": 1, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
951
|
-
],
|
|
952
|
-
"root": {
|
|
953
|
-
"type": "logic_equal",
|
|
954
|
-
"nodes": [
|
|
955
|
-
{
|
|
956
|
-
"type": "query",
|
|
957
|
-
"query": "order.service",
|
|
958
|
-
"object": {"identifier": 0},
|
|
959
|
-
"parameters": []
|
|
960
|
-
},
|
|
961
|
-
{
|
|
962
|
-
"type": "identifier",
|
|
963
|
-
"identifier": 1
|
|
964
|
-
}
|
|
965
|
-
]
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
"env": {
|
|
969
|
-
"account": "myshop_merchant",
|
|
970
|
-
"network": "mainnet",
|
|
971
|
-
"no_cache": true
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
```
|
|
976
|
-
|
|
977
|
-
***
|
|
978
|
-
|
|
979
|
-
**Guard 6: service_customer_win_v2** - Verify order at customer win nodes AND order belongs to this service
|
|
980
|
-
|
|
981
|
-
```json
|
|
982
|
-
{
|
|
983
|
-
"tool": "onchain_operations",
|
|
984
|
-
"data": {
|
|
985
|
-
"operation_type": "guard",
|
|
986
|
-
"data": {
|
|
987
|
-
"namedNew": {
|
|
988
|
-
"name": "service_customer_win_v2",
|
|
989
|
-
"tags": ["order", "customer-win", "level2-dynamic-binding"],
|
|
990
|
-
"replaceExistName": true
|
|
991
|
-
},
|
|
992
|
-
"description": "Verify order at customer win nodes (Lost, Return Complete) AND order belongs to three_body_signature_service_v2. VERIFIER CONSTRAINT LEVEL 2 (dynamic identity binding): Signer bound to query('order.owner') — only the order's rightful owner can trigger the refund. RISK ELIMINATION: Three-fold verification - (1) order at customer win node, (2) signer is order.owner (dynamic query, prevents fund theft - only order owner can trigger their own refund), (3) order belongs to three_body_signature_service_v2 (prevents cross-service theft).",
|
|
993
|
-
"table": [
|
|
994
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
995
|
-
{"identifier": 1, "b_submission": false, "value_type": "String", "value": "Lost"},
|
|
996
|
-
{"identifier": 2, "b_submission": false, "value_type": "String", "value": "Return Complete"},
|
|
997
|
-
{"identifier": 3, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
998
|
-
],
|
|
999
|
-
"root": {
|
|
1000
|
-
"type": "logic_and",
|
|
1001
|
-
"nodes": [
|
|
1002
|
-
{
|
|
1003
|
-
"type": "logic_or",
|
|
1004
|
-
"nodes": [
|
|
1005
|
-
{
|
|
1006
|
-
"type": "logic_string_nocase_equal",
|
|
1007
|
-
"nodes": [
|
|
1008
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
1009
|
-
{"type": "identifier", "identifier": 1}
|
|
1010
|
-
]
|
|
1011
|
-
},
|
|
1012
|
-
{
|
|
1013
|
-
"type": "logic_string_nocase_equal",
|
|
1014
|
-
"nodes": [
|
|
1015
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
1016
|
-
{"type": "identifier", "identifier": 2}
|
|
1017
|
-
]
|
|
1018
|
-
}
|
|
1019
|
-
]
|
|
1020
|
-
},
|
|
1021
|
-
{
|
|
1022
|
-
"type": "logic_equal",
|
|
1023
|
-
"nodes": [
|
|
1024
|
-
{"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
|
|
1025
|
-
{"type": "context", "context": "Signer"}
|
|
1026
|
-
]
|
|
1027
|
-
},
|
|
1028
|
-
{
|
|
1029
|
-
"type": "logic_equal",
|
|
1030
|
-
"nodes": [
|
|
1031
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
1032
|
-
{"type": "identifier", "identifier": 3}
|
|
1033
|
-
]
|
|
1034
|
-
}
|
|
1035
|
-
]
|
|
1036
|
-
}
|
|
1037
|
-
},
|
|
1038
|
-
"env": {
|
|
1039
|
-
"account": "myshop_merchant",
|
|
1040
|
-
"network": "mainnet",
|
|
1041
|
-
"no_cache": true
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
```
|
|
1046
|
-
|
|
1047
|
-
**Guard Explanation (Three-fold Verification — Level 2 Dynamic Binding):**
|
|
1048
|
-
- **Table Item 0**: Order address (submitted at runtime)
|
|
1049
|
-
- **Table Items 1-2**: Constant strings "Lost", "Return Complete" (customer win node names)
|
|
1050
|
-
- **Table Item 3**: Constant address `three_body_signature_service_v2` (this service's on-chain address)
|
|
1051
|
-
- **Condition 1 — Customer Win Node**: `logic_or` of two `logic_string_nocase_equal` checks against `query("progress.current", witness="OrderProgress")` — verifies the order is at one of the customer win nodes
|
|
1052
|
-
- **Condition 2 — Signer is Order Owner (Level 2 Dynamic)**: `logic_equal[query("order.owner"), context(Signer)]` — verifies the transaction caller is the order's owner (dynamic query, not a fixed address). This is the **Level 2 dynamic identity binding** pattern: the Signer is bound to a query result (not a fixed address), so it survives personnel changes and avoids the R-C4-04 lock-in risk. **Prevents fund theft by unauthorized callers** (R-C3-01/R-C3-06). Only the customer who placed the order can trigger the refund.
|
|
1053
|
-
- **Condition 3 — Service Ownership**: `logic_equal[query("order.service"), identifier[3]]` — verifies the submitted Order's `service` field equals `three_body_signature_service_v2`, **preventing cross-service theft** where someone submits another service's order (R-C3-05)
|
|
1054
|
-
- **root**: `logic_and` of all three conditions — all must pass for allocation to proceed
|
|
1055
|
-
|
|
1056
|
-
> **Risk Elimination (R-C3-06) — CRITICAL — Level 2 Dynamic Binding**: The allocator uses `"who": {"Signer": "signer"}` (funds go to the caller). This is safe ONLY because Condition 2 binds the Signer to `query("order.owner")` (dynamic query — Level 2). Without this binding, anyone could submit any Lost/Return Complete order and steal 100% of funds. The dynamic query pattern ensures funds always flow to the order's rightful owner, regardless of who calls the transaction. Unlike Level 1 (fixed address), Level 2 dynamic binding does NOT trigger R-C4-04 because the bound identity is a query result, not an immutable address constant.
|
|
1057
|
-
```
|
|
1058
|
-
|
|
1059
|
-
**Guard 6 — Alternative Shorthand Form (VecString + vec_contains_string_nocase)**
|
|
1060
|
-
|
|
1061
|
-
The `logic_or` of two `logic_string_nocase_equal` checks above can be collapsed into a single `vec_contains_string_nocase` over a `VecString` constant. Both forms are **semantically equivalent** (verified by `guard-examples-lint.spec.ts` → "Semantic Equivalence — Guard 6 Shorthand" tests: identical risk diagnostics, identical `root_type`, identical `errors`/`ready` state).
|
|
1062
|
-
|
|
1063
|
-
```json
|
|
1064
|
-
{
|
|
1065
|
-
"tool": "onchain_operations",
|
|
1066
|
-
"data": {
|
|
1067
|
-
"operation_type": "guard",
|
|
1068
|
-
"data": {
|
|
1069
|
-
"namedNew": {
|
|
1070
|
-
"name": "service_customer_win_v2",
|
|
1071
|
-
"tags": ["order", "customer-win", "level2-dynamic-binding"],
|
|
1072
|
-
"replaceExistName": true
|
|
1073
|
-
},
|
|
1074
|
-
"description": "Verify order at customer win nodes (Lost, Return Complete) AND order belongs to three_body_signature_service_v2. SHORTHAND: collapses two String constants + logic_or[logic_string_nocase_equal x 2] into a single VecString + vec_contains_string_nocase. Semantically equivalent to the original form (see guard-examples-lint 'Semantic Equivalence — Guard 6 Shorthand' tests).",
|
|
1075
|
-
"table": [
|
|
1076
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
1077
|
-
{"identifier": 1, "b_submission": false, "value_type": "VecString", "value": ["Lost", "Return Complete"], "name": "customer_win_nodes"},
|
|
1078
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "name": "service_address", "value": "three_body_signature_service_v2"}
|
|
1079
|
-
],
|
|
1080
|
-
"root": {
|
|
1081
|
-
"type": "logic_and",
|
|
1082
|
-
"nodes": [
|
|
1083
|
-
{
|
|
1084
|
-
"type": "vec_contains_string_nocase",
|
|
1085
|
-
"nodes": [
|
|
1086
|
-
{"type": "identifier", "identifier": 1},
|
|
1087
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []}
|
|
1088
|
-
]
|
|
1089
|
-
},
|
|
1090
|
-
{
|
|
1091
|
-
"type": "logic_equal",
|
|
1092
|
-
"nodes": [
|
|
1093
|
-
{"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
|
|
1094
|
-
{"type": "context", "context": "Signer"}
|
|
1095
|
-
]
|
|
1096
|
-
},
|
|
1097
|
-
{
|
|
1098
|
-
"type": "logic_equal",
|
|
1099
|
-
"nodes": [
|
|
1100
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
1101
|
-
{"type": "identifier", "identifier": 2}
|
|
1102
|
-
]
|
|
1103
|
-
}
|
|
1104
|
-
]
|
|
1105
|
-
}
|
|
1106
|
-
},
|
|
1107
|
-
"env": {
|
|
1108
|
-
"account": "myshop_merchant",
|
|
1109
|
-
"network": "mainnet",
|
|
1110
|
-
"no_cache": true
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
```
|
|
1115
|
-
|
|
1116
|
-
**Shorthand Equivalence Explanation:**
|
|
1117
|
-
|
|
1118
|
-
| Aspect | Original Form | Shorthand Form |
|
|
1119
|
-
|---|---|---|
|
|
1120
|
-
| `table` count | 4 entries (1 Address + 2 String + 1 Address) | 3 entries (1 Address + 1 VecString + 1 Address) |
|
|
1121
|
-
| Condition 1 node | `logic_or` of 2 × `logic_string_nocase_equal` | `vec_contains_string_nocase` (single node) |
|
|
1122
|
-
| Condition 2 node (Signer binding) | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
|
|
1123
|
-
| Condition 3 node (Service ownership) | `logic_equal` (unchanged) | `logic_equal` (unchanged) |
|
|
1124
|
-
| `root` type | `logic_and` | `logic_and` (identical) |
|
|
1125
|
-
| Risk diagnostics (R-C3-*) | identical | identical (security-equivalent) |
|
|
1126
|
-
| Lint diagnostics (LE-04, SG-01, SG-03) | identical | identical |
|
|
1127
|
-
| SH-03 warnings (missing `name`) | 2 (the 2 unnamed String constants) | 0 (the VecString is named `customer_win_nodes`) |
|
|
1128
|
-
| Total warnings | 4 | 2 (2 fewer — the eliminated SH-03s) |
|
|
1129
|
-
|
|
1130
|
-
**Case-sensitivity note (critical)**: The source uses `logic_string_nocase_equal` (case-insensitive), so the target is `vec_contains_string_nocase` (case-insensitive). If the source had used `logic_equal` on String (case-sensitive — "Lost" ≠ "lost"), the target would have to be `vec_contains_string` (case-sensitive) to preserve semantics. **Mixing case-sensitive and case-insensitive operators in the same `logic_or` is NOT convertible** — the original `logic_or` must be kept because there is no single `vec_contains_*` variant that captures both behaviors. This is a fundamental limitation of the contains shorthand: it is syntactic sugar, not a universal replacement.
|
|
1131
|
-
|
|
1132
|
-
**Equivalence verification**: See `d:\wowok\agent\mcp\src\knowledge\__tests__\guard-examples-lint.spec.ts` → describe block `"Semantic Equivalence — Guard 6 Shorthand (service_customer_win_v2: VecString + vec_contains_string_nocase)"`. The 8-test suite verifies: identical `root_type`, identical `errors`/`ready`, identical risk diagnostic codes, identical lint diagnostic codes (excluding SH-03), fewer SH-03 warnings, reduced `table_count`, no SDK syntax errors, and complete `risk_assessment`.
|
|
1133
|
-
|
|
1134
|
-
***
|
|
1135
|
-
|
|
1136
|
-
### Step 5: Create Machine (Multi-Path Workflow)
|
|
1137
|
-
|
|
1138
|
-
Create Machine with all nodes and guards in a single operation.
|
|
1139
|
-
|
|
1140
|
-
**Important Notes on Machine Design**:
|
|
1141
|
-
|
|
1142
|
-
1. **Entry Node Constraint (Mandatory)**: At least one node MUST have a pair with `prev_node: ""` (empty string). This defines the entry point from the initial state. Without such a node, Progress cannot advance from its initial empty state. In this example, the "Order Confirmed" node has `prev_node: ""` serving as the entry point.
|
|
1143
|
-
|
|
1144
|
-
2. **`namedOperator` for Customer Operations**: In Machine forwards, setting `namedOperator: ""` (empty string) allows the **customer** to operate the Progress through their Order. This is required for all forwards that should be triggered by the customer via the order system. Forwards without `namedOperator` or with a specific named operator require the merchant or designated operator to execute.
|
|
1145
|
-
|
|
1146
|
-
3. **Permission Index vs namedOperator**: Each forward MUST specify either `permissionIndex` (shared internal role) OR `namedOperator` (per-Progress namespace). Order user operations MUST use `namedOperator("")`.
|
|
1147
|
-
|
|
1148
|
-
**Prompt**: Create Machine "myshop\_advanced\_machine\_v2" with permission "myshop\_perm\_v2" and all nodes.
|
|
1149
|
-
|
|
1150
|
-
```json
|
|
1151
|
-
{
|
|
1152
|
-
"tool": "onchain_operations",
|
|
1153
|
-
"data": {
|
|
1154
|
-
"operation_type": "machine",
|
|
1155
|
-
"data": {
|
|
1156
|
-
"object": {
|
|
1157
|
-
"name": "myshop_advanced_machine_v2",
|
|
1158
|
-
"replaceExistName": true,
|
|
1159
|
-
"permission": "myshop_perm_v2"
|
|
1160
|
-
},
|
|
1161
|
-
"description": "Multi-path order processing with delivery confirmation, wonderful rating, lost handling and return processing - Complete workflow with guards",
|
|
1162
|
-
"node": {
|
|
1163
|
-
"op": "add",
|
|
1164
|
-
"nodes": [
|
|
1165
|
-
{
|
|
1166
|
-
"name": "Order Confirmed",
|
|
1167
|
-
"pairs": [
|
|
1168
|
-
{
|
|
1169
|
-
"prev_node": "",
|
|
1170
|
-
"threshold": 1,
|
|
1171
|
-
"forwards": [
|
|
1172
|
-
{
|
|
1173
|
-
"name": "Confirm Order",
|
|
1174
|
-
"permissionIndex": 1000,
|
|
1175
|
-
"weight": 1
|
|
1176
|
-
}
|
|
1177
|
-
]
|
|
1178
|
-
}
|
|
1179
|
-
]
|
|
1180
|
-
},
|
|
1181
|
-
{
|
|
1182
|
-
"name": "Order Cancel",
|
|
1183
|
-
"pairs": [
|
|
1184
|
-
{
|
|
1185
|
-
"prev_node": "Order Confirmed",
|
|
1186
|
-
"threshold": 1,
|
|
1187
|
-
"forwards": [
|
|
1188
|
-
{
|
|
1189
|
-
"name": "Cancel Order",
|
|
1190
|
-
"permissionIndex": 1000,
|
|
1191
|
-
"weight": 1
|
|
1192
|
-
}
|
|
1193
|
-
]
|
|
1194
|
-
}
|
|
1195
|
-
]
|
|
1196
|
-
},
|
|
1197
|
-
{
|
|
1198
|
-
"name": "Shipping",
|
|
1199
|
-
"pairs": [
|
|
1200
|
-
{
|
|
1201
|
-
"prev_node": "Order Confirmed",
|
|
1202
|
-
"threshold": 1,
|
|
1203
|
-
"forwards": [
|
|
1204
|
-
{
|
|
1205
|
-
"name": "Confirm Signature and Submit Merkle Root",
|
|
1206
|
-
"permissionIndex": 1001,
|
|
1207
|
-
"weight": 1,
|
|
1208
|
-
"guard": { "guard": "machine_merkle_root_v2" }
|
|
1209
|
-
}
|
|
1210
|
-
]
|
|
1211
|
-
}
|
|
1212
|
-
]
|
|
1213
|
-
},
|
|
1214
|
-
{
|
|
1215
|
-
"name": "Delivery Complete",
|
|
1216
|
-
"pairs": [
|
|
1217
|
-
{
|
|
1218
|
-
"prev_node": "Shipping",
|
|
1219
|
-
"threshold": 1,
|
|
1220
|
-
"forwards": [
|
|
1221
|
-
{
|
|
1222
|
-
"name": "Confirm Receipt",
|
|
1223
|
-
"weight": 1,
|
|
1224
|
-
"namedOperator": ""
|
|
1225
|
-
}
|
|
1226
|
-
]
|
|
1227
|
-
}
|
|
1228
|
-
]
|
|
1229
|
-
},
|
|
1230
|
-
{
|
|
1231
|
-
"name": "Wonderful",
|
|
1232
|
-
"pairs": [
|
|
1233
|
-
{
|
|
1234
|
-
"prev_node": "Delivery Complete",
|
|
1235
|
-
"threshold": 1,
|
|
1236
|
-
"forwards": [
|
|
1237
|
-
{
|
|
1238
|
-
"name": "Rate as Wonderful",
|
|
1239
|
-
"weight": 1,
|
|
1240
|
-
"namedOperator": ""
|
|
1241
|
-
}
|
|
1242
|
-
]
|
|
1243
|
-
}
|
|
1244
|
-
]
|
|
1245
|
-
},
|
|
1246
|
-
{
|
|
1247
|
-
"name": "Order Complete",
|
|
1248
|
-
"pairs": [
|
|
1249
|
-
{
|
|
1250
|
-
"prev_node": "Delivery Complete",
|
|
1251
|
-
"threshold": 1,
|
|
1252
|
-
"forwards": [
|
|
1253
|
-
{
|
|
1254
|
-
"name": "Complete Order",
|
|
1255
|
-
"permissionIndex": 1001,
|
|
1256
|
-
"weight": 1
|
|
1257
|
-
}
|
|
1258
|
-
]
|
|
1259
|
-
},
|
|
1260
|
-
{
|
|
1261
|
-
"prev_node": "Shipping",
|
|
1262
|
-
"threshold": 1,
|
|
1263
|
-
"forwards": [
|
|
1264
|
-
{
|
|
1265
|
-
"name": "Auto Complete from Shipping",
|
|
1266
|
-
"permissionIndex": 1001,
|
|
1267
|
-
"weight": 1,
|
|
1268
|
-
"guard": { "guard": "machine_time_10d_v2" }
|
|
1269
|
-
}
|
|
1270
|
-
]
|
|
1271
|
-
}
|
|
1272
|
-
]
|
|
1273
|
-
},
|
|
1274
|
-
{
|
|
1275
|
-
"name": "Lost",
|
|
1276
|
-
"pairs": [
|
|
1277
|
-
{
|
|
1278
|
-
"prev_node": "Shipping",
|
|
1279
|
-
"threshold": 2,
|
|
1280
|
-
"forwards": [
|
|
1281
|
-
{
|
|
1282
|
-
"name": "Report Lost",
|
|
1283
|
-
"weight": 1,
|
|
1284
|
-
"namedOperator": ""
|
|
1285
|
-
},
|
|
1286
|
-
{
|
|
1287
|
-
"name": "Confirm Lost with Merkle Root",
|
|
1288
|
-
"permissionIndex": 1001,
|
|
1289
|
-
"weight": 1,
|
|
1290
|
-
"guard": { "guard": "machine_merkle_root_v2" }
|
|
1291
|
-
}
|
|
1292
|
-
]
|
|
1293
|
-
}
|
|
1294
|
-
]
|
|
1295
|
-
},
|
|
1296
|
-
{
|
|
1297
|
-
"name": "Non-receipt Return",
|
|
1298
|
-
"pairs": [
|
|
1299
|
-
{
|
|
1300
|
-
"prev_node": "Shipping",
|
|
1301
|
-
"threshold": 2,
|
|
1302
|
-
"forwards": [
|
|
1303
|
-
{
|
|
1304
|
-
"name": "Request Return",
|
|
1305
|
-
"weight": 1,
|
|
1306
|
-
"namedOperator": ""
|
|
1307
|
-
},
|
|
1308
|
-
{
|
|
1309
|
-
"name": "Confirm Return with Merkle Root",
|
|
1310
|
-
"permissionIndex": 1001,
|
|
1311
|
-
"weight": 1,
|
|
1312
|
-
"guard": { "guard": "machine_merkle_root_v2" }
|
|
1313
|
-
}
|
|
1314
|
-
]
|
|
1315
|
-
}
|
|
1316
|
-
]
|
|
1317
|
-
},
|
|
1318
|
-
{
|
|
1319
|
-
"name": "Receipt Return",
|
|
1320
|
-
"pairs": [
|
|
1321
|
-
{
|
|
1322
|
-
"prev_node": "Delivery Complete",
|
|
1323
|
-
"threshold": 2,
|
|
1324
|
-
"forwards": [
|
|
1325
|
-
{
|
|
1326
|
-
"name": "Request Return with Receipt",
|
|
1327
|
-
"weight": 1,
|
|
1328
|
-
"namedOperator": ""
|
|
1329
|
-
},
|
|
1330
|
-
{
|
|
1331
|
-
"name": "Confirm Return Address with Merkle Root",
|
|
1332
|
-
"permissionIndex": 1001,
|
|
1333
|
-
"weight": 1,
|
|
1334
|
-
"guard": { "guard": "machine_merkle_root_v2" }
|
|
1335
|
-
}
|
|
1336
|
-
]
|
|
1337
|
-
}
|
|
1338
|
-
]
|
|
1339
|
-
},
|
|
1340
|
-
{
|
|
1341
|
-
"name": "Return Fail",
|
|
1342
|
-
"pairs": [
|
|
1343
|
-
{
|
|
1344
|
-
"prev_node": "Receipt Return",
|
|
1345
|
-
"threshold": 1,
|
|
1346
|
-
"forwards": [
|
|
1347
|
-
{
|
|
1348
|
-
"name": "Timeout Return Not Received",
|
|
1349
|
-
"permissionIndex": 1001,
|
|
1350
|
-
"weight": 1,
|
|
1351
|
-
"guard": { "guard": "machine_time_10d_v2" }
|
|
1352
|
-
}
|
|
1353
|
-
]
|
|
1354
|
-
}
|
|
1355
|
-
]
|
|
1356
|
-
},
|
|
1357
|
-
{
|
|
1358
|
-
"name": "Return Complete",
|
|
1359
|
-
"pairs": [
|
|
1360
|
-
{
|
|
1361
|
-
"prev_node": "Receipt Return",
|
|
1362
|
-
"threshold": 2,
|
|
1363
|
-
"forwards": [
|
|
1364
|
-
{
|
|
1365
|
-
"name": "Submit Return Merkle Root",
|
|
1366
|
-
"weight": 1,
|
|
1367
|
-
"namedOperator": "",
|
|
1368
|
-
"guard": { "guard": "machine_merkle_root_v2" }
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
"name": "Confirm Return Received",
|
|
1372
|
-
"permissionIndex": 1001,
|
|
1373
|
-
"weight": 1
|
|
1374
|
-
}
|
|
1375
|
-
]
|
|
1376
|
-
},
|
|
1377
|
-
{
|
|
1378
|
-
"prev_node": "Non-receipt Return",
|
|
1379
|
-
"threshold": 1,
|
|
1380
|
-
"forwards": [
|
|
1381
|
-
{
|
|
1382
|
-
"name": "Confirm Goods Recovered",
|
|
1383
|
-
"permissionIndex": 1001,
|
|
1384
|
-
"weight": 1
|
|
1385
|
-
}
|
|
1386
|
-
]
|
|
1387
|
-
}
|
|
1388
|
-
]
|
|
1389
|
-
}
|
|
1390
|
-
]
|
|
1391
|
-
}
|
|
1392
|
-
},
|
|
1393
|
-
"env": {
|
|
1394
|
-
"account": "myshop_merchant",
|
|
1395
|
-
"network": "mainnet",
|
|
1396
|
-
"no_cache": true
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
```
|
|
1401
|
-
|
|
1402
|
-
***
|
|
1403
|
-
|
|
1404
|
-
### Step 6: Publish Machine
|
|
1405
|
-
|
|
1406
|
-
> **Pre-Publish Verification (Mandatory)**: Before publishing, export and review the Machine node structure using `machineNode2file`. Once published, node settings become immutable. Verify all nodes, forwards, guards, and permission indices are correct.
|
|
1407
|
-
>
|
|
1408
|
-
> ```json
|
|
1409
|
-
> {
|
|
1410
|
-
> "tool": "machineNode2file",
|
|
1411
|
-
> "data": {
|
|
1412
|
-
> "machine": "myshop_advanced_machine_v2",
|
|
1413
|
-
> "file_path": ".trae/tmp/myshop_machine_export.json",
|
|
1414
|
-
> "format": "json"
|
|
1415
|
-
> }
|
|
1416
|
-
> }
|
|
1417
|
-
> ```
|
|
1418
|
-
>
|
|
1419
|
-
> Confirm with the user that the exported structure is correct before proceeding to publish.
|
|
1420
|
-
|
|
1421
|
-
Machine must be published before binding to Service.
|
|
1422
|
-
|
|
1423
|
-
```json
|
|
1424
|
-
{
|
|
1425
|
-
"tool": "onchain_operations",
|
|
1426
|
-
"data": {
|
|
1427
|
-
"operation_type": "machine",
|
|
1428
|
-
"data": {
|
|
1429
|
-
"object": "myshop_advanced_machine_v2",
|
|
1430
|
-
"publish": true
|
|
1431
|
-
},
|
|
1432
|
-
"env": {
|
|
1433
|
-
"account": "myshop_merchant",
|
|
1434
|
-
"network": "mainnet",
|
|
1435
|
-
"no_cache": true,
|
|
1436
|
-
"confirmed": true
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
```
|
|
1441
|
-
|
|
1442
|
-
***
|
|
1443
|
-
|
|
1444
|
-
### Step 7: Bind Machine to Service
|
|
1445
|
-
|
|
1446
|
-
Bind the Machine to the Service. **Important**: The Service must be unpublished when binding the Machine.
|
|
1447
|
-
|
|
1448
|
-
**Prompt**: Bind machine "myshop\_advanced\_machine\_v2" to service "three\_body\_signature\_service\_v2".
|
|
1449
|
-
|
|
1450
|
-
```json
|
|
1451
|
-
{
|
|
1452
|
-
"tool": "onchain_operations",
|
|
1453
|
-
"data": {
|
|
1454
|
-
"operation_type": "service",
|
|
1455
|
-
"data": {
|
|
1456
|
-
"object": "three_body_signature_service_v2",
|
|
1457
|
-
"machine": "myshop_advanced_machine_v2"
|
|
1458
|
-
},
|
|
1459
|
-
"env": {
|
|
1460
|
-
"account": "myshop_merchant",
|
|
1461
|
-
"network": "mainnet",
|
|
1462
|
-
"no_cache": true
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
```
|
|
1467
|
-
|
|
1468
|
-
**Note**: This step must be performed before publishing the Service. Once published, the Machine cannot be bound.
|
|
1469
|
-
|
|
1470
|
-
***
|
|
1471
|
-
|
|
1472
|
-
### Step 8: Create Service Guards (Optional)
|
|
1473
|
-
|
|
1474
|
-
Create guards for Service order_allocators (if needed).
|
|
1475
|
-
|
|
1476
|
-
**Guard List:**
|
|
1477
|
-
|
|
1478
|
-
| # | Guard Name | Purpose |
|
|
1479
|
-
|---|------------|---------|
|
|
1480
|
-
| 5 | `service_merchant_win_v2` | Verify node in [Order Complete, Wonderful, Return Fail] |
|
|
1481
|
-
| 6 | `service_customer_win_v2` | Verify node in [Lost, Return Complete] |
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
***
|
|
1486
|
-
|
|
1487
|
-
### Step 9: Create Arbitration Object
|
|
1488
|
-
|
|
1489
|
-
Create an Arbitration object as the final on-chain mechanism for protecting user rights.
|
|
1490
|
-
|
|
1491
|
-
**IMPORTANT**: Arbitration `voting_guard` must use object format with `op` and `guards` array.
|
|
1492
|
-
|
|
1493
|
-
#### Step 9.1: Create an Independent Permission for Arbitration
|
|
1494
|
-
|
|
1495
|
-
> **WHY a separate Permission?** The Service contract (`service.move` → `arbitration_add_imp`) asserts `arbitration.permission != self.permission` when an Arbitration is bound to a Service. If the Arbitration shared the Service's Permission (`myshop_perm_v2`), the binding in Step 10 would abort with `E_ARBITRATION_PERMISSION_CONFLICT`. Create a dedicated Permission `myshop_arb_perm_v2` first.
|
|
1496
|
-
|
|
1497
|
-
**Prompt**: Create permission object "myshop\_arb\_perm\_v2".
|
|
1498
|
-
|
|
1499
|
-
```json
|
|
1500
|
-
{
|
|
1501
|
-
"tool": "onchain_operations",
|
|
1502
|
-
"data": {
|
|
1503
|
-
"operation_type": "permission",
|
|
1504
|
-
"data": {
|
|
1505
|
-
"object": {
|
|
1506
|
-
"name": "myshop_arb_perm_v2",
|
|
1507
|
-
"replaceExistName": true
|
|
1508
|
-
},
|
|
1509
|
-
"description": "Independent Permission for the MyShop Arbitration object. MUST differ from the Service Permission (myshop_perm_v2) — the Service contract asserts arbitration.permission != service.permission on binding."
|
|
1510
|
-
},
|
|
1511
|
-
"env": {
|
|
1512
|
-
"account": "myshop_merchant",
|
|
1513
|
-
"network": "mainnet",
|
|
1514
|
-
"no_cache": true
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
```
|
|
1519
|
-
|
|
1520
|
-
#### Step 9.2: Create the Arbitration Object
|
|
1521
|
-
|
|
1522
|
-
**Prompt**: Create arbitration object "myshop\_arbitration\_v2" with permission "myshop\_arb\_perm\_v2".
|
|
1523
|
-
|
|
1524
|
-
```json
|
|
1525
|
-
{
|
|
1526
|
-
"tool": "onchain_operations",
|
|
1527
|
-
"data": {
|
|
1528
|
-
"operation_type": "arbitration",
|
|
1529
|
-
"data": {
|
|
1530
|
-
"object": {
|
|
1531
|
-
"name": "myshop_arbitration_v2",
|
|
1532
|
-
"replaceExistName": true,
|
|
1533
|
-
"permission": "myshop_arb_perm_v2"
|
|
1534
|
-
},
|
|
1535
|
-
"description": "Arbitration for MyShop Advanced - Final dispute resolution mechanism",
|
|
1536
|
-
"voting_guard": {
|
|
1537
|
-
"op": "add",
|
|
1538
|
-
"guards": [
|
|
1539
|
-
{
|
|
1540
|
-
"guard": "machine_merkle_root_v2",
|
|
1541
|
-
"vote_weight": {
|
|
1542
|
-
"FixedValue": 1
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
]
|
|
1546
|
-
}
|
|
1547
|
-
},
|
|
1548
|
-
"env": {
|
|
1549
|
-
"account": "myshop_merchant",
|
|
1550
|
-
"network": "mainnet",
|
|
1551
|
-
"no_cache": true
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
```
|
|
1556
|
-
|
|
1557
|
-
**Note**: Arbitration object is automatically published upon creation. No separate publish step is required.
|
|
1558
|
-
```
|
|
1559
|
-
|
|
1560
|
-
***
|
|
1561
|
-
|
|
1562
|
-
### Step 10: Configure Order Allocators and Publish
|
|
1563
|
-
|
|
1564
|
-
Configure order_allocators to define fund distribution rules, then publish the Service.
|
|
1565
|
-
|
|
1566
|
-
> **Pre-Publish Verification (Mandatory)**: Before publishing the Service, verify all bindings are correct: Machine, Arbitration, and order_allocators. Once published, the Machine and order_allocators become permanently immutable (L1-locked). Use `query_toolkit` to confirm the Service state:
|
|
1567
|
-
>
|
|
1568
|
-
> ```json
|
|
1569
|
-
> {
|
|
1570
|
-
> "tool": "query_toolkit",
|
|
1571
|
-
> "data": {
|
|
1572
|
-
> "query_type": "onchain_objects",
|
|
1573
|
-
> "objects": ["three_body_signature_service_v2"],
|
|
1574
|
-
> "network": "mainnet",
|
|
1575
|
-
> "no_cache": true
|
|
1576
|
-
> }
|
|
1577
|
-
> }
|
|
1578
|
-
> ```
|
|
1579
|
-
>
|
|
1580
|
-
> Confirm with the user that all bindings and configurations are correct before proceeding to publish.
|
|
1581
|
-
|
|
1582
|
-
**IMPORTANT**: Service must have order_allocators configured before publishing. Once published, order_allocators becomes immutable.
|
|
1583
|
-
|
|
1584
|
-
**Prompt**: Configure order_allocators and publish service "three\_body\_signature\_service\_v2".
|
|
1585
|
-
|
|
1586
|
-
```json
|
|
1587
|
-
{
|
|
1588
|
-
"tool": "onchain_operations",
|
|
1589
|
-
"data": {
|
|
1590
|
-
"operation_type": "service",
|
|
1591
|
-
"data": {
|
|
1592
|
-
"object": "three_body_signature_service_v2",
|
|
1593
|
-
"sales": {
|
|
1594
|
-
"op": "add",
|
|
1595
|
-
"sales": [
|
|
1596
|
-
{
|
|
1597
|
-
"name": "The Three-Body Problem + Author Signature",
|
|
1598
|
-
"price": 100000000,
|
|
1599
|
-
"stock": 100,
|
|
1600
|
-
"suspension": false,
|
|
1601
|
-
"wip": "https://wowok.net/test/three_body.wip",
|
|
1602
|
-
"wip_hash": "03c18561efa8faf4d75480eb1f732c4a46ffde95599e92eca06167785fc07a5b"
|
|
1603
|
-
}
|
|
1604
|
-
]
|
|
1605
|
-
},
|
|
1606
|
-
"order_allocators": {
|
|
1607
|
-
"description": "Order fund allocation - 100% to Treasury when order complete/wonderful/return fail, 100% to Order owner when lost/return complete",
|
|
1608
|
-
"threshold": 1,
|
|
1609
|
-
"allocators": [
|
|
1610
|
-
{
|
|
1611
|
-
"guard": "service_merchant_win_v2",
|
|
1612
|
-
"sharing": [
|
|
1613
|
-
{
|
|
1614
|
-
"who": {"Entity": {"name_or_address": "myshop_treasury_v2"}},
|
|
1615
|
-
"sharing": 10000,
|
|
1616
|
-
"mode": "Rate"
|
|
1617
|
-
}
|
|
1618
|
-
]
|
|
1619
|
-
},
|
|
1620
|
-
{
|
|
1621
|
-
"guard": "service_customer_win_v2",
|
|
1622
|
-
"sharing": [
|
|
1623
|
-
{
|
|
1624
|
-
"who": {"Signer": "signer"},
|
|
1625
|
-
"sharing": 10000,
|
|
1626
|
-
"mode": "Rate"
|
|
1627
|
-
}
|
|
1628
|
-
]
|
|
1629
|
-
}
|
|
1630
|
-
]
|
|
1631
|
-
},
|
|
1632
|
-
"arbitrations": {
|
|
1633
|
-
"op": "add",
|
|
1634
|
-
"objects": ["myshop_arbitration_v2"]
|
|
1635
|
-
},
|
|
1636
|
-
"publish": true
|
|
1637
|
-
},
|
|
1638
|
-
"env": {
|
|
1639
|
-
"account": "myshop_merchant",
|
|
1640
|
-
"network": "mainnet",
|
|
1641
|
-
"no_cache": true,
|
|
1642
|
-
"confirmed": true
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
```
|
|
1647
|
-
|
|
1648
|
-
**Fund Allocation Rules:**
|
|
1649
|
-
|
|
1650
|
-
| Guard | Condition | Recipient | Amount | Verifier Level |
|
|
1651
|
-
|-------|-----------|-----------|--------|----------------|
|
|
1652
|
-
| service_merchant_win_v2 | Node is Order Complete / Wonderful / Return Fail | Treasury (merchant revenue aggregation) | 100% | Level 3 (no Signer binding) |
|
|
1653
|
-
| service_customer_win_v2 | Node is Lost / Return Complete | Order owner (customer, via Signer) | 100% | Level 2 dynamic (Signer == order.owner) |
|
|
1654
|
-
|
|
1655
|
-
**Recipient Types:**
|
|
1656
|
-
- `{ "Entity": { "name_or_address": "myshop_treasury_v2" } }` - Funds flow to the fixed Treasury address (merchant revenue aggregation). Safest — funds go to a fixed recipient regardless of caller. Uses the same Permission as the Service for governance consistency. **No Signer binding needed in the Guard** (R-C3-06 safe, Level 3 scene-combined).
|
|
1657
|
-
- `{ "Signer": "signer" }` - Transaction sender (caller). **⚠️ R-C3-06 Risk**: If the Guard does NOT bind the Signer to an authorized address, anyone who passes the Guard can steal 100% of funds. Safe ONLY when the Guard includes a `logic_equal[context(Signer), <authorized_address_or_query>]` check. This example uses Level 2 dynamic binding (`query("order.owner")`) — funds flow to the order's rightful owner.
|
|
1658
|
-
|
|
1659
|
-
> **R-C3-06 Risk Elimination — Guard + Sharing Coupling**: The `order_allocators` scene couples Guard verification (WHO can trigger) with sharing recipient (WHERE funds go). This example uses two verifier constraint levels:
|
|
1660
|
-
> - **Merchant win allocator** (`sharing.who = Entity → myshop_treasury_v2`, **Level 3 scene-combined**): Funds flow to the fixed Treasury address. Inherently safe — funds go to a fixed recipient regardless of caller. The `service_merchant_win_v2` Guard does NOT bind `context(Signer)` — the scene itself (Entity sharing to Treasury) ensures fund-flow safety. This is the recommended Level 3 pattern: no Signer binding, no R-C4-04 lock-in risk, no inconvenience.
|
|
1661
|
-
> - **Customer win allocator** (`sharing.who = Signer`, **Level 2 dynamic binding**): Funds flow to the caller. Safe ONLY because `service_customer_win_v2` Guard binds `context(Signer)` to `query("order.owner")` (dynamic query — Level 2). This ensures funds always flow to the order's rightful owner — only the customer who placed the order can receive the refund.
|
|
1662
|
-
>
|
|
1663
|
-
> **Treasury-First Rule**: Following the fund-flow design pattern established in the Insurance example, merchant revenue flows to `myshop_treasury_v2` (not the Service address). This aggregates public funds for operational distribution and makes the allocator inherently safe (R-C3-06). The Treasury uses the same Permission as the Service (`myshop_perm_v2`) for governance consistency.
|
|
1664
|
-
```
|
|
1665
|
-
|
|
1666
|
-
### Verifier Constraint Design Notes
|
|
1667
|
-
|
|
1668
|
-
This example demonstrates all three verifier constraint levels across its Guards. The verifier constraint level classifies how strictly the Signer identity is constrained, trading off security against convenience.
|
|
1669
|
-
|
|
1670
|
-
| Guard | Level | Pattern | Why |
|
|
1671
|
-
|-------|-------|---------|-----|
|
|
1672
|
-
| Guard 1-3 (machine_merkle_root_v2, machine_service_order_v2, machine_time_*) | Level 3 | No Signer binding | Machine forward's `permissionIndex` already verifies operator identity — Signer binding is redundant |
|
|
1673
|
-
| Guard 4 (service_merchant_win_v2) | Level 3 | No Signer binding | Allocator uses `sharing.who=Entity` (myshop_treasury_v2) — funds flow to fixed Treasury regardless of caller (R-C3-06 safe). Two-fold verification: node + order.service binding |
|
|
1674
|
-
| Guard 5 (machine_service_order_v2) | Level 3 | No Signer binding | Project-binding only (order.service check); machine forward verifies operator |
|
|
1675
|
-
| Guard 6 (service_customer_win_v2) | Level 2 dynamic | Signer == query("order.owner") | Allocator uses `sharing.who=Signer` — funds flow to caller, must bind to order owner to prevent theft |
|
|
1676
|
-
| Reward guards (reward_wonderful_v2, reward_lost_v2, reward_shipping_timeout_v2) | Level 3 | No Signer binding | One-time claim via record count; funds flow to fixed reward pool recipient |
|
|
1677
|
-
|
|
1678
|
-
**Key design decisions**:
|
|
1679
|
-
|
|
1680
|
-
1. **Merchant funds → Treasury (not Service)**: Following the Treasury-first rule, merchant revenue flows to `myshop_treasury_v2` (created with the same Permission as the Service). This aggregates public funds for operations and distribution, and makes the allocator inherently safe (R-C3-06) — no Signer binding needed (Level 3).
|
|
1681
|
-
|
|
1682
|
-
2. **Customer refunds → order.owner (dynamic)**: Customer refunds must go to the actual customer who placed the order. The Level 2 dynamic binding (`query("order.owner")`) ensures only the rightful owner receives the refund, regardless of who calls the transaction. Unlike Level 1 (fixed address), this survives customer account changes.
|
|
1683
|
-
|
|
1684
|
-
3. **No Level 1 strict binding anywhere**: No Guard uses `logic_equal[context(Signer), fixed_address]` because:
|
|
1685
|
-
- The merchant role may change (personnel rotation) — Level 1 would lock the Guard to one address permanently
|
|
1686
|
-
- The Treasury pattern makes Signer binding unnecessary for the merchant allocator (Level 3)
|
|
1687
|
-
- The dynamic `order.owner` query is more appropriate for customer refunds (Level 2 dynamic)
|
|
1688
|
-
- Level 1 would trigger R-C4-04 (convenience warning) and create operational risk
|
|
1689
|
-
|
|
1690
|
-
**Alternative designs considered**:
|
|
1691
|
-
- **Guard 4 could use Level 2 identity-set** (merchant OR admin via permission.owner OR has admin) — **rejected** because Treasury (Entity sharing) already makes Signer binding redundant. Adding Level 2 would add complexity without safety benefit.
|
|
1692
|
-
- **Guard 6 could use Level 2 identity-set** (order.owner OR order.agent via 1562 OR 1567) — **viable** if agents should be able to trigger refunds on behalf of customers. The current single-customer design (Level 2 dynamic, `order.owner` only) is simpler and sufficient for this example. See `tpl_allocator_identity_set_order_holder` template for the identity-set construction pattern.
|
|
1693
|
-
- **Guard 4 could use Level 2 dynamic permission** (permission.owner OR has admin, with dynamic permission via 1488) — **viable** for scenarios where the Service may rotate its permission. See `tpl_allocator_identity_set_service_provider_dynamic` template for this pattern. Rejected here because the Treasury pattern already provides fund-flow safety without Signer binding.
|
|
1694
|
-
|
|
1695
|
-
***
|
|
1696
|
-
|
|
1697
|
-
### Step 11: Create Empty Reward Object (Optional)
|
|
1698
|
-
|
|
1699
|
-
Create an empty reward object first. This object will be referenced by reward guards to prevent double-claiming.
|
|
1700
|
-
|
|
1701
|
-
**Prompt**: Create empty reward object.
|
|
1702
|
-
|
|
1703
|
-
```json
|
|
1704
|
-
{
|
|
1705
|
-
"tool": "onchain_operations",
|
|
1706
|
-
"data": {
|
|
1707
|
-
"operation_type": "reward",
|
|
1708
|
-
"data": {
|
|
1709
|
-
"object": {
|
|
1710
|
-
"name": "myshop_reward_v2",
|
|
1711
|
-
"replaceExistName": true,
|
|
1712
|
-
"permission": "myshop_perm_v2"
|
|
1713
|
-
},
|
|
1714
|
-
"description": "MyShop reward pool for wonderful service and compensation"
|
|
1715
|
-
},
|
|
1716
|
-
"env": {
|
|
1717
|
-
"account": "myshop_merchant",
|
|
1718
|
-
"network": "mainnet",
|
|
1719
|
-
"no_cache": true
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
```
|
|
1724
|
-
|
|
1725
|
-
***
|
|
1726
|
-
|
|
1727
|
-
### Step 11b: Bind Reward to Service (Post-Publish)
|
|
1728
|
-
|
|
1729
|
-
The Reward object only exists now, so the `rewards` binding is done here — deliberately AFTER publish. `rewards add` is an **L3 operation** (remains mutable after publish; only remove/clear requires pause + lock), unlike `machine` and `order_allocators` which are L1-locked at publish. This ordering also avoids referencing a not-yet-created object during the Step 10 publish call.
|
|
1730
|
-
|
|
1731
|
-
**Prompt**: Add reward "myshop\_reward\_v2" to service "three\_body\_signature\_service\_v2".
|
|
1732
|
-
|
|
1733
|
-
```json
|
|
1734
|
-
{
|
|
1735
|
-
"tool": "onchain_operations",
|
|
1736
|
-
"data": {
|
|
1737
|
-
"operation_type": "service",
|
|
1738
|
-
"data": {
|
|
1739
|
-
"object": "three_body_signature_service_v2",
|
|
1740
|
-
"rewards": {
|
|
1741
|
-
"op": "add",
|
|
1742
|
-
"objects": ["myshop_reward_v2"]
|
|
1743
|
-
}
|
|
1744
|
-
},
|
|
1745
|
-
"env": {
|
|
1746
|
-
"account": "myshop_merchant",
|
|
1747
|
-
"network": "mainnet",
|
|
1748
|
-
"no_cache": true
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
```
|
|
1753
|
-
|
|
1754
|
-
***
|
|
1755
|
-
|
|
1756
|
-
### Step 12: Create Reward Guards (Optional)
|
|
1757
|
-
|
|
1758
|
-
Create guards for reward verification with double-claim protection:
|
|
1759
|
-
|
|
1760
|
-
> **Note on `query_reward_record_exists`**: The guard uses `query_reward_record_exists` with `where.storeFromId` to prevent double-claiming. The SDK automatically appends an internal table entry (type VecU8, using the **next free identifier**) for this query's parameters — you only define the business identifiers in the table (0–3 for Guards 7/8; 0–5 for Guard 9, which adds a time condition); the tool handles the rest.
|
|
1761
|
-
|
|
1762
|
-
| # | Guard Name | Purpose | Reward Amount |
|
|
1763
|
-
|---|------------|---------|---------------|
|
|
1764
|
-
**Guard 7: reward_wonderful_v2**
|
|
1765
|
-
|
|
1766
|
-
```json
|
|
1767
|
-
{
|
|
1768
|
-
"tool": "onchain_operations",
|
|
1769
|
-
"data": {
|
|
1770
|
-
"operation_type": "guard",
|
|
1771
|
-
"data": {
|
|
1772
|
-
"namedNew": {
|
|
1773
|
-
"name": "reward_wonderful_v2",
|
|
1774
|
-
"replaceExistName": true
|
|
1775
|
-
},
|
|
1776
|
-
"description": "Verify order at Wonderful node for reward, signer must be order owner, order belongs to this service, and not claimed before",
|
|
1777
|
-
"table": [
|
|
1778
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
1779
|
-
{"identifier": 1, "b_submission": false, "value_type": "String", "value": "Wonderful"},
|
|
1780
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "value": "myshop_reward_v2", "name": "reward_object"},
|
|
1781
|
-
{"identifier": 3, "b_submission": false, "value_type": "Address", "value": "three_body_signature_service_v2", "name": "service_address"}
|
|
1782
|
-
],
|
|
1783
|
-
"root": {
|
|
1784
|
-
"type": "logic_and",
|
|
1785
|
-
"nodes": [
|
|
1786
|
-
{
|
|
1787
|
-
"type": "logic_string_nocase_equal",
|
|
1788
|
-
"nodes": [
|
|
1789
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
1790
|
-
{"type": "identifier", "identifier": 1}
|
|
1791
|
-
]
|
|
1792
|
-
},
|
|
1793
|
-
{
|
|
1794
|
-
"type": "logic_equal",
|
|
1795
|
-
"nodes": [
|
|
1796
|
-
{"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
|
|
1797
|
-
{"type": "context", "context": "Signer"}
|
|
1798
|
-
]
|
|
1799
|
-
},
|
|
1800
|
-
{
|
|
1801
|
-
"type": "logic_equal",
|
|
1802
|
-
"nodes": [
|
|
1803
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
1804
|
-
{"type": "identifier", "identifier": 3}
|
|
1805
|
-
]
|
|
1806
|
-
},
|
|
1807
|
-
{
|
|
1808
|
-
"type": "logic_not",
|
|
1809
|
-
"node": {
|
|
1810
|
-
"type": "query_reward_record_exists",
|
|
1811
|
-
"object": {"identifier": 2},
|
|
1812
|
-
"where": {
|
|
1813
|
-
"storeFromId": {"identifier": 0}
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
]
|
|
1818
|
-
}
|
|
1819
|
-
},
|
|
1820
|
-
"env": {
|
|
1821
|
-
"account": "myshop_merchant",
|
|
1822
|
-
"network": "mainnet",
|
|
1823
|
-
"no_cache": true
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
```
|
|
1828
|
-
|
|
1829
|
-
**Guard 8: reward_lost_v2**
|
|
1830
|
-
|
|
1831
|
-
```json
|
|
1832
|
-
{
|
|
1833
|
-
"tool": "onchain_operations",
|
|
1834
|
-
"data": {
|
|
1835
|
-
"operation_type": "guard",
|
|
1836
|
-
"data": {
|
|
1837
|
-
"namedNew": {
|
|
1838
|
-
"name": "reward_lost_v2",
|
|
1839
|
-
"replaceExistName": true
|
|
1840
|
-
},
|
|
1841
|
-
"description": "Verify order at Lost node for compensation, signer must be order owner, order belongs to this service, and not claimed before",
|
|
1842
|
-
"table": [
|
|
1843
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
1844
|
-
{"identifier": 1, "b_submission": false, "value_type": "String", "value": "Lost"},
|
|
1845
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "value": "myshop_reward_v2", "name": "reward_object"},
|
|
1846
|
-
{"identifier": 3, "b_submission": false, "value_type": "Address", "value": "three_body_signature_service_v2", "name": "service_address"}
|
|
1847
|
-
],
|
|
1848
|
-
"root": {
|
|
1849
|
-
"type": "logic_and",
|
|
1850
|
-
"nodes": [
|
|
1851
|
-
{
|
|
1852
|
-
"type": "logic_string_nocase_equal",
|
|
1853
|
-
"nodes": [
|
|
1854
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
1855
|
-
{"type": "identifier", "identifier": 1}
|
|
1856
|
-
]
|
|
1857
|
-
},
|
|
1858
|
-
{
|
|
1859
|
-
"type": "logic_equal",
|
|
1860
|
-
"nodes": [
|
|
1861
|
-
{"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
|
|
1862
|
-
{"type": "context", "context": "Signer"}
|
|
1863
|
-
]
|
|
1864
|
-
},
|
|
1865
|
-
{
|
|
1866
|
-
"type": "logic_equal",
|
|
1867
|
-
"nodes": [
|
|
1868
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
1869
|
-
{"type": "identifier", "identifier": 3}
|
|
1870
|
-
]
|
|
1871
|
-
},
|
|
1872
|
-
{
|
|
1873
|
-
"type": "logic_not",
|
|
1874
|
-
"node": {
|
|
1875
|
-
"type": "query_reward_record_exists",
|
|
1876
|
-
"object": {"identifier": 2},
|
|
1877
|
-
"where": {
|
|
1878
|
-
"storeFromId": {"identifier": 0}
|
|
1879
|
-
}
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
]
|
|
1883
|
-
}
|
|
1884
|
-
},
|
|
1885
|
-
"env": {
|
|
1886
|
-
"account": "myshop_merchant",
|
|
1887
|
-
"network": "mainnet",
|
|
1888
|
-
"no_cache": true
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
```
|
|
1893
|
-
|
|
1894
|
-
**Guard 9: reward_shipping_timeout_v2**
|
|
1895
|
-
|
|
1896
|
-
> **Time condition included**: unlike Guards 7/8, this Guard ALSO verifies the order has been stuck at the Shipping node for ≥ 2 days (172800000 ms) — otherwise the customer could claim "timeout compensation" immediately after shipping. It uses the same secure pattern as Guard 2/3: the Progress object is submitted at runtime (Address identifier 4) and the start time is read on-chain via `query("progress.current_time")` (GUARDQUERY id 1272).
|
|
1897
|
-
>
|
|
1898
|
-
> **Claim submission contract**: claiming via this Guard requires TWO submissions — identifier 0 = Order address (as in Guards 7/8) AND identifier 4 = the order's Progress object address (e.g. `myshop_progress_v2`).
|
|
1899
|
-
|
|
1900
|
-
```json
|
|
1901
|
-
{
|
|
1902
|
-
"tool": "onchain_operations",
|
|
1903
|
-
"data": {
|
|
1904
|
-
"operation_type": "guard",
|
|
1905
|
-
"data": {
|
|
1906
|
-
"namedNew": {
|
|
1907
|
-
"name": "reward_shipping_timeout_v2",
|
|
1908
|
-
"replaceExistName": true
|
|
1909
|
-
},
|
|
1910
|
-
"description": "Verify order at Shipping node for timeout compensation: signer must be order owner, order belongs to this service, not claimed before, AND the order has been at the Shipping node for >= 2 days (Clock - progress.current_time >= 172800000 ms, progress submitted as Address identifier 4)",
|
|
1911
|
-
"table": [
|
|
1912
|
-
{"identifier": 0, "b_submission": true, "value_type": "Address", "name": "order_id"},
|
|
1913
|
-
{"identifier": 1, "b_submission": false, "value_type": "String", "value": "Shipping"},
|
|
1914
|
-
{"identifier": 2, "b_submission": false, "value_type": "Address", "value": "myshop_reward_v2", "name": "reward_object"},
|
|
1915
|
-
{"identifier": 3, "b_submission": false, "value_type": "Address", "value": "three_body_signature_service_v2", "name": "service_address"},
|
|
1916
|
-
{"identifier": 4, "b_submission": true, "value_type": "Address", "name": "progress_id"},
|
|
1917
|
-
{"identifier": 5, "b_submission": false, "value_type": "U64", "value": "172800000", "name": "timeout_ms"}
|
|
1918
|
-
],
|
|
1919
|
-
"root": {
|
|
1920
|
-
"type": "logic_and",
|
|
1921
|
-
"nodes": [
|
|
1922
|
-
{
|
|
1923
|
-
"type": "logic_string_nocase_equal",
|
|
1924
|
-
"nodes": [
|
|
1925
|
-
{"type": "query", "query": "progress.current", "object": {"identifier": 0, "convert_witness": "OrderProgress"}, "parameters": []},
|
|
1926
|
-
{"type": "identifier", "identifier": 1}
|
|
1927
|
-
]
|
|
1928
|
-
},
|
|
1929
|
-
{
|
|
1930
|
-
"type": "logic_equal",
|
|
1931
|
-
"nodes": [
|
|
1932
|
-
{"type": "query", "query": "order.owner", "object": {"identifier": 0}, "parameters": []},
|
|
1933
|
-
{"type": "context", "context": "Signer"}
|
|
1934
|
-
]
|
|
1935
|
-
},
|
|
1936
|
-
{
|
|
1937
|
-
"type": "logic_equal",
|
|
1938
|
-
"nodes": [
|
|
1939
|
-
{"type": "query", "query": "order.service", "object": {"identifier": 0}, "parameters": []},
|
|
1940
|
-
{"type": "identifier", "identifier": 3}
|
|
1941
|
-
]
|
|
1942
|
-
},
|
|
1943
|
-
{
|
|
1944
|
-
"type": "logic_as_u256_greater_or_equal",
|
|
1945
|
-
"nodes": [
|
|
1946
|
-
{
|
|
1947
|
-
"type": "calc_number_subtract",
|
|
1948
|
-
"nodes": [
|
|
1949
|
-
{"type": "context", "context": "Clock"},
|
|
1950
|
-
{"type": "query", "query": "progress.current_time", "object": {"identifier": 4}, "parameters": []}
|
|
1951
|
-
]
|
|
1952
|
-
},
|
|
1953
|
-
{"type": "identifier", "identifier": 5}
|
|
1954
|
-
]
|
|
1955
|
-
},
|
|
1956
|
-
{
|
|
1957
|
-
"type": "logic_not",
|
|
1958
|
-
"node": {
|
|
1959
|
-
"type": "query_reward_record_exists",
|
|
1960
|
-
"object": {"identifier": 2},
|
|
1961
|
-
"where": {
|
|
1962
|
-
"storeFromId": {"identifier": 0}
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
]
|
|
1967
|
-
}
|
|
1968
|
-
},
|
|
1969
|
-
"env": {
|
|
1970
|
-
"account": "myshop_merchant",
|
|
1971
|
-
"network": "mainnet",
|
|
1972
|
-
"no_cache": true
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
```
|
|
1977
|
-
|
|
1978
|
-
***
|
|
1979
|
-
|
|
1980
|
-
### Step 13: Add Reward Guards to Reward Object (Optional)
|
|
1981
|
-
|
|
1982
|
-
Add reward guards to the reward object with `store_from_id` set to the order identifier. This enables double-claim protection by storing the order ID in reward records.
|
|
1983
|
-
|
|
1984
|
-
**Prompt**: Add reward guards with store_from_id.
|
|
1985
|
-
|
|
1986
|
-
```json
|
|
1987
|
-
{
|
|
1988
|
-
"tool": "onchain_operations",
|
|
1989
|
-
"data": {
|
|
1990
|
-
"operation_type": "reward",
|
|
1991
|
-
"data": {
|
|
1992
|
-
"object": "myshop_reward_v2",
|
|
1993
|
-
"guard_add": [
|
|
1994
|
-
{
|
|
1995
|
-
"guard": "reward_wonderful_v2",
|
|
1996
|
-
"recipient": {"Signer": "signer"},
|
|
1997
|
-
"amount": {"type": "Fixed", "value": 10000},
|
|
1998
|
-
"store_from_id": 0
|
|
1999
|
-
},
|
|
2000
|
-
{
|
|
2001
|
-
"guard": "reward_lost_v2",
|
|
2002
|
-
"recipient": {"Signer": "signer"},
|
|
2003
|
-
"amount": {"type": "Fixed", "value": 20000},
|
|
2004
|
-
"store_from_id": 0
|
|
2005
|
-
},
|
|
2006
|
-
{
|
|
2007
|
-
"guard": "reward_shipping_timeout_v2",
|
|
2008
|
-
"recipient": {"Signer": "signer"},
|
|
2009
|
-
"amount": {"type": "Fixed", "value": 20000},
|
|
2010
|
-
"store_from_id": 0
|
|
2011
|
-
}
|
|
2012
|
-
]
|
|
2013
|
-
},
|
|
2014
|
-
"env": {
|
|
2015
|
-
"account": "myshop_merchant",
|
|
2016
|
-
"network": "mainnet",
|
|
2017
|
-
"no_cache": true
|
|
2018
|
-
}
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
```
|
|
2022
|
-
|
|
2023
|
-
***
|
|
2024
|
-
|
|
2025
|
-
### Step 14: Deposit to Reward Pool (Optional)
|
|
2026
|
-
|
|
2027
|
-
Deposit WOW tokens to the reward pool for rewards and compensation.
|
|
2028
|
-
|
|
2029
|
-
**Prompt**: Deposit to reward object "myshop\_reward\_v2".
|
|
2030
|
-
|
|
2031
|
-
```json
|
|
2032
|
-
{
|
|
2033
|
-
"tool": "onchain_operations",
|
|
2034
|
-
"data": {
|
|
2035
|
-
"operation_type": "reward",
|
|
2036
|
-
"data": {
|
|
2037
|
-
"object": "myshop_reward_v2",
|
|
2038
|
-
"coin_add": {
|
|
2039
|
-
"balance": 150000000
|
|
2040
|
-
}
|
|
2041
|
-
},
|
|
2042
|
-
"env": {
|
|
2043
|
-
"account": "myshop_merchant",
|
|
2044
|
-
"network": "mainnet",
|
|
2045
|
-
"no_cache": true
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
}
|
|
2049
|
-
```
|
|
2050
|
-
|
|
2051
|
-
***
|
|
2052
|
-
|
|
2053
|
-
## Part 3: Customer Order Flow
|
|
2054
|
-
|
|
2055
|
-
### Step 1: Create Order with WIP Verification
|
|
2056
|
-
|
|
2057
|
-
Customer places an order for "The Three-Body Problem + Author Signature" with WIP hash verification.
|
|
2058
|
-
|
|
2059
|
-
**Prompt**: Customer "myshop\_customer" creates an order.
|
|
2060
|
-
|
|
2061
|
-
```json
|
|
2062
|
-
{
|
|
2063
|
-
"tool": "onchain_operations",
|
|
2064
|
-
"data": {
|
|
2065
|
-
"operation_type": "service",
|
|
2066
|
-
"data": {
|
|
2067
|
-
"object": "three_body_signature_service_v2",
|
|
2068
|
-
"order_new": {
|
|
2069
|
-
"buy": {
|
|
2070
|
-
"items": [
|
|
2071
|
-
{
|
|
2072
|
-
"name": "The Three-Body Problem + Author Signature",
|
|
2073
|
-
"stock": 1,
|
|
2074
|
-
"wip_hash": "03c18561efa8faf4d75480eb1f732c4a46ffde95599e92eca06167785fc07a5b"
|
|
2075
|
-
}
|
|
2076
|
-
],
|
|
2077
|
-
"total_pay": {
|
|
2078
|
-
"balance": 100000000
|
|
2079
|
-
},
|
|
2080
|
-
"payment_remark": "To my dear friend - keep exploring the universe"
|
|
2081
|
-
},
|
|
2082
|
-
"namedNewOrder": {
|
|
2083
|
-
"name": "myshop_order_v2",
|
|
2084
|
-
"replaceExistName": true
|
|
2085
|
-
},
|
|
2086
|
-
"namedNewAllocation": {
|
|
2087
|
-
"name": "myshop_allocation_v2",
|
|
2088
|
-
"replaceExistName": true
|
|
2089
|
-
},
|
|
2090
|
-
"namedNewProgress": {
|
|
2091
|
-
"name": "myshop_progress_v2",
|
|
2092
|
-
"replaceExistName": true
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
},
|
|
2096
|
-
"env": {
|
|
2097
|
-
"account": "myshop_customer",
|
|
2098
|
-
"network": "mainnet",
|
|
2099
|
-
"no_cache": true
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2103
|
-
```
|
|
2104
|
-
|
|
2105
|
-
***
|
|
2106
|
-
|
|
2107
|
-
### Step 2: Merchant Confirms Order
|
|
2108
|
-
|
|
2109
|
-
Merchant confirms the order. This step uses permission index 1000 (no Guard submission needed).
|
|
2110
|
-
|
|
2111
|
-
**Prompt**: Merchant confirms order.
|
|
2112
|
-
|
|
2113
|
-
```json
|
|
2114
|
-
{
|
|
2115
|
-
"tool": "onchain_operations",
|
|
2116
|
-
"data": {
|
|
2117
|
-
"operation_type": "progress",
|
|
2118
|
-
"data": {
|
|
2119
|
-
"object": "myshop_progress_v2",
|
|
2120
|
-
"operate": {
|
|
2121
|
-
"operation": {
|
|
2122
|
-
"next_node_name": "Order Confirmed",
|
|
2123
|
-
"forward": "Confirm Order"
|
|
2124
|
-
},
|
|
2125
|
-
"op": "next",
|
|
2126
|
-
"message": "Order confirmed by merchant"
|
|
2127
|
-
}
|
|
2128
|
-
},
|
|
2129
|
-
"env": {
|
|
2130
|
-
"account": "myshop_merchant",
|
|
2131
|
-
"network": "mainnet",
|
|
2132
|
-
"no_cache": true
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
}
|
|
2136
|
-
```
|
|
2137
|
-
|
|
2138
|
-
***
|
|
2139
|
-
|
|
2140
|
-
### Step 3: Merchant Starts Shipping
|
|
2141
|
-
|
|
2142
|
-
Merchant starts shipping after signature service is completed. The merchant submits a Merkle Root (66-character hex string with 0x prefix) proving communication with the customer via Messenger.
|
|
2143
|
-
|
|
2144
|
-
**Prompt**: Merchant starts shipping with Merkle Root submission.
|
|
2145
|
-
|
|
2146
|
-
```json
|
|
2147
|
-
{
|
|
2148
|
-
"tool": "onchain_operations",
|
|
2149
|
-
"data": {
|
|
2150
|
-
"operation_type": "progress",
|
|
2151
|
-
"data": {
|
|
2152
|
-
"object": "myshop_progress_v2",
|
|
2153
|
-
"operate": {
|
|
2154
|
-
"operation": {
|
|
2155
|
-
"next_node_name": "Shipping",
|
|
2156
|
-
"forward": "Confirm Signature and Submit Merkle Root"
|
|
2157
|
-
},
|
|
2158
|
-
"op": "next",
|
|
2159
|
-
"message": "Shipping started - signature completed and Merkle Root submitted"
|
|
2160
|
-
}
|
|
2161
|
-
},
|
|
2162
|
-
"env": {
|
|
2163
|
-
"account": "myshop_merchant",
|
|
2164
|
-
"network": "mainnet",
|
|
2165
|
-
"no_cache": true
|
|
2166
|
-
},
|
|
2167
|
-
"submission": {
|
|
2168
|
-
"type": "submission",
|
|
2169
|
-
"guard": [
|
|
2170
|
-
{
|
|
2171
|
-
"object": "machine_merkle_root_v2",
|
|
2172
|
-
"impack": true
|
|
2173
|
-
}
|
|
2174
|
-
],
|
|
2175
|
-
"submission": [
|
|
2176
|
-
{
|
|
2177
|
-
"guard": "machine_merkle_root_v2",
|
|
2178
|
-
"submission": [
|
|
2179
|
-
{
|
|
2180
|
-
"identifier": 0,
|
|
2181
|
-
"b_submission": true,
|
|
2182
|
-
"value_type": "String",
|
|
2183
|
-
"value": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
2184
|
-
}
|
|
2185
|
-
]
|
|
2186
|
-
}
|
|
2187
|
-
]
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
```
|
|
2192
|
-
|
|
2193
|
-
**Note**: The `machine_merkle_root_v2` Guard expects a 66-character string (including "0x" prefix). The Guard validates that the string length equals 66 characters. The Merkle Root is computed from the Messenger conversation between merchant and customer, proving that tracking information was exchanged.
|
|
2194
|
-
|
|
2195
|
-
***
|
|
2196
|
-
|
|
2197
|
-
### Step 4: Customer Confirms Delivery
|
|
2198
|
-
|
|
2199
|
-
Customer confirms receipt of goods.
|
|
2200
|
-
|
|
2201
|
-
**Prompt**: Customer confirms delivery.
|
|
2202
|
-
|
|
2203
|
-
```json
|
|
2204
|
-
{
|
|
2205
|
-
"tool": "onchain_operations",
|
|
2206
|
-
"data": {
|
|
2207
|
-
"operation_type": "order",
|
|
2208
|
-
"data": {
|
|
2209
|
-
"object": "myshop_order_v2",
|
|
2210
|
-
"progress": {
|
|
2211
|
-
"operation": {
|
|
2212
|
-
"next_node_name": "Delivery Complete",
|
|
2213
|
-
"forward": "Confirm Receipt"
|
|
2214
|
-
},
|
|
2215
|
-
"op": "next",
|
|
2216
|
-
"message": "Delivery confirmed - goods received"
|
|
2217
|
-
}
|
|
2218
|
-
},
|
|
2219
|
-
"env": {
|
|
2220
|
-
"account": "myshop_customer",
|
|
2221
|
-
"network": "mainnet",
|
|
2222
|
-
"no_cache": true
|
|
2223
|
-
}
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
```
|
|
2227
|
-
|
|
2228
|
-
***
|
|
2229
|
-
|
|
2230
|
-
### Step 5: Customer Rates Wonderful
|
|
2231
|
-
|
|
2232
|
-
Alternatively, customer can rate as Wonderful (very satisfied).
|
|
2233
|
-
|
|
2234
|
-
**Prompt**: Customer rates order as Wonderful.
|
|
2235
|
-
|
|
2236
|
-
```json
|
|
2237
|
-
{
|
|
2238
|
-
"tool": "onchain_operations",
|
|
2239
|
-
"data": {
|
|
2240
|
-
"operation_type": "order",
|
|
2241
|
-
"data": {
|
|
2242
|
-
"object": "myshop_order_v2",
|
|
2243
|
-
"progress": {
|
|
2244
|
-
"operation": {
|
|
2245
|
-
"next_node_name": "Wonderful",
|
|
2246
|
-
"forward": "Rate as Wonderful"
|
|
2247
|
-
},
|
|
2248
|
-
"op": "next",
|
|
2249
|
-
"message": "Rated as Wonderful - very satisfied with the service"
|
|
2250
|
-
}
|
|
2251
|
-
},
|
|
2252
|
-
"env": {
|
|
2253
|
-
"account": "myshop_customer",
|
|
2254
|
-
"network": "mainnet",
|
|
2255
|
-
"no_cache": true
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
|
-
}
|
|
2259
|
-
```
|
|
2260
|
-
|
|
2261
|
-
***
|
|
2262
|
-
|
|
2263
|
-
### Step 6: Claim Wonderful Reward
|
|
2264
|
-
|
|
2265
|
-
Customer claims Wonderful reward from reward pool.
|
|
2266
|
-
|
|
2267
|
-
**Prompt**: Customer claims Wonderful reward.
|
|
2268
|
-
|
|
2269
|
-
```json
|
|
2270
|
-
{
|
|
2271
|
-
"tool": "onchain_operations",
|
|
2272
|
-
"data": {
|
|
2273
|
-
"operation_type": "reward",
|
|
2274
|
-
"data": {
|
|
2275
|
-
"object": "myshop_reward_v2",
|
|
2276
|
-
"claim": "reward_wonderful_v2"
|
|
2277
|
-
},
|
|
2278
|
-
"env": {
|
|
2279
|
-
"account": "myshop_customer",
|
|
2280
|
-
"network": "mainnet",
|
|
2281
|
-
"no_cache": true
|
|
2282
|
-
},
|
|
2283
|
-
"submission": {
|
|
2284
|
-
"type": "submission",
|
|
2285
|
-
"guard": [
|
|
2286
|
-
{
|
|
2287
|
-
"object": "reward_wonderful_v2",
|
|
2288
|
-
"impack": true
|
|
2289
|
-
}
|
|
2290
|
-
],
|
|
2291
|
-
"submission": [
|
|
2292
|
-
{
|
|
2293
|
-
"guard": "reward_wonderful_v2",
|
|
2294
|
-
"submission": [
|
|
2295
|
-
{
|
|
2296
|
-
"identifier": 0,
|
|
2297
|
-
"b_submission": true,
|
|
2298
|
-
"value_type": "Address",
|
|
2299
|
-
"value": "myshop_order_v2"
|
|
2300
|
-
}
|
|
2301
|
-
]
|
|
2302
|
-
}
|
|
2303
|
-
]
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
}
|
|
2307
|
-
```
|
|
2308
|
-
|
|
2309
|
-
***
|
|
2310
|
-
|
|
2311
|
-
### Step 7: Order Auto-Complete or Manual Complete
|
|
2312
|
-
|
|
2313
|
-
Order can auto-complete after a time threshold or be manually completed by the merchant.
|
|
2314
|
-
|
|
2315
|
-
**Auto-Complete from Shipping (10 days, guard: machine_time_10d_v2)**:
|
|
2316
|
-
|
|
2317
|
-
```json
|
|
2318
|
-
{
|
|
2319
|
-
"tool": "onchain_operations",
|
|
2320
|
-
"data": {
|
|
2321
|
-
"operation_type": "progress",
|
|
2322
|
-
"data": {
|
|
2323
|
-
"object": "myshop_progress_v2",
|
|
2324
|
-
"operate": {
|
|
2325
|
-
"operation": {
|
|
2326
|
-
"next_node_name": "Order Complete",
|
|
2327
|
-
"forward": "Auto Complete from Shipping"
|
|
2328
|
-
},
|
|
2329
|
-
"op": "next",
|
|
2330
|
-
"message": "Order auto-completed after 10 days"
|
|
2331
|
-
}
|
|
2332
|
-
},
|
|
2333
|
-
"env": {
|
|
2334
|
-
"account": "myshop_merchant",
|
|
2335
|
-
"network": "mainnet",
|
|
2336
|
-
"no_cache": true
|
|
2337
|
-
},
|
|
2338
|
-
"submission": {
|
|
2339
|
-
"type": "submission",
|
|
2340
|
-
"guard": [
|
|
2341
|
-
{
|
|
2342
|
-
"object": "machine_time_10d_v2",
|
|
2343
|
-
"impack": true
|
|
2344
|
-
}
|
|
2345
|
-
],
|
|
2346
|
-
"submission": [
|
|
2347
|
-
{
|
|
2348
|
-
"guard": "machine_time_10d_v2",
|
|
2349
|
-
"submission": [
|
|
2350
|
-
{
|
|
2351
|
-
"identifier": 0,
|
|
2352
|
-
"b_submission": true,
|
|
2353
|
-
"value_type": "Address",
|
|
2354
|
-
"value": "myshop_progress_v2"
|
|
2355
|
-
}
|
|
2356
|
-
]
|
|
2357
|
-
}
|
|
2358
|
-
]
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
```
|
|
2363
|
-
|
|
2364
|
-
**Manual Complete from Delivery Complete (no Guard)**:
|
|
2365
|
-
|
|
2366
|
-
The "Complete Order" forward (Delivery Complete → Order Complete, permissionIndex 1001) has no Guard, so no `submission` is needed.
|
|
2367
|
-
|
|
2368
|
-
```json
|
|
2369
|
-
{
|
|
2370
|
-
"tool": "onchain_operations",
|
|
2371
|
-
"data": {
|
|
2372
|
-
"operation_type": "progress",
|
|
2373
|
-
"data": {
|
|
2374
|
-
"object": "myshop_progress_v2",
|
|
2375
|
-
"operate": {
|
|
2376
|
-
"operation": {
|
|
2377
|
-
"next_node_name": "Order Complete",
|
|
2378
|
-
"forward": "Complete Order"
|
|
2379
|
-
},
|
|
2380
|
-
"op": "next",
|
|
2381
|
-
"message": "Order manually completed by merchant after delivery"
|
|
2382
|
-
}
|
|
2383
|
-
},
|
|
2384
|
-
"env": {
|
|
2385
|
-
"account": "myshop_merchant",
|
|
2386
|
-
"network": "mainnet",
|
|
2387
|
-
"no_cache": true
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
```
|
|
2392
|
-
|
|
2393
|
-
> **Note**: There is no "auto-complete from Delivery Complete" forward in this Machine — an earlier 2-day variant referenced a non-existent forward plus the illustrative `machine_time_2d_v2` Guard (see the Step 4 note). From Delivery Complete, the order finishes via "Complete Order" (above), "Rate as Wonderful" (Step 5), or a return path (Step 9).
|
|
2394
|
-
|
|
2395
|
-
***
|
|
2396
|
-
|
|
2397
|
-
### Step 8: Lost Package Handling
|
|
2398
|
-
|
|
2399
|
-
If package is lost, customer reports and merchant confirms.
|
|
2400
|
-
|
|
2401
|
-
**Step 8.1: Customer Reports Lost**
|
|
2402
|
-
|
|
2403
|
-
```json
|
|
2404
|
-
{
|
|
2405
|
-
"tool": "onchain_operations",
|
|
2406
|
-
"data": {
|
|
2407
|
-
"operation_type": "order",
|
|
2408
|
-
"data": {
|
|
2409
|
-
"object": "myshop_order_v2",
|
|
2410
|
-
"progress": {
|
|
2411
|
-
"operation": {
|
|
2412
|
-
"next_node_name": "Lost",
|
|
2413
|
-
"forward": "Report Lost"
|
|
2414
|
-
},
|
|
2415
|
-
"op": "next",
|
|
2416
|
-
"message": "Package reported as lost"
|
|
2417
|
-
}
|
|
2418
|
-
},
|
|
2419
|
-
"env": {
|
|
2420
|
-
"account": "myshop_customer",
|
|
2421
|
-
"network": "mainnet",
|
|
2422
|
-
"no_cache": true
|
|
2423
|
-
}
|
|
2424
|
-
}
|
|
2425
|
-
}
|
|
2426
|
-
```
|
|
2427
|
-
|
|
2428
|
-
**Step 8.2: Merchant Confirms Lost**
|
|
2429
|
-
|
|
2430
|
-
```json
|
|
2431
|
-
{
|
|
2432
|
-
"tool": "onchain_operations",
|
|
2433
|
-
"data": {
|
|
2434
|
-
"operation_type": "progress",
|
|
2435
|
-
"data": {
|
|
2436
|
-
"object": "myshop_progress_v2",
|
|
2437
|
-
"operate": {
|
|
2438
|
-
"operation": {
|
|
2439
|
-
"next_node_name": "Lost",
|
|
2440
|
-
"forward": "Confirm Lost with Merkle Root"
|
|
2441
|
-
},
|
|
2442
|
-
"op": "next",
|
|
2443
|
-
"message": "Lost confirmed with Merkle Root"
|
|
2444
|
-
}
|
|
2445
|
-
},
|
|
2446
|
-
"env": {
|
|
2447
|
-
"account": "myshop_merchant",
|
|
2448
|
-
"network": "mainnet",
|
|
2449
|
-
"no_cache": true
|
|
2450
|
-
},
|
|
2451
|
-
"submission": {
|
|
2452
|
-
"type": "submission",
|
|
2453
|
-
"guard": [
|
|
2454
|
-
{
|
|
2455
|
-
"object": "machine_merkle_root_v2",
|
|
2456
|
-
"impack": true
|
|
2457
|
-
}
|
|
2458
|
-
],
|
|
2459
|
-
"submission": [
|
|
2460
|
-
{
|
|
2461
|
-
"guard": "machine_merkle_root_v2",
|
|
2462
|
-
"submission": [
|
|
2463
|
-
{
|
|
2464
|
-
"identifier": 0,
|
|
2465
|
-
"b_submission": true,
|
|
2466
|
-
"value_type": "String",
|
|
2467
|
-
"value": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
2468
|
-
}
|
|
2469
|
-
]
|
|
2470
|
-
}
|
|
2471
|
-
]
|
|
2472
|
-
}
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
|
-
```
|
|
2476
|
-
|
|
2477
|
-
**Step 8.3: Claim Lost Compensation**
|
|
2478
|
-
|
|
2479
|
-
```json
|
|
2480
|
-
{
|
|
2481
|
-
"tool": "onchain_operations",
|
|
2482
|
-
"data": {
|
|
2483
|
-
"operation_type": "reward",
|
|
2484
|
-
"data": {
|
|
2485
|
-
"object": "myshop_reward_v2",
|
|
2486
|
-
"claim": "reward_lost_v2"
|
|
2487
|
-
},
|
|
2488
|
-
"env": {
|
|
2489
|
-
"account": "myshop_customer",
|
|
2490
|
-
"network": "mainnet",
|
|
2491
|
-
"no_cache": true
|
|
2492
|
-
},
|
|
2493
|
-
"submission": {
|
|
2494
|
-
"type": "submission",
|
|
2495
|
-
"guard": [
|
|
2496
|
-
{
|
|
2497
|
-
"object": "reward_lost_v2",
|
|
2498
|
-
"impack": true
|
|
2499
|
-
}
|
|
2500
|
-
],
|
|
2501
|
-
"submission": [
|
|
2502
|
-
{
|
|
2503
|
-
"guard": "reward_lost_v2",
|
|
2504
|
-
"submission": [
|
|
2505
|
-
{
|
|
2506
|
-
"identifier": 0,
|
|
2507
|
-
"b_submission": true,
|
|
2508
|
-
"value_type": "Address",
|
|
2509
|
-
"value": "myshop_order_v2"
|
|
2510
|
-
}
|
|
2511
|
-
]
|
|
2512
|
-
}
|
|
2513
|
-
]
|
|
2514
|
-
}
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
```
|
|
2518
|
-
|
|
2519
|
-
***
|
|
2520
|
-
|
|
2521
|
-
### Step 9: Return Process (Receipt Return)
|
|
2522
|
-
|
|
2523
|
-
Customer requests return after delivery confirmation.
|
|
2524
|
-
|
|
2525
|
-
**Step 9.1: Customer Requests Return**
|
|
2526
|
-
|
|
2527
|
-
```json
|
|
2528
|
-
{
|
|
2529
|
-
"tool": "onchain_operations",
|
|
2530
|
-
"data": {
|
|
2531
|
-
"operation_type": "order",
|
|
2532
|
-
"data": {
|
|
2533
|
-
"object": "myshop_order_v2",
|
|
2534
|
-
"progress": {
|
|
2535
|
-
"operation": {
|
|
2536
|
-
"next_node_name": "Receipt Return",
|
|
2537
|
-
"forward": "Request Return with Receipt"
|
|
2538
|
-
},
|
|
2539
|
-
"op": "next",
|
|
2540
|
-
"message": "Return requested after delivery"
|
|
2541
|
-
}
|
|
2542
|
-
},
|
|
2543
|
-
"env": {
|
|
2544
|
-
"account": "myshop_customer",
|
|
2545
|
-
"network": "mainnet",
|
|
2546
|
-
"no_cache": true
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
```
|
|
2551
|
-
|
|
2552
|
-
**Step 9.2: Merchant Confirms Return Address**
|
|
2553
|
-
|
|
2554
|
-
```json
|
|
2555
|
-
{
|
|
2556
|
-
"tool": "onchain_operations",
|
|
2557
|
-
"data": {
|
|
2558
|
-
"operation_type": "progress",
|
|
2559
|
-
"data": {
|
|
2560
|
-
"object": "myshop_progress_v2",
|
|
2561
|
-
"operate": {
|
|
2562
|
-
"operation": {
|
|
2563
|
-
"next_node_name": "Receipt Return",
|
|
2564
|
-
"forward": "Confirm Return Address with Merkle Root"
|
|
2565
|
-
},
|
|
2566
|
-
"op": "next",
|
|
2567
|
-
"message": "Return address confirmed with Merkle Root"
|
|
2568
|
-
}
|
|
2569
|
-
},
|
|
2570
|
-
"env": {
|
|
2571
|
-
"account": "myshop_merchant",
|
|
2572
|
-
"network": "mainnet",
|
|
2573
|
-
"no_cache": true
|
|
2574
|
-
},
|
|
2575
|
-
"submission": {
|
|
2576
|
-
"type": "submission",
|
|
2577
|
-
"guard": [
|
|
2578
|
-
{
|
|
2579
|
-
"object": "machine_merkle_root_v2",
|
|
2580
|
-
"impack": true
|
|
2581
|
-
}
|
|
2582
|
-
],
|
|
2583
|
-
"submission": [
|
|
2584
|
-
{
|
|
2585
|
-
"guard": "machine_merkle_root_v2",
|
|
2586
|
-
"submission": [
|
|
2587
|
-
{
|
|
2588
|
-
"identifier": 0,
|
|
2589
|
-
"b_submission": true,
|
|
2590
|
-
"value_type": "String",
|
|
2591
|
-
"value": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
|
2592
|
-
}
|
|
2593
|
-
]
|
|
2594
|
-
}
|
|
2595
|
-
]
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
```
|
|
2600
|
-
|
|
2601
|
-
**Step 9.3: Customer Submits Return Merkle Root**
|
|
2602
|
-
|
|
2603
|
-
```json
|
|
2604
|
-
{
|
|
2605
|
-
"tool": "onchain_operations",
|
|
2606
|
-
"data": {
|
|
2607
|
-
"operation_type": "order",
|
|
2608
|
-
"data": {
|
|
2609
|
-
"object": "myshop_order_v2",
|
|
2610
|
-
"progress": {
|
|
2611
|
-
"operation": {
|
|
2612
|
-
"next_node_name": "Return Complete",
|
|
2613
|
-
"forward": "Submit Return Merkle Root"
|
|
2614
|
-
},
|
|
2615
|
-
"op": "next",
|
|
2616
|
-
"message": "Return shipping Merkle Root submitted"
|
|
2617
|
-
}
|
|
2618
|
-
},
|
|
2619
|
-
"env": {
|
|
2620
|
-
"account": "myshop_customer",
|
|
2621
|
-
"network": "mainnet",
|
|
2622
|
-
"no_cache": true
|
|
2623
|
-
},
|
|
2624
|
-
"submission": {
|
|
2625
|
-
"type": "submission",
|
|
2626
|
-
"guard": [
|
|
2627
|
-
{
|
|
2628
|
-
"object": "machine_merkle_root_v2",
|
|
2629
|
-
"impack": true
|
|
2630
|
-
}
|
|
2631
|
-
],
|
|
2632
|
-
"submission": [
|
|
2633
|
-
{
|
|
2634
|
-
"guard": "machine_merkle_root_v2",
|
|
2635
|
-
"submission": [
|
|
2636
|
-
{
|
|
2637
|
-
"identifier": 0,
|
|
2638
|
-
"b_submission": true,
|
|
2639
|
-
"value_type": "String",
|
|
2640
|
-
"value": "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
|
|
2641
|
-
}
|
|
2642
|
-
]
|
|
2643
|
-
}
|
|
2644
|
-
]
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
```
|
|
2649
|
-
|
|
2650
|
-
**Step 9.4: Merchant Confirms Return Received**
|
|
2651
|
-
|
|
2652
|
-
```json
|
|
2653
|
-
{
|
|
2654
|
-
"tool": "onchain_operations",
|
|
2655
|
-
"data": {
|
|
2656
|
-
"operation_type": "progress",
|
|
2657
|
-
"data": {
|
|
2658
|
-
"object": "myshop_progress_v2",
|
|
2659
|
-
"operate": {
|
|
2660
|
-
"operation": {
|
|
2661
|
-
"next_node_name": "Return Complete",
|
|
2662
|
-
"forward": "Confirm Return Received"
|
|
2663
|
-
},
|
|
2664
|
-
"op": "next",
|
|
2665
|
-
"message": "Return received and confirmed"
|
|
2666
|
-
}
|
|
2667
|
-
},
|
|
2668
|
-
"env": {
|
|
2669
|
-
"account": "myshop_merchant",
|
|
2670
|
-
"network": "mainnet",
|
|
2671
|
-
"no_cache": true
|
|
2672
|
-
}
|
|
2673
|
-
}
|
|
2674
|
-
}
|
|
2675
|
-
```
|
|
2676
|
-
|
|
2677
|
-
> **Receipt Return path**: Steps 9.3 + 9.4 complete the Receipt Return → Return Complete transition (threshold=2, dual-signature). The customer submits return tracking (Merkle Root), and the merchant confirms receipt of the returned goods.
|
|
2678
|
-
|
|
2679
|
-
**Step 9.5: Merchant Confirms Goods Recovered (Non-receipt Return path)**
|
|
2680
|
-
|
|
2681
|
-
For the Non-receipt Return path, the customer never received the goods and has nothing to return. The customer's non-receipt was already confirmed when entering the Non-receipt Return node (dual-signature at entry). The transition to Return Complete requires only the merchant to confirm goods recovery (threshold=1).
|
|
2682
|
-
|
|
2683
|
-
```json
|
|
2684
|
-
{
|
|
2685
|
-
"tool": "onchain_operations",
|
|
2686
|
-
"data": {
|
|
2687
|
-
"operation_type": "progress",
|
|
2688
|
-
"data": {
|
|
2689
|
-
"object": "myshop_progress_v2",
|
|
2690
|
-
"operate": {
|
|
2691
|
-
"operation": {
|
|
2692
|
-
"next_node_name": "Return Complete",
|
|
2693
|
-
"forward": "Confirm Goods Recovered"
|
|
2694
|
-
},
|
|
2695
|
-
"op": "next",
|
|
2696
|
-
"message": "Goods recovered by merchant - non-receipt return complete"
|
|
2697
|
-
}
|
|
2698
|
-
},
|
|
2699
|
-
"env": {
|
|
2700
|
-
"account": "myshop_merchant",
|
|
2701
|
-
"network": "mainnet",
|
|
2702
|
-
"no_cache": true
|
|
2703
|
-
}
|
|
2704
|
-
}
|
|
2705
|
-
}
|
|
2706
|
-
```
|
|
2707
|
-
|
|
2708
|
-
> **Non-receipt Return path**: Only Step 9.5 is needed (threshold=1, merchant-only). No customer action required — the customer never received the goods and has nothing to return or submit. The merchant confirms the goods have been recovered (e.g., returned by logistics to the merchant).
|
|
2709
|
-
|
|
2710
|
-
***
|
|
2711
|
-
|
|
2712
|
-
### Step 10: Return Fail (Timeout)
|
|
2713
|
-
|
|
2714
|
-
If customer doesn't return within 10 days, merchant can mark as Return Fail.
|
|
2715
|
-
|
|
2716
|
-
```json
|
|
2717
|
-
{
|
|
2718
|
-
"tool": "onchain_operations",
|
|
2719
|
-
"data": {
|
|
2720
|
-
"operation_type": "progress",
|
|
2721
|
-
"data": {
|
|
2722
|
-
"object": "myshop_progress_v2",
|
|
2723
|
-
"operate": {
|
|
2724
|
-
"operation": {
|
|
2725
|
-
"next_node_name": "Return Fail",
|
|
2726
|
-
"forward": "Timeout Return Not Received"
|
|
2727
|
-
},
|
|
2728
|
-
"op": "next",
|
|
2729
|
-
"message": "Return failed - timeout"
|
|
2730
|
-
}
|
|
2731
|
-
},
|
|
2732
|
-
"env": {
|
|
2733
|
-
"account": "myshop_merchant",
|
|
2734
|
-
"network": "mainnet",
|
|
2735
|
-
"no_cache": true
|
|
2736
|
-
},
|
|
2737
|
-
"submission": {
|
|
2738
|
-
"type": "submission",
|
|
2739
|
-
"guard": [
|
|
2740
|
-
{
|
|
2741
|
-
"object": "machine_time_10d_v2",
|
|
2742
|
-
"impack": true
|
|
2743
|
-
}
|
|
2744
|
-
],
|
|
2745
|
-
"submission": [
|
|
2746
|
-
{
|
|
2747
|
-
"guard": "machine_time_10d_v2",
|
|
2748
|
-
"submission": [
|
|
2749
|
-
{
|
|
2750
|
-
"identifier": 0,
|
|
2751
|
-
"b_submission": true,
|
|
2752
|
-
"value_type": "Address",
|
|
2753
|
-
"value": "myshop_progress_v2"
|
|
2754
|
-
}
|
|
2755
|
-
]
|
|
2756
|
-
}
|
|
2757
|
-
]
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
}
|
|
2761
|
-
```
|
|
2762
|
-
|
|
2763
|
-
***
|
|
2764
|
-
|
|
2765
|
-
## Part 4: Fund Allocation
|
|
2766
|
-
|
|
2767
|
-
### Merchant Wins (Order Complete, Wonderful, Return Fail)
|
|
2768
|
-
|
|
2769
|
-
When order reaches Order Complete, Wonderful, or Return Fail, merchant can withdraw funds.
|
|
2770
|
-
|
|
2771
|
-
**Prompt**: Merchant withdraws funds when winning condition is met.
|
|
2772
|
-
|
|
2773
|
-
```json
|
|
2774
|
-
{
|
|
2775
|
-
"tool": "onchain_operations",
|
|
2776
|
-
"data": {
|
|
2777
|
-
"operation_type": "allocation",
|
|
2778
|
-
"data": {
|
|
2779
|
-
"object": "myshop_allocation_v2",
|
|
2780
|
-
"alloc_by_guard": "service_merchant_win_v2"
|
|
2781
|
-
},
|
|
2782
|
-
"env": {
|
|
2783
|
-
"account": "myshop_merchant",
|
|
2784
|
-
"network": "mainnet",
|
|
2785
|
-
"no_cache": true
|
|
2786
|
-
},
|
|
2787
|
-
"submission": {
|
|
2788
|
-
"type": "submission",
|
|
2789
|
-
"guard": [
|
|
2790
|
-
{
|
|
2791
|
-
"object": "service_merchant_win_v2",
|
|
2792
|
-
"impack": true
|
|
2793
|
-
}
|
|
2794
|
-
],
|
|
2795
|
-
"submission": [
|
|
2796
|
-
{
|
|
2797
|
-
"guard": "service_merchant_win_v2",
|
|
2798
|
-
"submission": [
|
|
2799
|
-
{
|
|
2800
|
-
"identifier": 0,
|
|
2801
|
-
"b_submission": true,
|
|
2802
|
-
"value_type": "Address",
|
|
2803
|
-
"value": "myshop_order_v2"
|
|
2804
|
-
}
|
|
2805
|
-
]
|
|
2806
|
-
}
|
|
2807
|
-
]
|
|
2808
|
-
}
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
```
|
|
2812
|
-
|
|
2813
|
-
### Customer Wins (Lost, Return Complete)
|
|
2814
|
-
|
|
2815
|
-
When order reaches Lost or Return Complete, customer can withdraw funds.
|
|
2816
|
-
|
|
2817
|
-
**Prompt**: Customer withdraws funds when winning condition is met.
|
|
2818
|
-
|
|
2819
|
-
```json
|
|
2820
|
-
{
|
|
2821
|
-
"tool": "onchain_operations",
|
|
2822
|
-
"data": {
|
|
2823
|
-
"operation_type": "allocation",
|
|
2824
|
-
"data": {
|
|
2825
|
-
"object": "myshop_allocation_v2",
|
|
2826
|
-
"alloc_by_guard": "service_customer_win_v2"
|
|
2827
|
-
},
|
|
2828
|
-
"env": {
|
|
2829
|
-
"account": "myshop_customer",
|
|
2830
|
-
"network": "mainnet",
|
|
2831
|
-
"no_cache": true
|
|
2832
|
-
},
|
|
2833
|
-
"submission": {
|
|
2834
|
-
"type": "submission",
|
|
2835
|
-
"guard": [
|
|
2836
|
-
{
|
|
2837
|
-
"object": "service_customer_win_v2",
|
|
2838
|
-
"impack": true
|
|
2839
|
-
}
|
|
2840
|
-
],
|
|
2841
|
-
"submission": [
|
|
2842
|
-
{
|
|
2843
|
-
"guard": "service_customer_win_v2",
|
|
2844
|
-
"submission": [
|
|
2845
|
-
{
|
|
2846
|
-
"identifier": 0,
|
|
2847
|
-
"b_submission": true,
|
|
2848
|
-
"value_type": "Address",
|
|
2849
|
-
"value": "myshop_order_v2"
|
|
2850
|
-
}
|
|
2851
|
-
]
|
|
2852
|
-
}
|
|
2853
|
-
]
|
|
2854
|
-
}
|
|
2855
|
-
}
|
|
2856
|
-
}
|
|
2857
|
-
```
|
|
2858
|
-
|
|
2859
|
-
***
|
|
2860
|
-
|
|
2861
|
-
## Summary
|
|
2862
|
-
|
|
2863
|
-
This advanced e-commerce example demonstrates:
|
|
2864
|
-
|
|
2865
|
-
1. **Multi-Path Workflow**: Orders can complete through normal delivery, wonderful rating, or various return paths
|
|
2866
|
-
2. **Dual-Signature Returns**: Receipt returns require confirmation from both parties (threshold=2); non-receipt returns require only merchant confirmation of goods recovery (threshold=1)
|
|
2867
|
-
3. **Time-Based Auto-Completion**: Orders auto-complete from Shipping after a 10-day threshold (guard-verified); from Delivery Complete the merchant completes manually via the "Complete Order" forward
|
|
2868
|
-
4. **Guard-Based Verification**: All state transitions and fund allocations are protected by guards
|
|
2869
|
-
5. **Reward Incentive System**: Wonderful ratings receive rewards, lost packages and shipping delays receive compensation
|
|
2870
|
-
6. **Arbitration Support**: Service binds to Arbitration object for final on-chain dispute resolution
|
|
2871
|
-
7. **Privacy-Preserving Logistics**: Only Merkle Roots are submitted on-chain, actual tracking info is shared via Messenger
|
|
2872
|
-
8. **Flexible Fund Allocation**: Clear rules for merchant win (Order Complete, Wonderful, Return Fail) vs customer win (Lost, Return Complete)
|
|
2873
|
-
|
|
2874
|
-
The system ensures accountability through the "Who Completes the Key Action, Who Submits the Proof" principle, creating a clear audit trail for all critical actions.
|