@deeeed/metamask-harness 0.47.4 → 0.49.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.
Files changed (261) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +3 -2
  3. package/adapters/extension/lib/macos-focus.cjs +2 -2
  4. package/adapters/extension/live.sh +6 -8
  5. package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +1 -0
  6. package/adapters/shared/ensure-runner-deps.sh +6 -0
  7. package/dist/adapters/extension/runtime-decision.js +18 -1
  8. package/dist/adapters/extension/runtime.js +5 -5
  9. package/dist/adapters/extension/surface.js +1 -0
  10. package/dist/app-lifecycle.js +3 -1
  11. package/dist/command-contract.js +2 -0
  12. package/dist/commands/call.js +1 -8
  13. package/dist/commands/device-target.js +12 -3
  14. package/dist/commands/doctor.js +7 -5
  15. package/dist/commands/fixtures.js +1 -1
  16. package/dist/commands/help.js +17 -5
  17. package/dist/commands/launch/index.js +10 -0
  18. package/dist/commands/manifest.js +3 -1
  19. package/dist/commands/mobile-device-view.js +13 -3
  20. package/dist/commands/parse-args.js +2 -0
  21. package/dist/commands/run-engine.js +29 -4
  22. package/dist/commands/run.js +1 -1
  23. package/dist/commands/runtime-launch.js +10 -1
  24. package/dist/commands/status.js +8 -4
  25. package/dist/devices.js +31 -9
  26. package/dist/execution-provenance.js +8 -7
  27. package/dist/funding-execution-context.js +62 -17
  28. package/dist/heal-bounds.js +3 -3
  29. package/dist/live-adapter-contract.js +4 -0
  30. package/dist/manifest.js +2 -13
  31. package/dist/metamask-action-validation.js +3 -2
  32. package/dist/mm-harness-cli.js +4 -2
  33. package/dist/runner.js +14 -3
  34. package/docs/RECIPES.md +135 -24
  35. package/docs/RELEASE-QA-CAPABILITY-MAP.md +3 -2
  36. package/library/actions/core/perps/_controller.mjs +24 -24
  37. package/library/actions/core/perps/assert_orders.mjs +3 -5
  38. package/library/actions/core/perps/assert_positions.mjs +3 -5
  39. package/library/actions/core/perps/close_orders.mjs +39 -19
  40. package/library/actions/core/perps/close_positions.mjs +53 -12
  41. package/library/actions/core/perps/edit_order.mjs +2 -0
  42. package/library/actions/core/perps/ensure_orders.mjs +3 -4
  43. package/library/actions/core/perps/ensure_positions.mjs +4 -5
  44. package/library/actions/core/perps/place_order.mjs +7 -14
  45. package/library/actions/core/perps/read_account.mjs +2 -0
  46. package/library/actions/core/perps/read_orders.mjs +2 -0
  47. package/library/actions/core/perps/read_positions.mjs +3 -1
  48. package/library/actions/core/perps/read_snapshot.mjs +3 -0
  49. package/library/actions/core/perps/start_state.mjs +3 -14
  50. package/library/actions/core/perps/teardown_state.mjs +3 -14
  51. package/library/actions/core/perps/update_position_tpsl.mjs +13 -19
  52. package/library/actions/core/wallet/list_accounts.mjs +3 -0
  53. package/library/actions/extension/analytics/consent.mjs +2 -0
  54. package/library/actions/extension/analytics/set_consent.mjs +2 -0
  55. package/library/actions/extension/assets/home-token-identity.mjs +31 -0
  56. package/library/actions/extension/assets/import_custom_token.mjs +63 -79
  57. package/library/actions/extension/assets/open_details.mjs +19 -7
  58. package/library/actions/extension/assets/prepare_send.mjs +1 -0
  59. package/library/actions/extension/assets/read_details.mjs +62 -29
  60. package/library/actions/extension/assets/read_visible_state.mjs +5 -1
  61. package/library/actions/extension/assets/review_send.mjs +1 -0
  62. package/library/actions/extension/assets/select_network_scope.mjs +17 -9
  63. package/library/actions/extension/assets/send.mjs +2 -0
  64. package/library/actions/extension/assets/set_custom_gas.mjs +1 -0
  65. package/library/actions/extension/assets/set_token_visibility.mjs +86 -17
  66. package/library/actions/extension/assets/verify_sorting.mjs +63 -14
  67. package/library/actions/extension/deeplink/open.mjs +1 -0
  68. package/library/actions/extension/networks/add_chainlist.mjs +2 -0
  69. package/library/actions/extension/networks/add_custom.mjs +21 -17
  70. package/library/actions/extension/networks/custom_network.mjs +10 -3
  71. package/library/actions/extension/networks/read_visible_state.mjs +2 -0
  72. package/library/actions/extension/networks/remove_custom.mjs +1 -0
  73. package/library/actions/extension/performance/_navigation-memory.mjs +37 -6
  74. package/library/actions/extension/performance/compare_idle_navigation_memory.mjs +5 -2
  75. package/library/actions/extension/performance/measure_detached_dom.mjs +5 -2
  76. package/library/actions/extension/performance/measure_navigation_memory.mjs +5 -2
  77. package/library/actions/extension/perps/assert_orders.mjs +1 -0
  78. package/library/actions/extension/perps/assert_positions.mjs +1 -0
  79. package/library/actions/extension/perps/assert_visible_consistency.mjs +11 -4
  80. package/library/actions/extension/perps/close_orders.mjs +4 -1
  81. package/library/actions/extension/perps/close_positions.mjs +1 -0
  82. package/library/actions/extension/perps/close_visible_position.mjs +160 -11
  83. package/library/actions/extension/perps/compare_provider_market.mjs +2 -0
  84. package/library/actions/extension/perps/edit_margin.mjs +3 -1
  85. package/library/actions/extension/perps/ensure_orders.mjs +1 -0
  86. package/library/actions/extension/perps/ensure_positions.mjs +1 -0
  87. package/library/actions/extension/perps/mutation-receipt.mjs +54 -3
  88. package/library/actions/extension/perps/open_balance_action.mjs +17 -7
  89. package/library/actions/extension/perps/open_position_action.mjs +1 -0
  90. package/library/actions/extension/perps/perps.mjs +550 -69
  91. package/library/actions/extension/perps/place_order.mjs +1 -0
  92. package/library/actions/extension/perps/read_eligibility.mjs +1 -0
  93. package/library/actions/extension/perps/read_funds_confirmation.mjs +10 -0
  94. package/library/actions/extension/perps/read_orders.mjs +1 -0
  95. package/library/actions/extension/perps/read_positions.mjs +1 -0
  96. package/library/actions/extension/perps/read_snapshot.mjs +4 -1
  97. package/library/actions/extension/perps/read_visible_state.mjs +12 -6
  98. package/library/actions/extension/perps/search_markets.mjs +8 -2
  99. package/library/actions/extension/perps/select_activity_filter.mjs +2 -1
  100. package/library/actions/extension/perps/select_market_filter.mjs +75 -45
  101. package/library/actions/extension/perps/set_market_favorite.mjs +7 -3
  102. package/library/actions/extension/perps/state.mjs +2 -0
  103. package/library/actions/extension/perps/update_position_tpsl.mjs +3 -1
  104. package/library/actions/extension/perps/visible-mutation-identity.mjs +6 -2
  105. package/library/actions/extension/platform/cdp.mjs +50 -142
  106. package/library/actions/extension/settings/set_basic_functionality.mjs +1 -0
  107. package/library/actions/extension/swap_bridge/quote-state.mjs +56 -0
  108. package/library/actions/extension/swap_bridge/read_visible_state.mjs +5 -1
  109. package/library/actions/extension/swap_bridge/select_assets.mjs +12 -1
  110. package/library/actions/extension/swap_bridge/set_amount.mjs +11 -8
  111. package/library/actions/extension/swap_bridge/set_max_amount.mjs +18 -18
  112. package/library/actions/extension/swap_bridge/set_slippage.mjs +1 -9
  113. package/library/actions/extension/ui/locators.mjs +1 -0
  114. package/library/actions/extension/ui/navigate.mjs +60 -14
  115. package/library/actions/extension/wallet/ensure_unlocked.mjs +2 -0
  116. package/library/actions/extension/wallet/import.mjs +2 -0
  117. package/library/actions/extension/wallet/list_accounts.mjs +1 -0
  118. package/library/actions/extension/wallet/lock.mjs +4 -1
  119. package/library/actions/extension/wallet/read_state.mjs +1 -0
  120. package/library/actions/extension/wallet/reset.mjs +2 -0
  121. package/library/actions/extension/wallet/secret-input.mjs +2 -0
  122. package/library/actions/extension/wallet/select_account.mjs +2 -0
  123. package/library/actions/extension/wallet/setup.mjs +1 -0
  124. package/library/actions/extension/wallet/state.mjs +2 -0
  125. package/library/actions/extension/wallet/visible-session.mjs +2 -0
  126. package/library/actions/mobile/analytics/consent-settings.mjs +1 -0
  127. package/library/actions/mobile/analytics/set_consent.mjs +1 -0
  128. package/library/actions/mobile/app/network-control.mjs +2 -0
  129. package/library/actions/mobile/app/network.mjs +1 -0
  130. package/library/actions/mobile/app/network_assert.mjs +1 -0
  131. package/library/actions/mobile/app/network_capture.mjs +1 -0
  132. package/library/actions/mobile/assets/import_custom_token.mjs +3 -0
  133. package/library/actions/mobile/assets/open_details.mjs +1 -0
  134. package/library/actions/mobile/assets/read_details.mjs +1 -0
  135. package/library/actions/mobile/assets/read_visible_state.mjs +4 -1
  136. package/library/actions/mobile/assets/set_token_visibility.mjs +15 -9
  137. package/library/actions/mobile/assets/verify_sorting.mjs +90 -7
  138. package/library/actions/mobile/deeplink/open.mjs +1 -0
  139. package/library/actions/mobile/networks/add_custom.mjs +1 -0
  140. package/library/actions/mobile/networks/network-management.mjs +23 -15
  141. package/library/actions/mobile/networks/read_visible_state.mjs +1 -0
  142. package/library/actions/mobile/networks/remove_custom.mjs +7 -2
  143. package/library/actions/mobile/perps/assert_orders.mjs +1 -0
  144. package/library/actions/mobile/perps/assert_positions.mjs +1 -0
  145. package/library/actions/mobile/perps/capture_performance.mjs +1 -0
  146. package/library/actions/mobile/perps/close_orders.mjs +1 -0
  147. package/library/actions/mobile/perps/close_positions.mjs +1 -0
  148. package/library/actions/mobile/perps/ensure_orders.mjs +1 -0
  149. package/library/actions/mobile/perps/ensure_positions.mjs +1 -0
  150. package/library/actions/mobile/perps/measure_homepage_visible.mjs +1 -0
  151. package/library/actions/mobile/perps/performance-capture.mjs +2 -0
  152. package/library/actions/mobile/perps/perps.mjs +8 -1
  153. package/library/actions/mobile/perps/place_order.mjs +1 -0
  154. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +2 -0
  155. package/library/actions/mobile/perps/read-visible-state-loop.mjs +3 -0
  156. package/library/actions/mobile/perps/read_orders.mjs +1 -0
  157. package/library/actions/mobile/perps/read_positions.mjs +1 -0
  158. package/library/actions/mobile/perps/read_visible_state.mjs +1 -0
  159. package/library/actions/mobile/perps/search_markets.mjs +1 -0
  160. package/library/actions/mobile/perps/set_market_favorite.mjs +17 -19
  161. package/library/actions/mobile/platform/bridge.mjs +16 -4
  162. package/library/actions/mobile/platform/native-session-name.mjs +1 -0
  163. package/library/actions/mobile/platform/native-session.mjs +28 -17
  164. package/library/actions/mobile/platform/observe-ui.mjs +4 -2
  165. package/library/actions/mobile/platform/tool-paths.mjs +1 -0
  166. package/library/actions/mobile/swap_bridge/native-session.mjs +1 -0
  167. package/library/actions/mobile/swap_bridge/read_visible_state.mjs +1 -0
  168. package/library/actions/mobile/swap_bridge/select_assets.mjs +2 -0
  169. package/library/actions/mobile/swap_bridge/set_amount.mjs +1 -0
  170. package/library/actions/mobile/swap_bridge/set_max_amount.mjs +1 -0
  171. package/library/actions/mobile/swap_bridge/set_slippage.mjs +1 -0
  172. package/library/actions/mobile/swap_bridge/submit_transaction.mjs +2 -0
  173. package/library/actions/mobile/ui/locators.mjs +1 -0
  174. package/library/actions/mobile/ui/native-navigation.mjs +2 -0
  175. package/library/actions/mobile/ui/navigate.mjs +3 -1
  176. package/library/actions/mobile/wallet/ensure_unlocked.mjs +2 -0
  177. package/library/actions/mobile/wallet/home.mjs +1 -0
  178. package/library/actions/mobile/wallet/import.mjs +2 -0
  179. package/library/actions/mobile/wallet/list_accounts.mjs +1 -0
  180. package/library/actions/mobile/wallet/lock.mjs +1 -0
  181. package/library/actions/mobile/wallet/native-ui.mjs +2 -0
  182. package/library/actions/mobile/wallet/read_state.mjs +2 -0
  183. package/library/actions/mobile/wallet/reset-helper.mjs +1 -0
  184. package/library/actions/mobile/wallet/reset.mjs +1 -0
  185. package/library/actions/mobile/wallet/select_account.mjs +2 -0
  186. package/library/actions/mobile/wallet/setup.mjs +2 -0
  187. package/library/actions/shared/analytics/assert_events.mjs +3 -0
  188. package/library/actions/shared/analytics/consent.mjs +3 -0
  189. package/library/actions/shared/analytics/read_events.mjs +2 -0
  190. package/library/actions/shared/analytics/start_capture.mjs +3 -0
  191. package/library/actions/shared/app/network-artifact.mjs +2 -0
  192. package/library/actions/shared/app/network-assert.mjs +2 -0
  193. package/library/actions/shared/assets/visible-state.mjs +2 -0
  194. package/library/actions/shared/deeplink/url.mjs +3 -0
  195. package/library/actions/shared/networks/visible-state.mjs +2 -0
  196. package/library/actions/shared/perps/visible-state.mjs +16 -3
  197. package/library/actions/shared/swap-bridge/transaction.mjs +3 -0
  198. package/library/actions/shared/swap-bridge/visible-state.mjs +2 -0
  199. package/library/actions/shared/ui/locators.mjs +2 -0
  200. package/library/actions/shared/wallet/import-source.mjs +3 -0
  201. package/library/manifests/core.action-manifest.json +34 -2
  202. package/library/manifests/extension.action-manifest.json +50 -17
  203. package/library/manifests/mobile.action-manifest.json +11 -10
  204. package/library/recipes/core/perps/smoke.recipe.json +23 -0
  205. package/library/recipes/core/perps/snapshot.recipe.json +26 -1
  206. package/library/recipes/extension/assets/release-custom-network-token-persistence.recipe.json +25 -8
  207. package/library/recipes/extension/performance/navigation-memory-suite.recipe.json +219 -0
  208. package/library/recipes/extension/performance/navigation-memory.recipe.json +61 -156
  209. package/library/recipes/extension/wallet/smoke.recipe.json +17 -8
  210. package/library/recipes/mobile/app/lifecycle-smoke.recipe.json +89 -0
  211. package/library/recipes/mobile/networks/release-custom-network-persistence.recipe.json +31 -6
  212. package/library/recipes/mobile/networks/release-multichain-visibility.recipe.json +5 -4
  213. package/library/recipes/mobile/wallet/smoke.recipe.json +17 -8
  214. package/library/recipes/{assets → shared/assets}/release-token-address-import.recipe.json +7 -0
  215. package/library/recipes/{assets → shared/assets}/release-token-details.recipe.json +2 -2
  216. package/library/recipes/shared/assets/release-token-hide-readd.recipe.json +91 -0
  217. package/library/recipes/{assets → shared/assets}/release-token-persistence.recipe.json +3 -0
  218. package/library/recipes/{assets → shared/assets}/release-token-search-import.recipe.json +4 -1
  219. package/library/recipes/{assets → shared/assets}/release-token-sorting.recipe.json +13 -2
  220. package/library/recipes/{swap-bridge → shared/swap-bridge}/release-quote.recipe.json +29 -3
  221. package/package.json +3 -3
  222. package/site/assets/help-recipes.json +220 -27
  223. package/library/recipes/assets/release-token-hide-readd.recipe.json +0 -57
  224. package/library/recipes/core/perps/clean-market-testnet.recipe.json +0 -44
  225. package/library/recipes/core/perps/order-lifecycle.recipe.json +0 -82
  226. package/library/recipes/core/perps/read-markets.recipe.json +0 -36
  227. package/library/recipes/core/perps/trading-lifecycle.recipe.json +0 -80
  228. package/library/recipes/extension/perps/release-activity-filters.recipe.json +0 -51
  229. package/library/recipes/extension/perps/release-funds-flows.recipe.json +0 -76
  230. package/library/recipes/extension/perps/release-live-limit-order.recipe.json +0 -109
  231. package/library/recipes/extension/perps/release-market-filters.recipe.json +0 -97
  232. package/library/recipes/extension/perps/release-order-entry.recipe.json +0 -158
  233. package/library/recipes/extension/perps/release-order-validation.recipe.json +0 -259
  234. package/library/recipes/extension/perps/release-visible-consistency.recipe.json +0 -47
  235. package/library/recipes/extension/perps/source-dev-snapshot-consistency.recipe.json +0 -76
  236. package/library/recipes/mobile/app/lifecycle.android-smoke.recipe.json +0 -69
  237. package/library/recipes/mobile/perps/chase-assert-running.recipe.json +0 -110
  238. package/library/recipes/mobile/perps/chase-place.recipe.json +0 -145
  239. package/library/recipes/mobile/perps/chase-terminate.recipe.json +0 -98
  240. package/library/recipes/mobile/perps/performance.recipe.json +0 -722
  241. package/library/recipes/mobile/perps/pro-order-setup.recipe.json +0 -111
  242. package/library/recipes/mobile/perps/pro-order-start-state.recipe.json +0 -53
  243. package/library/recipes/mobile/perps/scale-assert-orders.recipe.json +0 -126
  244. package/library/recipes/mobile/perps/scale-place.recipe.json +0 -186
  245. package/library/recipes/mobile/perps/twap-assert-active.recipe.json +0 -97
  246. package/library/recipes/mobile/perps/twap-place.recipe.json +0 -146
  247. package/library/recipes/mobile/runner/action-validation.recipe.json +0 -336
  248. package/library/recipes/perps/clean-market-testnet.recipe.json +0 -49
  249. package/library/recipes/perps/lifecycle.recipe.json +0 -144
  250. package/library/recipes/perps/release-live-market-order.recipe.json +0 -139
  251. package/library/recipes/perps/release-watchlist.recipe.json +0 -111
  252. package/library/recipes/swap-bridge/release-max-quote.recipe.json +0 -72
  253. /package/library/recipes/{assets → shared/assets}/release-token-list.recipe.json +0 -0
  254. /package/library/recipes/{perps → shared/perps}/release-market-details.recipe.json +0 -0
  255. /package/library/recipes/{perps → shared/perps}/release-market-search.recipe.json +0 -0
  256. /package/library/recipes/{swap-bridge → shared/swap-bridge}/release-custom-slippage.recipe.json +0 -0
  257. /package/library/recipes/{swap-bridge → shared/swap-bridge}/release-live-max-swap.recipe.json +0 -0
  258. /package/library/recipes/{swap-bridge → shared/swap-bridge}/release-live-swap.recipe.json +0 -0
  259. /package/library/recipes/{swap-bridge → shared/swap-bridge}/release-surface.recipe.json +0 -0
  260. /package/library/recipes/{wallet → shared/wallet}/import.recipe.json +0 -0
  261. /package/library/recipes/{wallet → shared/wallet}/reset-import.recipe.json +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Mobile release custom-network persistence",
