@deeeed/metamask-harness 0.40.0 → 0.41.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/CHANGELOG.md +22 -0
- package/adapters/manifest.json +8 -0
- package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +5 -4
- package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +24 -5
- package/adapters/mobile/metro-config.cjs +94 -0
- package/adapters/mobile/start-metro.sh +13 -1
- package/dist/commands/device-target.js +3 -0
- package/dist/commands/run-engine.js +4 -14
- package/dist/funding-execution-context.js +35 -28
- package/dist/heal-bounds.js +1 -0
- package/dist/live-adapter-contract.js +2 -1
- package/dist/mm-harness-cli.js +1 -1
- package/docs/RECIPES.md +25 -19
- package/library/actions/extension/perps/mutation-receipt.mjs +12 -8
- package/library/actions/extension/perps/select_activity_filter.mjs +1 -1
- package/library/actions/extension/perps/select_market_filter.mjs +1 -1
- package/library/actions/mobile/perps/capture_performance.mjs +2 -2
- package/library/actions/mobile/perps/performance-capture.mjs +375 -17
- package/library/actions/mobile/perps/perps.mjs +56 -10
- package/library/actions/mobile/platform/bridge.mjs +59 -1
- package/library/actions/mobile/wallet/ensure_unlocked.mjs +60 -26
- package/library/actions/mobile/wallet/import.mjs +2 -0
- package/library/actions/mobile/wallet/select_account.mjs +21 -2
- package/library/manifests/mobile.action-manifest.json +47 -6
- package/library/recipes/mobile/perps/performance.recipe.json +680 -26
- package/package.json +1 -1
- package/library/recipes/mobile/perps/performance.background-resume.recipe.json +0 -56
- package/library/recipes/mobile/perps/performance.cold-start.recipe.json +0 -56
- package/library/recipes/mobile/perps/performance.homepage.android-background-reconnect.recipe.json +0 -159
- package/library/recipes/mobile/perps/performance.homepage.android-background-short.recipe.json +0 -157
- package/library/recipes/mobile/perps/performance.homepage.android-cold-disk-cache.recipe.json +0 -165
- package/library/recipes/mobile/perps/performance.homepage.android-cold-no-cache.recipe.json +0 -139
- package/library/recipes/mobile/perps/performance.homepage.android-network-recovery.recipe.json +0 -149
- package/library/recipes/mobile/perps/performance.homepage.cold-position-sample.recipe.json +0 -120
- package/library/recipes/mobile/perps/performance.homepage.ios-background-reconnect.recipe.json +0 -111
- package/library/recipes/mobile/perps/performance.homepage.ios-background-short.recipe.json +0 -108
- package/library/recipes/mobile/perps/performance.homepage.ios-cold-disk-cache.recipe.json +0 -122
- package/library/recipes/mobile/perps/performance.homepage.ios-cold-no-cache.recipe.json +0 -95
- package/library/recipes/mobile/perps/performance.warm-start.recipe.json +0 -49
|
@@ -1,41 +1,695 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
|
|
3
|
-
"title": "MetaMask
|
|
4
|
-
"description": "
|
|
3
|
+
"title": "MetaMask Perps loading lifecycle performance",
|
|
4
|
+
"description": "The single platform-neutral Perps loading recipe. Parameters select account, content, lifecycle, network, endpoint mode, and sample identity; Android and iOS use the same graph. It proves visible content and captures Perps bootstrap, market, account, and live-stream evidence while setup stays outside the evidence window.",
|
|
5
|
+
"paramsSchema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["account"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"account": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Exact fixture account name, such as Trading or dev3."
|
|
13
|
+
},
|
|
14
|
+
"content_variant": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["positions", "trending"],
|
|
17
|
+
"default": "positions",
|
|
18
|
+
"description": "Measure a position-owning account or an independently proven empty account showing generic markets."
|
|
19
|
+
},
|
|
20
|
+
"initial_account": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"default": "dev2",
|
|
23
|
+
"description": "Source account used only by the account-switch lifecycle."
|
|
24
|
+
},
|
|
25
|
+
"initial_content_variant": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": ["positions", "trending"],
|
|
28
|
+
"default": "trending",
|
|
29
|
+
"description": "Proven source-account state for account switching."
|
|
30
|
+
},
|
|
31
|
+
"provider": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"default": "hyperliquid"
|
|
34
|
+
},
|
|
35
|
+
"initial_network": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"enum": ["mainnet", "testnet"],
|
|
38
|
+
"default": "mainnet"
|
|
39
|
+
},
|
|
40
|
+
"target_network": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"enum": ["mainnet", "testnet"],
|
|
43
|
+
"default": "testnet"
|
|
44
|
+
},
|
|
45
|
+
"market": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"default": "BTC",
|
|
48
|
+
"description": "Exact visible position market symbol."
|
|
49
|
+
},
|
|
50
|
+
"lifecycle": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"enum": [
|
|
53
|
+
"navigate_return",
|
|
54
|
+
"cold_disk_cache",
|
|
55
|
+
"cold_no_cache",
|
|
56
|
+
"background_short",
|
|
57
|
+
"background_reconnect",
|
|
58
|
+
"account_switch",
|
|
59
|
+
"network_switch"
|
|
60
|
+
],
|
|
61
|
+
"default": "cold_no_cache",
|
|
62
|
+
"description": "One lifecycle invariant exercised by this sample."
|
|
63
|
+
},
|
|
64
|
+
"sample_id": {
|
|
65
|
+
"type": "string",
|
|
66
|
+
"default": "sample",
|
|
67
|
+
"description": "Artifact-local sample identifier."
|
|
68
|
+
},
|
|
69
|
+
"snapshot_endpoint_mode": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"enum": ["deployed", "local"],
|
|
72
|
+
"default": "deployed",
|
|
73
|
+
"description": "Whether the current build uses its configured deployed endpoint or an explicitly routed local snapshot endpoint."
|
|
74
|
+
},
|
|
75
|
+
"snapshot_port": {
|
|
76
|
+
"type": "number",
|
|
77
|
+
"default": 3000,
|
|
78
|
+
"description": "Host port used only by the explicitly routed local snapshot endpoint."
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
5
82
|
"workflow": {
|
|
6
|
-
"entry": "ensure-
|
|
83
|
+
"entry": "ensure-wallet",
|
|
7
84
|
"nodes": {
|
|
8
|
-
"
|
|
85
|
+
"ensure-wallet": {
|
|
86
|
+
"action": "metamask.wallet.ensure_unlocked",
|
|
87
|
+
"target_timeout_ms": 90000,
|
|
88
|
+
"unlock_timeout_ms": 90000,
|
|
89
|
+
"stable_unlocked_ms": 0,
|
|
90
|
+
"intent": "Restore the already-provisioned fixture wallet without rerunning onboarding outside timing",
|
|
91
|
+
"next": "select-sample-account"
|
|
92
|
+
},
|
|
93
|
+
"select-sample-account": {
|
|
94
|
+
"action": "metamask.wallet.select_account",
|
|
95
|
+
"name": "{{params.account}}",
|
|
96
|
+
"cdp_timeout_ms": 30000,
|
|
97
|
+
"timeout_ms": 30000,
|
|
98
|
+
"intent": "Select the exact fixture account outside timing rather than relying on prior device state",
|
|
99
|
+
"next": "select-content-context-reset"
|
|
100
|
+
},
|
|
101
|
+
"select-content-context-reset": {
|
|
102
|
+
"action": "switch",
|
|
103
|
+
"value": "{{params.content_variant}}",
|
|
104
|
+
"equals": "trending",
|
|
105
|
+
"cases": {
|
|
106
|
+
"match": "clear-empty-account-caches"
|
|
107
|
+
},
|
|
108
|
+
"default": "select-network-target-preflight",
|
|
109
|
+
"intent": "Reconstruct Perps context only for the independently empty account used by the market lane"
|
|
110
|
+
},
|
|
111
|
+
"clear-empty-account-caches": {
|
|
112
|
+
"action": "metamask.perps.clear_performance_caches",
|
|
113
|
+
"intent": "Remove prior-account Perps memory and disk data before proving the empty account",
|
|
114
|
+
"next": "restart-empty-account-context"
|
|
115
|
+
},
|
|
116
|
+
"restart-empty-account-context": {
|
|
117
|
+
"action": "app.lifecycle",
|
|
118
|
+
"command": "restart",
|
|
119
|
+
"settle_ms": 0,
|
|
120
|
+
"runtime_ready_timeout_ms": 90000,
|
|
121
|
+
"timeout_ms": 120000,
|
|
122
|
+
"intent": "Construct controllers against the selected empty account outside the measurement window",
|
|
123
|
+
"next": "unlock-empty-account-context"
|
|
124
|
+
},
|
|
125
|
+
"unlock-empty-account-context": {
|
|
126
|
+
"action": "metamask.wallet.ensure_unlocked",
|
|
127
|
+
"target_timeout_ms": 90000,
|
|
128
|
+
"unlock_timeout_ms": 90000,
|
|
129
|
+
"intent": "Restore and prove the selected empty account after the setup-only process restart outside measurement",
|
|
130
|
+
"next": "select-network-target-preflight"
|
|
131
|
+
},
|
|
132
|
+
"select-network-target-preflight": {
|
|
133
|
+
"action": "switch",
|
|
134
|
+
"value": "{{params.lifecycle}}",
|
|
135
|
+
"equals": "network_switch",
|
|
136
|
+
"cases": {
|
|
137
|
+
"match": "prepare-target-network-preflight"
|
|
138
|
+
},
|
|
139
|
+
"default": "prepare-initial-state-preflight",
|
|
140
|
+
"intent": "Inspect the target-network position before changing to the measured source network"
|
|
141
|
+
},
|
|
142
|
+
"prepare-initial-state-preflight": {
|
|
143
|
+
"action": "metamask.perps.start_state",
|
|
144
|
+
"account": "{{params.account}}",
|
|
145
|
+
"provider": "{{params.provider}}",
|
|
146
|
+
"network": "{{params.initial_network}}",
|
|
147
|
+
"page": "home",
|
|
148
|
+
"positions": false,
|
|
149
|
+
"orders": false,
|
|
150
|
+
"timeout_ms": 120000,
|
|
151
|
+
"intent": "Initialize the exact Perps account, provider, and network outside timing before asserting its real position",
|
|
152
|
+
"next": "select-content-precondition"
|
|
153
|
+
},
|
|
154
|
+
"prepare-target-network-preflight": {
|
|
155
|
+
"action": "metamask.perps.start_state",
|
|
156
|
+
"account": "{{params.account}}",
|
|
157
|
+
"provider": "{{params.provider}}",
|
|
158
|
+
"network": "{{params.target_network}}",
|
|
159
|
+
"page": "home",
|
|
160
|
+
"positions": false,
|
|
161
|
+
"orders": false,
|
|
162
|
+
"timeout_ms": 120000,
|
|
163
|
+
"intent": "Set the target network outside timing only so its existing position can be proven",
|
|
164
|
+
"next": "select-content-precondition"
|
|
165
|
+
},
|
|
166
|
+
"select-content-precondition": {
|
|
167
|
+
"action": "switch",
|
|
168
|
+
"value": "{{params.content_variant}}",
|
|
169
|
+
"equals": "trending",
|
|
170
|
+
"cases": {
|
|
171
|
+
"match": "assert-no-positions"
|
|
172
|
+
},
|
|
173
|
+
"default": "assert-position",
|
|
174
|
+
"intent": "Prove either the existing position or the empty account before timing"
|
|
175
|
+
},
|
|
176
|
+
"assert-no-positions": {
|
|
177
|
+
"action": "metamask.perps.assert_positions",
|
|
178
|
+
"state": "none",
|
|
179
|
+
"mode": "all",
|
|
180
|
+
"timeout_ms": 30000,
|
|
181
|
+
"intent": "Prove the market-only account has no open positions",
|
|
182
|
+
"next": "assert-no-orders"
|
|
183
|
+
},
|
|
184
|
+
"assert-no-orders": {
|
|
185
|
+
"action": "metamask.perps.assert_orders",
|
|
186
|
+
"state": "none",
|
|
187
|
+
"mode": "all",
|
|
188
|
+
"timeout_ms": 30000,
|
|
189
|
+
"intent": "Prove the market-only account has no open orders",
|
|
190
|
+
"next": "select-account-switch-preparation"
|
|
191
|
+
},
|
|
192
|
+
"assert-position": {
|
|
193
|
+
"action": "metamask.perps.assert_positions",
|
|
194
|
+
"market": "{{params.market}}",
|
|
195
|
+
"state": "open",
|
|
196
|
+
"timeout_ms": 30000,
|
|
197
|
+
"intent": "Prove the real position exists without creating or replacing exchange state",
|
|
198
|
+
"next": "select-account-switch-preparation"
|
|
199
|
+
},
|
|
200
|
+
"select-account-switch-preparation": {
|
|
201
|
+
"action": "switch",
|
|
202
|
+
"value": "{{params.lifecycle}}",
|
|
203
|
+
"equals": "account_switch",
|
|
204
|
+
"cases": {
|
|
205
|
+
"match": "select-initial-account"
|
|
206
|
+
},
|
|
207
|
+
"default": "select-network-switch-preparation",
|
|
208
|
+
"intent": "Move to the source account outside timing only for the account-switch lifecycle"
|
|
209
|
+
},
|
|
210
|
+
"select-initial-account": {
|
|
211
|
+
"action": "metamask.wallet.select_account",
|
|
212
|
+
"name": "{{params.initial_account}}",
|
|
213
|
+
"cdp_timeout_ms": 30000,
|
|
214
|
+
"timeout_ms": 30000,
|
|
215
|
+
"intent": "Prime the source account while preserving the target account's proven position",
|
|
216
|
+
"next": "select-initial-account-precondition"
|
|
217
|
+
},
|
|
218
|
+
"select-initial-account-precondition": {
|
|
219
|
+
"action": "switch",
|
|
220
|
+
"value": "{{params.initial_content_variant}}",
|
|
221
|
+
"equals": "positions",
|
|
222
|
+
"cases": {
|
|
223
|
+
"match": "assert-initial-account-position"
|
|
224
|
+
},
|
|
225
|
+
"default": "assert-initial-account-no-positions",
|
|
226
|
+
"intent": "Prove the account-switch source has its declared position state"
|
|
227
|
+
},
|
|
228
|
+
"assert-initial-account-position": {
|
|
229
|
+
"action": "metamask.perps.assert_positions",
|
|
230
|
+
"market": "{{params.market}}",
|
|
231
|
+
"state": "open",
|
|
232
|
+
"timeout_ms": 30000,
|
|
233
|
+
"intent": "Prove the account-switch source owns the expected position",
|
|
234
|
+
"next": "open-wallet-home"
|
|
235
|
+
},
|
|
236
|
+
"assert-initial-account-no-positions": {
|
|
237
|
+
"action": "metamask.perps.assert_positions",
|
|
238
|
+
"state": "none",
|
|
239
|
+
"mode": "all",
|
|
240
|
+
"timeout_ms": 30000,
|
|
241
|
+
"intent": "Prove the account-switch source has no positions before timing",
|
|
242
|
+
"next": "assert-initial-account-no-orders"
|
|
243
|
+
},
|
|
244
|
+
"assert-initial-account-no-orders": {
|
|
245
|
+
"action": "metamask.perps.assert_orders",
|
|
246
|
+
"state": "none",
|
|
247
|
+
"mode": "all",
|
|
248
|
+
"timeout_ms": 30000,
|
|
249
|
+
"intent": "Prove the account-switch source has no orders before timing",
|
|
250
|
+
"next": "open-wallet-home"
|
|
251
|
+
},
|
|
252
|
+
"select-network-switch-preparation": {
|
|
253
|
+
"action": "switch",
|
|
254
|
+
"value": "{{params.lifecycle}}",
|
|
255
|
+
"equals": "network_switch",
|
|
256
|
+
"cases": {
|
|
257
|
+
"match": "prepare-initial-network"
|
|
258
|
+
},
|
|
259
|
+
"default": "open-wallet-home",
|
|
260
|
+
"intent": "Move to the source network outside timing only for the network-switch lifecycle"
|
|
261
|
+
},
|
|
262
|
+
"prepare-initial-network": {
|
|
263
|
+
"action": "metamask.perps.start_state",
|
|
264
|
+
"account": "{{params.account}}",
|
|
265
|
+
"provider": "{{params.provider}}",
|
|
266
|
+
"network": "{{params.initial_network}}",
|
|
267
|
+
"page": "home",
|
|
268
|
+
"positions": false,
|
|
269
|
+
"orders": false,
|
|
270
|
+
"timeout_ms": 120000,
|
|
271
|
+
"intent": "Prime the source Perps network before the measured switch",
|
|
272
|
+
"next": "open-wallet-home"
|
|
273
|
+
},
|
|
274
|
+
"open-wallet-home": {
|
|
9
275
|
"action": "ui.navigate",
|
|
10
|
-
"page": "
|
|
11
|
-
"
|
|
12
|
-
"
|
|
276
|
+
"page": "home",
|
|
277
|
+
"timeout_ms": 30000,
|
|
278
|
+
"intent": "Persist Wallet Home and leave its Perps section available for the lifecycle sample",
|
|
279
|
+
"next": "reset-homepage-scroll"
|
|
280
|
+
},
|
|
281
|
+
"reset-homepage-scroll": {
|
|
282
|
+
"action": "ui.scroll",
|
|
283
|
+
"test_id": "wallet-screen",
|
|
284
|
+
"offset": 0,
|
|
285
|
+
"animated": false,
|
|
286
|
+
"timeout_ms": 60000,
|
|
287
|
+
"intent": "Move the Perps section out of view before the setup visibility proof",
|
|
288
|
+
"next": "select-account-switch-prime"
|
|
289
|
+
},
|
|
290
|
+
"select-account-switch-prime": {
|
|
291
|
+
"action": "switch",
|
|
292
|
+
"value": "{{params.lifecycle}}",
|
|
293
|
+
"equals": "account_switch",
|
|
294
|
+
"cases": {
|
|
295
|
+
"match": "select-local-snapshot-preparation"
|
|
296
|
+
},
|
|
297
|
+
"default": "start-prime-performance-capture",
|
|
298
|
+
"intent": "Skip target-content priming while the account-switch source identity is selected"
|
|
299
|
+
},
|
|
300
|
+
"start-prime-performance-capture": {
|
|
301
|
+
"action": "metamask.perps.capture_performance",
|
|
302
|
+
"phase": "start",
|
|
303
|
+
"intent": "Open a setup-only log window so resident Homepage content can be proven before lifecycle mutation",
|
|
304
|
+
"next": "prime-homepage-position"
|
|
305
|
+
},
|
|
306
|
+
"prime-homepage-position": {
|
|
307
|
+
"action": "ui.scroll",
|
|
308
|
+
"test_id": "wallet-screen",
|
|
309
|
+
"offset": 600,
|
|
310
|
+
"animated": true,
|
|
311
|
+
"timeout_ms": 60000,
|
|
312
|
+
"intent": "Prime the below-fold position section before the measured lifecycle",
|
|
313
|
+
"next": "finish-prime-performance-capture"
|
|
314
|
+
},
|
|
315
|
+
"finish-prime-performance-capture": {
|
|
316
|
+
"action": "metamask.perps.capture_performance",
|
|
317
|
+
"phase": "end",
|
|
318
|
+
"require_records": false,
|
|
319
|
+
"artifact_prefix": "setup/homepage-{{params.content_variant}}-prime-{{params.sample_id}}",
|
|
320
|
+
"intent": "Close the setup-only log window; native visibility is proven by the measured UI assertion later in the graph",
|
|
321
|
+
"next": "select-local-snapshot-preparation"
|
|
322
|
+
},
|
|
323
|
+
"select-local-snapshot-preparation": {
|
|
324
|
+
"action": "switch",
|
|
325
|
+
"value": "{{params.snapshot_endpoint_mode}}",
|
|
326
|
+
"equals": "local",
|
|
327
|
+
"cases": {
|
|
328
|
+
"match": "prepare-local-snapshot-endpoint"
|
|
329
|
+
},
|
|
330
|
+
"default": "select-navigate-return-setup",
|
|
331
|
+
"intent": "Route a host port only when the configured full-bootstrap endpoint is local"
|
|
332
|
+
},
|
|
333
|
+
"prepare-local-snapshot-endpoint": {
|
|
334
|
+
"action": "metamask.perps.prepare_local_snapshot_endpoint",
|
|
335
|
+
"port": "{{params.snapshot_port}}",
|
|
336
|
+
"intent": "Make the configured local Terminal endpoint reachable without an external command node",
|
|
337
|
+
"next": "select-navigate-return-setup"
|
|
13
338
|
},
|
|
14
|
-
"
|
|
15
|
-
"action": "
|
|
16
|
-
"
|
|
17
|
-
"
|
|
339
|
+
"select-navigate-return-setup": {
|
|
340
|
+
"action": "switch",
|
|
341
|
+
"value": "{{params.lifecycle}}",
|
|
342
|
+
"equals": "navigate_return",
|
|
343
|
+
"cases": {
|
|
344
|
+
"match": "navigate-away-before-capture"
|
|
345
|
+
},
|
|
346
|
+
"default": "start-performance-capture",
|
|
347
|
+
"intent": "Leave Homepage before arming the warm navigation-return evidence window"
|
|
18
348
|
},
|
|
19
|
-
"
|
|
349
|
+
"navigate-away-before-capture": {
|
|
20
350
|
"action": "ui.navigate",
|
|
21
|
-
"page": "perps
|
|
22
|
-
"
|
|
23
|
-
"intent": "
|
|
24
|
-
"next": "
|
|
351
|
+
"page": "perps",
|
|
352
|
+
"timeout_ms": 30000,
|
|
353
|
+
"intent": "Unmount the Homepage section while preserving resident Perps data",
|
|
354
|
+
"next": "start-performance-capture"
|
|
25
355
|
},
|
|
26
|
-
"
|
|
27
|
-
"action": "
|
|
28
|
-
"
|
|
356
|
+
"start-performance-capture": {
|
|
357
|
+
"action": "metamask.perps.capture_performance",
|
|
358
|
+
"phase": "start",
|
|
359
|
+
"intent": "Start passive app-log capture immediately before the measured lifecycle transition",
|
|
360
|
+
"next": "select-cold-no-cache"
|
|
361
|
+
},
|
|
362
|
+
"select-cold-no-cache": {
|
|
363
|
+
"action": "switch",
|
|
364
|
+
"value": "{{params.lifecycle}}",
|
|
365
|
+
"equals": "cold_no_cache",
|
|
366
|
+
"cases": {
|
|
367
|
+
"match": "clear-perps-caches"
|
|
368
|
+
},
|
|
369
|
+
"default": "select-cold-disk-cache",
|
|
370
|
+
"intent": "Choose the cold no-cache transition only for its named lifecycle"
|
|
371
|
+
},
|
|
372
|
+
"clear-perps-caches": {
|
|
373
|
+
"action": "metamask.perps.clear_performance_caches",
|
|
374
|
+
"intent": "Remove only persisted Perps market and user snapshots while preserving the wallet",
|
|
375
|
+
"next": "restart-app"
|
|
376
|
+
},
|
|
377
|
+
"select-cold-disk-cache": {
|
|
378
|
+
"action": "switch",
|
|
379
|
+
"value": "{{params.lifecycle}}",
|
|
380
|
+
"equals": "cold_disk_cache",
|
|
381
|
+
"cases": {
|
|
382
|
+
"match": "restart-app"
|
|
383
|
+
},
|
|
384
|
+
"default": "select-background-short",
|
|
385
|
+
"intent": "Choose the returning cold-process transition only for its named lifecycle"
|
|
29
386
|
},
|
|
30
|
-
"
|
|
31
|
-
"action": "app.
|
|
32
|
-
"
|
|
33
|
-
"
|
|
387
|
+
"restart-app": {
|
|
388
|
+
"action": "app.lifecycle",
|
|
389
|
+
"command": "restart",
|
|
390
|
+
"settle_ms": 0,
|
|
391
|
+
"runtime_ready_timeout_ms": 90000,
|
|
392
|
+
"timeout_ms": 120000,
|
|
393
|
+
"intent": "Restart the installed process without rebuilding or replacing wallet state; app-side clocks own the performance boundary",
|
|
394
|
+
"next": "unlock-after-restart"
|
|
34
395
|
},
|
|
35
|
-
"
|
|
396
|
+
"unlock-after-restart": {
|
|
36
397
|
"action": "metamask.wallet.ensure_unlocked",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
398
|
+
"target_timeout_ms": 90000,
|
|
399
|
+
"unlock_timeout_ms": 90000,
|
|
400
|
+
"stable_unlocked_ms": 0,
|
|
401
|
+
"intent": "Restore and prove the existing wallet after process restart without delaying the captured bootstrap window",
|
|
402
|
+
"next": "scroll-visible-position"
|
|
403
|
+
},
|
|
404
|
+
"select-background-short": {
|
|
405
|
+
"action": "switch",
|
|
406
|
+
"value": "{{params.lifecycle}}",
|
|
407
|
+
"equals": "background_short",
|
|
408
|
+
"cases": {
|
|
409
|
+
"match": "background-short"
|
|
410
|
+
},
|
|
411
|
+
"default": "select-background-reconnect",
|
|
412
|
+
"intent": "Choose the below-grace-period background transition only for its named lifecycle"
|
|
413
|
+
},
|
|
414
|
+
"background-short": {
|
|
415
|
+
"action": "app.lifecycle",
|
|
416
|
+
"command": "background",
|
|
417
|
+
"settle_ms": 3000,
|
|
418
|
+
"intent": "Keep the process inactive for less than the Perps connection grace period",
|
|
419
|
+
"next": "foreground-app"
|
|
420
|
+
},
|
|
421
|
+
"select-background-reconnect": {
|
|
422
|
+
"action": "switch",
|
|
423
|
+
"value": "{{params.lifecycle}}",
|
|
424
|
+
"equals": "background_reconnect",
|
|
425
|
+
"cases": {
|
|
426
|
+
"match": "background-reconnect"
|
|
427
|
+
},
|
|
428
|
+
"default": "select-account-switch",
|
|
429
|
+
"intent": "Choose the beyond-grace-period background transition only for its named lifecycle"
|
|
430
|
+
},
|
|
431
|
+
"background-reconnect": {
|
|
432
|
+
"action": "app.lifecycle",
|
|
433
|
+
"command": "background",
|
|
434
|
+
"settle_ms": 25000,
|
|
435
|
+
"intent": "Keep the process inactive beyond the Perps connection grace period",
|
|
436
|
+
"next": "foreground-app"
|
|
437
|
+
},
|
|
438
|
+
"foreground-app": {
|
|
439
|
+
"action": "app.lifecycle",
|
|
440
|
+
"command": "foreground",
|
|
441
|
+
"settle_ms": 0,
|
|
442
|
+
"runtime_ready_timeout_ms": 90000,
|
|
443
|
+
"timeout_ms": 120000,
|
|
444
|
+
"intent": "Restore the same process without adding an artificial post-foreground timing delay",
|
|
445
|
+
"next": "scroll-visible-position"
|
|
446
|
+
},
|
|
447
|
+
"select-account-switch": {
|
|
448
|
+
"action": "switch",
|
|
449
|
+
"value": "{{params.lifecycle}}",
|
|
450
|
+
"equals": "account_switch",
|
|
451
|
+
"cases": {
|
|
452
|
+
"match": "switch-to-target-account"
|
|
453
|
+
},
|
|
454
|
+
"default": "select-network-switch",
|
|
455
|
+
"intent": "Choose the account identity transition only for its named lifecycle"
|
|
456
|
+
},
|
|
457
|
+
"switch-to-target-account": {
|
|
458
|
+
"action": "metamask.wallet.select_account",
|
|
459
|
+
"name": "{{params.account}}",
|
|
460
|
+
"cdp_timeout_ms": 30000,
|
|
461
|
+
"timeout_ms": 30000,
|
|
462
|
+
"intent": "Switch through the same wallet account-selection action used by a client journey",
|
|
463
|
+
"next": "scroll-visible-position"
|
|
464
|
+
},
|
|
465
|
+
"select-network-switch": {
|
|
466
|
+
"action": "switch",
|
|
467
|
+
"value": "{{params.lifecycle}}",
|
|
468
|
+
"equals": "network_switch",
|
|
469
|
+
"cases": {
|
|
470
|
+
"match": "switch-to-target-network"
|
|
471
|
+
},
|
|
472
|
+
"default": "select-navigate-return",
|
|
473
|
+
"intent": "Choose the Perps network/DEX identity transition only for its named lifecycle"
|
|
474
|
+
},
|
|
475
|
+
"switch-to-target-network": {
|
|
476
|
+
"action": "metamask.perps.start_state",
|
|
477
|
+
"account": "{{params.account}}",
|
|
478
|
+
"provider": "{{params.provider}}",
|
|
479
|
+
"network": "{{params.target_network}}",
|
|
480
|
+
"page": false,
|
|
481
|
+
"positions": false,
|
|
482
|
+
"orders": false,
|
|
483
|
+
"timeout_ms": 120000,
|
|
484
|
+
"intent": "Switch the real in-app Perps controller context to the target network without mutating exchange state",
|
|
485
|
+
"next": "scroll-visible-position"
|
|
486
|
+
},
|
|
487
|
+
"select-navigate-return": {
|
|
488
|
+
"action": "switch",
|
|
489
|
+
"value": "{{params.lifecycle}}",
|
|
490
|
+
"equals": "navigate_return",
|
|
491
|
+
"cases": {
|
|
492
|
+
"match": "navigate-home-for-return"
|
|
493
|
+
},
|
|
494
|
+
"default": "invalid-lifecycle",
|
|
495
|
+
"intent": "Accept the remaining schema-valid warm navigation-return lifecycle"
|
|
496
|
+
},
|
|
497
|
+
"navigate-home-for-return": {
|
|
498
|
+
"action": "ui.navigate",
|
|
499
|
+
"page": "home",
|
|
500
|
+
"timeout_ms": 30000,
|
|
501
|
+
"intent": "Return to Wallet Home inside the evidence window while resident Perps data remains available",
|
|
502
|
+
"next": "reset-returned-homepage-scroll"
|
|
503
|
+
},
|
|
504
|
+
"reset-returned-homepage-scroll": {
|
|
505
|
+
"action": "ui.scroll",
|
|
506
|
+
"test_id": "wallet-screen",
|
|
507
|
+
"offset": 0,
|
|
508
|
+
"animated": false,
|
|
509
|
+
"timeout_ms": 60000,
|
|
510
|
+
"intent": "Force the retained Homepage section out of view before measuring a new warm viewport demand",
|
|
511
|
+
"next": "settle-returned-homepage-scroll"
|
|
512
|
+
},
|
|
513
|
+
"settle-returned-homepage-scroll": {
|
|
514
|
+
"action": "wait",
|
|
515
|
+
"duration_ms": 250,
|
|
516
|
+
"intent": "Allow the passive visibility observer to record the section leaving the viewport",
|
|
517
|
+
"next": "scroll-visible-position"
|
|
518
|
+
},
|
|
519
|
+
"scroll-visible-position": {
|
|
520
|
+
"action": "ui.scroll",
|
|
521
|
+
"test_id": "wallet-screen",
|
|
522
|
+
"offset": 600,
|
|
523
|
+
"animated": true,
|
|
524
|
+
"timeout_ms": 60000,
|
|
525
|
+
"intent": "Demand the below-fold Perps content inside the evidence window",
|
|
526
|
+
"next": "select-visible-content"
|
|
527
|
+
},
|
|
528
|
+
"select-visible-content": {
|
|
529
|
+
"action": "switch",
|
|
530
|
+
"value": "{{params.content_variant}}",
|
|
531
|
+
"equals": "trending",
|
|
532
|
+
"cases": {
|
|
533
|
+
"match": "wait-visible-trending"
|
|
534
|
+
},
|
|
535
|
+
"default": "wait-visible-position",
|
|
536
|
+
"intent": "Prove the requested content variant with the same native UI assertion on Android and iOS"
|
|
537
|
+
},
|
|
538
|
+
"wait-visible-trending": {
|
|
539
|
+
"action": "ui.wait_for",
|
|
540
|
+
"test_id": "homepage-trending-perps-carousel",
|
|
541
|
+
"expected": "visible",
|
|
542
|
+
"timeout_ms": 90000,
|
|
543
|
+
"intent": "Require the generic Perps market carousel to be visibly inside the viewport",
|
|
544
|
+
"next": "select-resident-finish"
|
|
545
|
+
},
|
|
546
|
+
"wait-visible-position": {
|
|
547
|
+
"action": "ui.wait_for",
|
|
548
|
+
"test_id": "homepage-perps-positions",
|
|
549
|
+
"expected": "visible",
|
|
550
|
+
"timeout_ms": 90000,
|
|
551
|
+
"intent": "Require the selected account's Perps position content to be visibly inside the viewport",
|
|
552
|
+
"next": "select-resident-finish"
|
|
553
|
+
},
|
|
554
|
+
"select-resident-finish": {
|
|
555
|
+
"action": "switch",
|
|
556
|
+
"value": "{{params.lifecycle}}",
|
|
557
|
+
"equals": "navigate_return",
|
|
558
|
+
"cases": {
|
|
559
|
+
"match": "finish-resident-performance-capture"
|
|
560
|
+
},
|
|
561
|
+
"default": "select-cold-no-cache-finish",
|
|
562
|
+
"intent": "Use lifecycle-specific evidence: resident warm data, preloaded cold data, or a post-transition socket delivery"
|
|
563
|
+
},
|
|
564
|
+
"select-cold-no-cache-finish": {
|
|
565
|
+
"action": "switch",
|
|
566
|
+
"value": "{{params.lifecycle}}",
|
|
567
|
+
"equals": "cold_no_cache",
|
|
568
|
+
"cases": {
|
|
569
|
+
"match": "finish-cold-no-cache-performance-capture"
|
|
570
|
+
},
|
|
571
|
+
"default": "select-cold-disk-cache-finish",
|
|
572
|
+
"intent": "Accept fresh data preloaded after process start but before the Homepage viewport demand only for cold no-cache"
|
|
573
|
+
},
|
|
574
|
+
"select-cold-disk-cache-finish": {
|
|
575
|
+
"action": "switch",
|
|
576
|
+
"value": "{{params.lifecycle}}",
|
|
577
|
+
"equals": "cold_disk_cache",
|
|
578
|
+
"cases": {
|
|
579
|
+
"match": "finish-cold-disk-cache-performance-capture"
|
|
580
|
+
},
|
|
581
|
+
"default": "select-background-short-finish",
|
|
582
|
+
"intent": "Require disk hydration and immediate first fresh delivery only for the returning cold-process lifecycle"
|
|
583
|
+
},
|
|
584
|
+
"select-background-short-finish": {
|
|
585
|
+
"action": "switch",
|
|
586
|
+
"value": "{{params.lifecycle}}",
|
|
587
|
+
"equals": "background_short",
|
|
588
|
+
"cases": {
|
|
589
|
+
"match": "finish-background-short-performance-capture"
|
|
590
|
+
},
|
|
591
|
+
"default": "select-account-switch-finish",
|
|
592
|
+
"intent": "Treat a below-grace resume as resident continuity; a new socket tick is optional because the connection remains alive"
|
|
593
|
+
},
|
|
594
|
+
"select-account-switch-finish": {
|
|
595
|
+
"action": "switch",
|
|
596
|
+
"value": "{{params.lifecycle}}",
|
|
597
|
+
"equals": "account_switch",
|
|
598
|
+
"cases": {
|
|
599
|
+
"match": "select-account-switch-content-finish"
|
|
600
|
+
},
|
|
601
|
+
"default": "finish-performance-capture",
|
|
602
|
+
"intent": "Use target-cache visibility plus fresh takeover without requiring a new process bootstrap"
|
|
603
|
+
},
|
|
604
|
+
"select-account-switch-content-finish": {
|
|
605
|
+
"action": "switch",
|
|
606
|
+
"value": "{{params.content_variant}}",
|
|
607
|
+
"equals": "trending",
|
|
608
|
+
"cases": {
|
|
609
|
+
"match": "finish-account-switch-empty-performance-capture"
|
|
610
|
+
},
|
|
611
|
+
"default": "finish-account-switch-performance-capture",
|
|
612
|
+
"intent": "Require the target account's declared empty or positioned visible state"
|
|
613
|
+
},
|
|
614
|
+
"finish-resident-performance-capture": {
|
|
615
|
+
"action": "metamask.perps.capture_performance",
|
|
616
|
+
"phase": "end",
|
|
617
|
+
"require_records": false,
|
|
618
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
619
|
+
"intent": "Preserve the warm resident capture after native visible-content proof",
|
|
620
|
+
"next": "capture-position"
|
|
621
|
+
},
|
|
622
|
+
"finish-cold-no-cache-performance-capture": {
|
|
623
|
+
"action": "metamask.perps.capture_performance",
|
|
624
|
+
"phase": "end",
|
|
625
|
+
"require_records": false,
|
|
626
|
+
"required_live_streams": ["positions", "orders", "account"],
|
|
627
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
628
|
+
"wait_timeout_ms": 90000,
|
|
629
|
+
"intent": "Require complete live account streams after native cold visible-content proof; live prices remain an independent optional milestone",
|
|
630
|
+
"next": "capture-position"
|
|
631
|
+
},
|
|
632
|
+
"finish-cold-disk-cache-performance-capture": {
|
|
633
|
+
"action": "metamask.perps.capture_performance",
|
|
634
|
+
"phase": "end",
|
|
635
|
+
"require_records": false,
|
|
636
|
+
"required_live_streams": ["positions", "orders", "account"],
|
|
637
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
638
|
+
"wait_timeout_ms": 90000,
|
|
639
|
+
"intent": "Require complete live account takeover after native cached-content proof",
|
|
640
|
+
"next": "capture-position"
|
|
641
|
+
},
|
|
642
|
+
"finish-background-short-performance-capture": {
|
|
643
|
+
"action": "metamask.perps.capture_performance",
|
|
644
|
+
"phase": "end",
|
|
645
|
+
"require_records": false,
|
|
646
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
647
|
+
"intent": "Preserve the short-resume capture after native resident-content proof; a new socket frame is not required while continuity is retained",
|
|
648
|
+
"next": "capture-position"
|
|
649
|
+
},
|
|
650
|
+
"finish-account-switch-performance-capture": {
|
|
651
|
+
"action": "metamask.perps.capture_performance",
|
|
652
|
+
"phase": "end",
|
|
653
|
+
"require_records": false,
|
|
654
|
+
"required_live_streams": ["positions", "orders", "account"],
|
|
655
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
656
|
+
"wait_timeout_ms": 90000,
|
|
657
|
+
"intent": "Require complete live data for the selected target account after native position-content proof",
|
|
658
|
+
"next": "capture-position"
|
|
659
|
+
},
|
|
660
|
+
"finish-account-switch-empty-performance-capture": {
|
|
661
|
+
"action": "metamask.perps.capture_performance",
|
|
662
|
+
"phase": "end",
|
|
663
|
+
"require_records": false,
|
|
664
|
+
"required_live_streams": ["positions", "orders", "account"],
|
|
665
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
666
|
+
"wait_timeout_ms": 90000,
|
|
667
|
+
"intent": "Require complete live empty-account data after native trending-content proof",
|
|
668
|
+
"next": "capture-position"
|
|
669
|
+
},
|
|
670
|
+
"finish-performance-capture": {
|
|
671
|
+
"action": "metamask.perps.capture_performance",
|
|
672
|
+
"phase": "end",
|
|
673
|
+
"require_records": false,
|
|
674
|
+
"required_live_streams": ["positions", "orders", "account"],
|
|
675
|
+
"artifact_prefix": "logs/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}",
|
|
676
|
+
"wait_timeout_ms": 90000,
|
|
677
|
+
"intent": "Require complete post-transition account streams after native visible-content proof",
|
|
678
|
+
"next": "capture-position"
|
|
679
|
+
},
|
|
680
|
+
"capture-position": {
|
|
681
|
+
"action": "ui.screenshot",
|
|
682
|
+
"path": "screenshots/perps-{{params.content_variant}}-{{params.lifecycle}}-{{params.sample_id}}.png",
|
|
683
|
+
"intent": "Preserve the settled native-visible Perps content for this exact lifecycle and sample",
|
|
684
|
+
"next": "done"
|
|
685
|
+
},
|
|
686
|
+
"invalid-lifecycle": {
|
|
687
|
+
"action": "end",
|
|
688
|
+
"status": "fail"
|
|
689
|
+
},
|
|
690
|
+
"done": {
|
|
691
|
+
"action": "end",
|
|
692
|
+
"status": "pass"
|
|
39
693
|
}
|
|
40
694
|
}
|
|
41
695
|
}
|