4
- "description": "Adds a custom network through native settings, proves it survives lock/unlock, and removes it.",
4
+ "description": "Adds a previously absent custom network through native settings, proves it survives lock/unlock, and removes only the network this run confirmed adding. Existing networks are preserved and refused as proof setup.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
@@ -11,11 +11,14 @@
11
11
  "chain_id": { "type": "integer", "minimum": 1, "default": 369 },
12
12
  "symbol": { "type": "string", "default": "PLS" },
13
13
  "explorer_url": { "type": "string", "default": "https://scan.pulsechain.com" },
14
+ "before_capture_path": { "type": "string", "default": "screenshots/custom-network-before-lock.png" },
15
+ "after_capture_path": { "type": "string", "default": "screenshots/custom-network-after-unlock.png" },
14
16
  "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
15
17
  }
16
18
  },
17
19
  "workflow": {
18
20
  "entry": "open-wallet",
21
+ "teardown": "require-owned-network",
19
22
  "nodes": {
20
23
  "open-wallet": {
21
24
  "action": "ui.navigate",
@@ -32,6 +35,14 @@
32
35
  "explorer_url": "{{params.explorer_url}}",
33
36
  "timeout_ms": "{{params.timeout_ms}}",
34
37
  "intent": "Add the custom network through visible settings",
38
+ "next": "require-added"
39
+ },
40
+ "require-added": {
41
+ "action": "assert_output",
42
+ "source": "add-network",
43
+ "stream": "added",
44
+ "match": "^true$",
45
+ "intent": "Refuse persistence proof when the requested network already existed",
35
46
  "next": "assert-added"
36
47
  },
37
48
  "assert-added": {
@@ -45,7 +56,7 @@
45
56
  },
46
57
  "capture-before": {
47
58
  "action": "ui.screenshot",
48
- "path": "screenshots/custom-network-before-lock.png",
59
+ "path": "{{params.before_capture_path}}",
49
60
  "label": "Custom network before lock",
50
61
  "intent": "Preserve pre-lock network evidence",
51
62
  "next": "lock-wallet"
@@ -71,9 +82,22 @@
71
82
  },
72
83
  "capture-after": {
73
84
  "action": "ui.screenshot",
74
- "path": "screenshots/custom-network-after-unlock.png",
85
+ "path": "{{params.after_capture_path}}",
75
86
  "label": "Custom network after unlock",
76
87
  "intent": "Preserve post-unlock network evidence",
88
+ "next": "done"
89
+ },
90
+ "require-owned-network": {
91
+ "action": "assert_output",
92
+ "source": "add-network",
93
+ "stream": "added",
94
+ "match": "^true$",
95
+ "intent": "Refuse deletion without completed evidence that this run added the network",
96
+ "next": "unlock-cleanup"
97
+ },
98
+ "unlock-cleanup": {
99
+ "action": "metamask.wallet.ensure_unlocked",
100
+ "intent": "Reach the task-owned network settings even if the lock-cycle proof failed",
77
101
  "next": "remove-network"
78
102
  },
79
103
  "remove-network": {
@@ -81,10 +105,11 @@
81
105
  "network": "{{params.network}}",
82
106
  "chain_id": "{{params.chain_id}}",
83
107
  "timeout_ms": "{{params.timeout_ms}}",
84
- "intent": "Remove the custom network and prove it is absent",
85
- "next": "done"
108
+ "intent": "Remove only the custom network this run confirmed adding and prove it is absent",
109
+ "next": "cleanup-done"
86
110
  },
87
- "done": { "action": "end", "status": "pass" }
111
+ "done": { "action": "end", "status": "pass" },
112
+ "cleanup-done": { "action": "end", "status": "pass" }
88
113
  }
89
114
  }
90
115
  }
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Mobile multi-network asset visibility",
4
- "description": "Proves funded assets from multiple protocol families are visible together in the opaque Mobile wallet.",
4
+ "description": "Checks that the requested asset symbols and formatted fiat values appear together in the Mobile wallet. Symbols alone do not prove network identity or funding.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "properties": {
9
+ "capture_path": { "type": "string", "default": "screenshots/mobile-multichain-assets.png" },
9
10
  "symbols": {
10
11
  "type": "array",
11
12
  "items": { "type": "string" },
@@ -39,14 +40,14 @@
39
40
  "minimum_asset_count": "{{params.minimum_asset_count}}",
40
41
  "require_fiat": true,
41
42
  "max_items": 100,
42
- "intent": "Prove assets from the requested protocol families are simultaneously visible",
43
+ "intent": "Prove the requested asset symbols and formatted fiat values appear together",
43
44
  "next": "capture-wallet"
44
45
  },
45
46
  "capture-wallet": {
46
47
  "action": "ui.screenshot",
47
- "path": "screenshots/mobile-multichain-assets.png",
48
+ "path": "{{params.capture_path}}",
48
49
  "label": "Mobile multi-network asset visibility",
49
- "intent": "Preserve reviewer-visible proof of aggregate multi-network holdings",
50
+ "intent": "Preserve reviewer-visible proof of the requested asset rows",
50
51
  "next": "done"
51
52
  },
52
53
  "done": {
@@ -2,18 +2,27 @@
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "MetaMask Mobile wallet smoke",
4
4
  "description": "Fixture-backed proof that the Mobile wallet is reachable, unlocked, readable, and visually capturable without depending on a product feature domain.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "capture_path": { "type": "string", "default": "screenshots/wallet-smoke.png" }
10
+ }
11
+ },
5
12
  "workflow": {
6
- "entry": "status",
13
+ "entry": "fixture",
7
14
  "nodes": {
8
- "status": {
9
- "action": "app.status",
10
- "next": "fixture",
11
- "intent": "Confirm the Mobile runtime is reachable"
12
- },
13
15
  "fixture": {
14
16
  "action": "metamask.wallet.fixture_status",
17
+ "next": "require-fixture",
18
+ "intent": "Read the checkout's wallet fixture readiness without changing it"
19
+ },
20
+ "require-fixture": {
21
+ "action": "assert_output",
22
+ "source": "fixture",
23
+ "assert": { "path": "$.status", "operator": "eq", "value": "ready" },
15
24
  "next": "unlock",
16
- "intent": "Confirm the checkout wallet fixture is ready"
25
+ "intent": "Require a ready on-disk fixture before interacting with the wallet; this does not prove imported account identity"
17
26
  },
18
27
  "unlock": {
19
28
  "action": "metamask.wallet.ensure_unlocked",
@@ -27,7 +36,7 @@
27
36
  },
28
37
  "screenshot": {
29
38
  "action": "ui.screenshot",
30
- "path": "screenshots/wallet-smoke.png",
39
+ "path": "{{params.capture_path}}",
31
40
  "next": "done",
32
41
  "intent": "Record the visible wallet state as evidence"
33
42
  },
@@ -32,6 +32,13 @@
32
32
  "decimals": "{{params.decimals}}",
33
33
  "timeout_ms": "{{params.timeout_ms}}",
34
34
  "intent": "Import the token by address on the selected network and verify its metadata",
35
+ "next": "assert-imported"
36
+ },
37
+ "assert-imported": {
38
+ "action": "assert_output",
39
+ "source": "import-token",
40
+ "assert": { "path": "$.changed", "operator": "eq", "value": true },
41
+ "intent": "Require a completed import rather than reusing an already-imported token",
35
42
  "next": "capture-imported-token"
36
43
  },
37
44
  "capture-imported-token": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Assets release token details",
4
- "description": "Opens the first visible asset and proves its live chart and market cap render through visible product UI.",
4
+ "description": "Open a visible token matching symbol and assert its chart and market cap through product UI. Symbol-only selection does not identify a network or token contract; use a uniquely matching row for this proof. Native reader compatibility must be validated on the tested build.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
@@ -24,7 +24,7 @@
24
24
  "action": "metamask.assets.open_details",
25
25
  "symbol": "{{params.symbol}}",
26
26
  "timeout_ms": "{{params.timeout_ms}}",
27
- "intent": "Open the requested visible funded asset",
27
+ "intent": "Open the visible token matching the requested symbol; no funding or network claim",
28
28
  "next": "assert-details"
29
29
  },
30
30
  "assert-details": {
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token hide and re-add",
4
+ "description": "Requires an enabled imported token, hides and re-enables it through Manage tokens, and restores the enabled baseline on failure. Both proof transitions must change state.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "query": { "type": "string", "default": "DAI" },
10
+ "asset_id": { "type": "string", "default": "", "description": "Exact ERC-20 identity on Extension; leave empty for Mobile query-only selection." },
11
+ "hidden_capture_path": { "type": "string", "default": "screenshots/assets-token-hidden.png" },
12
+ "restored_capture_path": { "type": "string", "default": "screenshots/assets-token-restored.png" },
13
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
14
+ }
15
+ },
16
+ "workflow": {
17
+ "entry": "open-wallet",
18
+ "teardown": "baseline-known",
19
+ "nodes": {
20
+ "open-wallet": {
21
+ "action": "ui.navigate",
22
+ "page": "home",
23
+ "intent": "Open the all-network asset list",
24
+ "next": "assert-baseline"
25
+ },
26
+ "assert-baseline": {
27
+ "action": "metamask.assets.set_token_visibility",
28
+ "asset_id": "{{params.asset_id}}",
29
+ "query": "{{params.query}}",
30
+ "visible": true,
31
+ "require_unchanged": true,
32
+ "timeout_ms": "{{params.timeout_ms}}",
33
+ "intent": "Verify the original enabled token before authorizing any restoration",
34
+ "next": "hide-token"
35
+ },
36
+ "hide-token": {
37
+ "action": "metamask.assets.set_token_visibility",
38
+ "asset_id": "{{params.asset_id}}",
39
+ "query": "{{params.query}}",
40
+ "visible": false,
41
+ "require_change": true,
42
+ "timeout_ms": "{{params.timeout_ms}}",
43
+ "intent": "Disable the imported token and prove its row disappears",
44
+ "next": "capture-hidden"
45
+ },
46
+ "capture-hidden": {
47
+ "action": "ui.screenshot",
48
+ "path": "{{params.hidden_capture_path}}",
49
+ "label": "Token hidden",
50
+ "intent": "Preserve reviewer-visible hidden state",
51
+ "next": "readd-token"
52
+ },
53
+ "readd-token": {
54
+ "action": "metamask.assets.set_token_visibility",
55
+ "asset_id": "{{params.asset_id}}",
56
+ "query": "{{params.query}}",
57
+ "visible": true,
58
+ "require_change": true,
59
+ "timeout_ms": "{{params.timeout_ms}}",
60
+ "intent": "Re-enable the token and prove its metadata row returns",
61
+ "next": "capture-restored"
62
+ },
63
+ "capture-restored": {
64
+ "action": "ui.screenshot",
65
+ "path": "{{params.restored_capture_path}}",
66
+ "label": "Token restored",
67
+ "intent": "Preserve reviewer-visible restored state",
68
+ "next": "done"
69
+ },
70
+ "done": { "action": "end", "status": "pass" },
71
+ "baseline-known": {
72
+ "action": "assert_output",
73
+ "source": "assert-baseline",
74
+ "stream": "requested",
75
+ "match": "^true$",
76
+ "intent": "Refuse restoration when this run did not verify the original enabled token",
77
+ "next": "restore-enabled"
78
+ },
79
+ "restore-enabled": {
80
+ "action": "metamask.assets.set_token_visibility",
81
+ "asset_id": "{{params.asset_id}}",
82
+ "query": "{{params.query}}",
83
+ "visible": true,
84
+ "timeout_ms": "{{params.timeout_ms}}",
85
+ "intent": "Restore the original enabled token after success or failure without changing the proof verdict",
86
+ "next": "cleanup-done"
87
+ },
88
+ "cleanup-done": { "action": "end", "status": "pass" }
89
+ }
90
+ }
91
+ }
@@ -6,6 +6,7 @@
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "properties": {
9
+ "asset_id": { "type": "string", "default": "", "description": "Optional exact ERC-20 identity on Extension; Mobile supports only empty/query-only mode." },
9
10
  "query": { "type": "string", "default": "DAI" },
10
11
  "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
12
  }
@@ -21,6 +22,7 @@
21
22
  },
22
23
  "assert-prestate": {
23
24
  "action": "metamask.assets.set_token_visibility",
25
+ "asset_id": "{{params.asset_id}}",
24
26
  "query": "{{params.query}}",
25
27
  "visible": true,
26
28
  "require_unchanged": true,
@@ -53,6 +55,7 @@
53
55
  },
54
56
  "assert-persisted": {
55
57
  "action": "metamask.assets.set_token_visibility",
58
+ "asset_id": "{{params.asset_id}}",
56
59
  "query": "{{params.query}}",
57
60
  "visible": true,
58
61
  "require_unchanged": true,
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Assets release token search import",
4
- "description": "Imports one token through live Manage tokens search and proves it appears in the token list.",
4
+ "description": "Requires a token that is not already enabled, imports it through live Manage tokens search, and proves it appears in the token list.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "properties": {
9
9
  "query": { "type": "string", "default": "DAI" },
10
+ "asset_id": { "type": "string", "default": "", "description": "Optional exact ERC-20 identity on Extension to disambiguate search results; leave empty for Mobile query-only selection." },
10
11
  "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
12
  }
12
13
  },
@@ -22,7 +23,9 @@
22
23
  "import-token": {
23
24
  "action": "metamask.assets.set_token_visibility",
24
25
  "query": "{{params.query}}",
26
+ "asset_id": "{{params.asset_id}}",
25
27
  "visible": true,
28
+ "require_change": true,
26
29
  "timeout_ms": "{{params.timeout_ms}}",
27
30
  "intent": "Find the token through the live API and enable its management toggle",
28
31
  "next": "capture-imported-token"
@@ -2,6 +2,17 @@
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Assets release token sorting",
4
4
  "description": "Exercises and verifies both token-list sort modes through visible product controls.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "capture_path": {
10
+ "type": "string",
11
+ "default": "screenshots/assets-sorted.png",
12
+ "description": "Final sort-state capture; pass distinct paths when composing repeated checks."
13
+ }
14
+ }
15
+ },
5
16
  "workflow": {
6
17
  "entry": "open-wallet",
7
18
  "nodes": {
@@ -18,8 +29,8 @@
18
29
  },
19
30
  "capture-sorted-list": {
20
31
  "action": "ui.screenshot",
21
- "path": "screenshots/assets-sorted-high-low.png",
22
- "label": "Assets sorted by declining balance",
32
+ "path": "{{params.capture_path}}",
33
+ "label": "Final asset sort state",
23
34
  "intent": "Preserve reviewer-visible sorted token list evidence",
24
35
  "next": "done"
25
36
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Swap release quote",
4
- "description": "Selects an exact live Swap pair, enters a capped amount, and proves a destination quote through visible product UI without submitting a transaction.",
4
+ "description": "Select an exact Swap pair, enter a fixed amount or use Max, and verify a reviewable destination quote without submitting. Extension quote identity requires exposed bridge quote state; an opaque build without it is not certified by UI amounts alone.",
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
@@ -14,7 +14,18 @@
14
14
  "destination_query": { "type": "string", "default": "WETH" },
15
15
  "source_asset_id": { "type": "string", "default": "" },
16
16
  "destination_asset_id": { "type": "string", "default": "" },
17
+ "amount_mode": {
18
+ "type": "string",
19
+ "enum": ["fixed", "max"],
20
+ "default": "fixed",
21
+ "description": "Enter amount or use the visible Max balance. Neither branch submits a transaction."
22
+ },
17
23
  "amount": { "type": "number", "minimum": 0.00000001, "default": 0.0001 },
24
+ "capture_path": {
25
+ "type": "string",
26
+ "default": "screenshots/swap-quote.png",
27
+ "description": "Use a distinct artifact path for each call when composing several quotes in one run."
28
+ },
18
29
  "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
19
30
  }
20
31
  },
@@ -40,7 +51,22 @@
40
51
  "destination_asset_id": "{{params.destination_asset_id}}",
41
52
  "timeout_ms": "{{params.timeout_ms}}",
42
53
  "intent": "Select the exact source and destination assets",
43
- "next": "enter-amount"
54
+ "next": "choose-amount"
55
+ },
56
+ "choose-amount": {
57
+ "action": "switch",
58
+ "value": "{{params.amount_mode}}",
59
+ "equals": "max",
60
+ "cases": { "match": "use-max" },
61
+ "default": "enter-amount",
62
+ "intent": "Run only the requested amount-entry method"
63
+ },
64
+ "use-max": {
65
+ "action": "metamask.swap_bridge.set_max_amount",
66
+ "wait_for_quote": true,
67
+ "timeout_ms": "{{params.timeout_ms}}",
68
+ "intent": "Use the visible available source balance and wait for its quote",
69
+ "next": "assert-quote"
44
70
  },
45
71
  "enter-amount": {
46
72
  "action": "metamask.swap_bridge.set_amount",
@@ -62,7 +88,7 @@
62
88
  },
63
89
  "capture-quote": {
64
90
  "action": "ui.screenshot",
65
- "path": "screenshots/swap-quote.png",
91
+ "path": "{{params.capture_path}}",
66
92
  "label": "Swap release quote",
67
93
  "intent": "Preserve reviewer-visible proof of the live quote",
68
94
  "next": "done"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deeeed/metamask-harness",
3
- "version": "0.47.4",
3
+ "version": "0.49.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mm-harness": "bin/mm-harness"
@@ -21,10 +21,10 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@farmslot/agent-runtime": "0.8.1",
24
- "@farmslot/expo-recipe": "0.8.1",
24
+ "@farmslot/expo-recipe": "0.9.0",
25
25
  "@farmslot/handoff": "^0.3.1",
26
26
  "@farmslot/protocol": "0.21.0",
27
- "@farmslot/recipe-harness": "0.15.1",
27
+ "@farmslot/recipe-harness": "0.16.0",
28
28
  "agent-device": "0.19.3",
29
29
  "commander": "^12.0.0",
30
30
  "es-module-lexer": "2.3.1",