@deeeed/metamask-harness 0.36.0 → 0.38.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 (140) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/adapters/extension/artifact-runtime-state.cjs +138 -0
  3. package/adapters/extension/inject.mjs +2 -0
  4. package/adapters/extension/launch-browser.cjs +24 -0
  5. package/adapters/extension/live.sh +82 -12
  6. package/adapters/extension/readiness.mjs +77 -36
  7. package/adapters/extension/snapshot-dist.sh +88 -3
  8. package/adapters/extension/verify.sh +6 -2
  9. package/adapters/manifest.json +17 -1
  10. package/adapters/shared/log-tui.mjs +1 -1
  11. package/dist/adapters/extension/artifact-integrity.js +38 -0
  12. package/dist/adapters/extension/extension-id.js +23 -4
  13. package/dist/adapters/extension/release-artifact.js +386 -0
  14. package/dist/adapters/extension/runtime-decision.js +164 -20
  15. package/dist/adapters/extension/runtime.js +169 -3
  16. package/dist/adapters/mobile/provision.js +38 -3
  17. package/dist/adapters/mobile/release-artifact-state.js +124 -0
  18. package/dist/adapters/mobile/release-artifact.js +295 -0
  19. package/dist/adapters.js +78 -6
  20. package/dist/app-lifecycle.js +4 -3
  21. package/dist/command-contract.js +16 -0
  22. package/dist/commands/call.js +6 -2
  23. package/dist/commands/launch/extension.js +74 -9
  24. package/dist/commands/launch/index.js +3 -0
  25. package/dist/commands/launch/mobile.js +2 -0
  26. package/dist/commands/provision.js +2 -0
  27. package/dist/commands/run-engine.js +109 -14
  28. package/dist/commands/run.js +4 -2
  29. package/dist/commands/runtime-launch.js +178 -10
  30. package/dist/heal-bounds.js +1 -1
  31. package/dist/live-adapter-contract.js +3 -1
  32. package/dist/metamask-action-validation.js +47 -1
  33. package/dist/mm-harness-cli.js +31 -1
  34. package/dist/recipe-security.js +40 -0
  35. package/dist/run-diagnostics.js +1 -1
  36. package/dist/runner.js +3 -0
  37. package/docs/RELEASE-QA-CAPABILITY-MAP.md +125 -0
  38. package/library/actions/extension/assets/finish_send.mjs +128 -0
  39. package/library/actions/extension/assets/import_custom_token.mjs +227 -0
  40. package/library/actions/extension/assets/prepare_send.mjs +53 -0
  41. package/library/actions/extension/assets/read_details.mjs +57 -0
  42. package/library/actions/extension/assets/read_visible_state.mjs +50 -0
  43. package/library/actions/extension/assets/review_send.mjs +23 -0
  44. package/library/actions/extension/assets/select_network_scope.mjs +30 -0
  45. package/library/actions/extension/assets/send.mjs +104 -0
  46. package/library/actions/extension/assets/set_custom_gas.mjs +56 -0
  47. package/library/actions/extension/assets/set_token_visibility.mjs +129 -0
  48. package/library/actions/extension/assets/verify_sorting.mjs +89 -0
  49. package/library/actions/extension/networks/add_chainlist.mjs +94 -0
  50. package/library/actions/extension/networks/add_custom.mjs +123 -0
  51. package/library/actions/extension/networks/custom_network.mjs +103 -0
  52. package/library/actions/extension/networks/read_visible_state.mjs +50 -0
  53. package/library/actions/extension/networks/remove_custom.mjs +68 -0
  54. package/library/actions/extension/perps/close_orders.mjs +1 -0
  55. package/library/actions/extension/perps/close_visible_position.mjs +133 -0
  56. package/library/actions/extension/perps/compare_provider_market.mjs +109 -0
  57. package/library/actions/extension/perps/edit_margin.mjs +82 -0
  58. package/library/actions/extension/perps/open_balance_action.mjs +58 -0
  59. package/library/actions/extension/perps/open_position_action.mjs +80 -0
  60. package/library/actions/extension/perps/perps.mjs +196 -2
  61. package/library/actions/extension/perps/place_order.mjs +5 -2
  62. package/library/actions/extension/perps/read_eligibility.mjs +34 -0
  63. package/library/actions/extension/perps/read_funds_confirmation.mjs +69 -0
  64. package/library/actions/extension/perps/read_snapshot.mjs +470 -0
  65. package/library/actions/extension/perps/read_visible_state.mjs +98 -0
  66. package/library/actions/extension/perps/select_activity_filter.mjs +44 -0
  67. package/library/actions/extension/perps/select_market_filter.mjs +71 -0
  68. package/library/actions/extension/perps/set_market_favorite.mjs +47 -0
  69. package/library/actions/extension/perps/update_position_tpsl.mjs +106 -0
  70. package/library/actions/extension/platform/cdp.mjs +109 -3
  71. package/library/actions/extension/settings/set_basic_functionality.mjs +58 -0
  72. package/library/actions/extension/swap_bridge/read_visible_state.mjs +71 -0
  73. package/library/actions/extension/swap_bridge/select_assets.mjs +103 -0
  74. package/library/actions/extension/swap_bridge/set_amount.mjs +36 -0
  75. package/library/actions/extension/swap_bridge/set_max_amount.mjs +58 -0
  76. package/library/actions/extension/swap_bridge/set_slippage.mjs +121 -0
  77. package/library/actions/extension/swap_bridge/submit_transaction.mjs +363 -0
  78. package/library/actions/extension/ui/activate_and_observe.mjs +96 -0
  79. package/library/actions/extension/ui/navigate.mjs +264 -8
  80. package/library/actions/extension/wallet/ensure_unlocked.mjs +2 -6
  81. package/library/actions/extension/wallet/import.mjs +13 -46
  82. package/library/actions/extension/wallet/lock.mjs +35 -0
  83. package/library/actions/extension/wallet/secret-input.mjs +98 -0
  84. package/library/actions/extension/wallet/select_account.mjs +71 -7
  85. package/library/actions/mobile/assets/read_visible_state.mjs +37 -0
  86. package/library/actions/mobile/perps/read_visible_state.mjs +31 -0
  87. package/library/actions/mobile/platform/native-session-name.mjs +5 -0
  88. package/library/actions/mobile/platform/observe-ui.mjs +86 -2
  89. package/library/actions/mobile/swap_bridge/native-session.mjs +45 -0
  90. package/library/actions/mobile/swap_bridge/read_visible_state.mjs +31 -0
  91. package/library/actions/mobile/swap_bridge/select_assets.mjs +94 -0
  92. package/library/actions/mobile/swap_bridge/set_amount.mjs +73 -0
  93. package/library/actions/mobile/ui/native-navigation.mjs +265 -0
  94. package/library/actions/mobile/ui/navigate.mjs +10 -1
  95. package/library/actions/mobile/wallet/ensure_unlocked.mjs +17 -0
  96. package/library/actions/mobile/wallet/import.mjs +71 -2
  97. package/library/actions/mobile/wallet/native-ui.mjs +512 -0
  98. package/library/actions/mobile/wallet/read_state.mjs +16 -0
  99. package/library/actions/mobile/wallet/reset.mjs +17 -4
  100. package/library/actions/shared/assets/visible-state.mjs +176 -0
  101. package/library/actions/shared/networks/visible-state.mjs +70 -0
  102. package/library/actions/shared/perps/visible-state.mjs +354 -0
  103. package/library/actions/shared/swap-bridge/transaction.mjs +54 -0
  104. package/library/actions/shared/swap-bridge/visible-state.mjs +97 -0
  105. package/library/actions/shared/ui/locators.mjs +7 -0
  106. package/library/manifests/extension.action-manifest.json +1366 -184
  107. package/library/manifests/mobile.action-manifest.json +235 -1
  108. package/library/recipes/assets/release-custom-gas-send.recipe.json +88 -0
  109. package/library/recipes/assets/release-custom-network-token-persistence.recipe.json +106 -0
  110. package/library/recipes/assets/release-native-max-cancel.recipe.json +70 -0
  111. package/library/recipes/assets/release-native-max-send.recipe.json +78 -0
  112. package/library/recipes/assets/release-own-account-send.recipe.json +80 -0
  113. package/library/recipes/assets/release-token-address-import.recipe.json +47 -0
  114. package/library/recipes/assets/release-token-details.recipe.json +48 -0
  115. package/library/recipes/assets/release-token-hide-readd.recipe.json +55 -0
  116. package/library/recipes/assets/release-token-list.recipe.json +75 -0
  117. package/library/recipes/assets/release-token-persistence.recipe.json +73 -0
  118. package/library/recipes/assets/release-token-search-import.recipe.json +40 -0
  119. package/library/recipes/assets/release-token-sorting.recipe.json +29 -0
  120. package/library/recipes/extension/networks/release-balance-stability.recipe.json +51 -0
  121. package/library/recipes/extension/perps/release-live-limit-order.recipe.json +104 -0
  122. package/library/recipes/extension/perps/release-order-entry.recipe.json +155 -0
  123. package/library/recipes/extension/perps/release-order-validation.recipe.json +220 -0
  124. package/library/recipes/extension/runner/action-validation.recipe.json +12 -1
  125. package/library/recipes/perps/release-activity-filters.recipe.json +51 -0
  126. package/library/recipes/perps/release-funds-flows.recipe.json +76 -0
  127. package/library/recipes/perps/release-live-market-order.recipe.json +122 -0
  128. package/library/recipes/perps/release-market-details.recipe.json +83 -0
  129. package/library/recipes/perps/release-market-search.recipe.json +79 -0
  130. package/library/recipes/perps/release-watchlist.recipe.json +99 -0
  131. package/library/recipes/swap-bridge/release-custom-slippage.recipe.json +90 -0
  132. package/library/recipes/swap-bridge/release-live-max-swap.recipe.json +99 -0
  133. package/library/recipes/swap-bridge/release-live-swap.recipe.json +101 -0
  134. package/library/recipes/swap-bridge/release-max-quote.recipe.json +72 -0
  135. package/library/recipes/swap-bridge/release-quote.recipe.json +72 -0
  136. package/library/recipes/swap-bridge/release-surface.recipe.json +43 -0
  137. package/library/recipes/wallet/import.recipe.json +20 -1
  138. package/library/recipes/wallet/reset-import.recipe.json +20 -1
  139. package/package.json +6 -5
  140. package/scripts/validate-release-report.mjs +319 -0
@@ -0,0 +1,80 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release own-account token send",
4
+ "description": "Sends a tiny token amount between owned accounts and proves its confirmed Activity details.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "source_address": { "type": "string", "default": "0x8dc623e964475d4d669da601fd15ea9125469003" },
10
+ "network": { "type": "string", "default": "Arbitrum" },
11
+ "chain_id": { "type": "integer", "minimum": 1, "default": 42161 },
12
+ "symbol": { "type": "string", "default": "USDC" },
13
+ "recipient": { "type": "string", "default": "0x5993d2153f080470bfe765ae81f4fa5fa2080916" },
14
+ "amount": { "type": ["string", "number"], "default": "0.01" },
15
+ "confirm_live": { "type": "boolean", "default": false },
16
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 120000 }
17
+ }
18
+ },
19
+ "workflow": {
20
+ "entry": "select-source",
21
+ "nodes": {
22
+ "select-source": {
23
+ "action": "metamask.wallet.select_account",
24
+ "address": "{{params.source_address}}",
25
+ "intent": "Select the funded source account",
26
+ "next": "select-network"
27
+ },
28
+ "select-network": {
29
+ "action": "ui.navigate",
30
+ "page": "network",
31
+ "network": "{{params.network}}",
32
+ "chain_id": "{{params.chain_id}}",
33
+ "add_if_missing": false,
34
+ "timeout_ms": "{{params.timeout_ms}}",
35
+ "intent": "Select the funded token network",
36
+ "next": "prepare-send"
37
+ },
38
+ "prepare-send": {
39
+ "action": "metamask.assets.prepare_send",
40
+ "symbol": "{{params.symbol}}",
41
+ "recipient": "{{params.recipient}}",
42
+ "amount": "{{params.amount}}",
43
+ "timeout_ms": "{{params.timeout_ms}}",
44
+ "intent": "Prepare the tiny own-account token send",
45
+ "next": "review-send"
46
+ },
47
+ "review-send": {
48
+ "action": "metamask.assets.review_send",
49
+ "timeout_ms": "{{params.timeout_ms}}",
50
+ "intent": "Review the send and prove its network fee",
51
+ "next": "capture-confirmation"
52
+ },
53
+ "capture-confirmation": {
54
+ "action": "ui.screenshot",
55
+ "path": "screenshots/assets-own-account-send-confirmation.png",
56
+ "label": "Own-account token send confirmation",
57
+ "intent": "Preserve the reviewed send evidence",
58
+ "next": "finish-send"
59
+ },
60
+ "finish-send": {
61
+ "action": "metamask.assets.finish_send",
62
+ "decision": "confirm",
63
+ "symbol": "{{params.symbol}}",
64
+ "amount": "{{params.amount}}",
65
+ "confirm_live": "{{params.confirm_live}}",
66
+ "timeout_ms": "{{params.timeout_ms}}",
67
+ "intent": "Confirm the authorized tiny send and prove its Activity details",
68
+ "next": "capture-confirmed"
69
+ },
70
+ "capture-confirmed": {
71
+ "action": "ui.screenshot",
72
+ "path": "screenshots/assets-own-account-send-confirmed.png",
73
+ "label": "Own-account token send confirmed",
74
+ "intent": "Preserve the confirmed transaction evidence",
75
+ "next": "done"
76
+ },
77
+ "done": { "action": "end", "status": "pass" }
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token address import",
4
+ "description": "Imports a token by address on a selected non-current network and proves the token persists in the list.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "network": { "type": "string", "default": "Polygon" },
10
+ "chain_id": { "type": "integer", "minimum": 1, "default": 137 },
11
+ "address": { "type": "string", "default": "0xc2132D05D31c914a87C6611C10748AaCbC5327aE" },
12
+ "symbol": { "type": "string", "default": "USDT" },
13
+ "decimals": { "type": "integer", "minimum": 0, "default": 6 },
14
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
15
+ }
16
+ },
17
+ "workflow": {
18
+ "entry": "open-wallet",
19
+ "nodes": {
20
+ "open-wallet": {
21
+ "action": "ui.navigate",
22
+ "page": "home",
23
+ "intent": "Open the all-network asset list",
24
+ "next": "import-token"
25
+ },
26
+ "import-token": {
27
+ "action": "metamask.assets.import_custom_token",
28
+ "network": "{{params.network}}",
29
+ "chain_id": "{{params.chain_id}}",
30
+ "address": "{{params.address}}",
31
+ "expected_symbol": "{{params.symbol}}",
32
+ "decimals": "{{params.decimals}}",
33
+ "timeout_ms": "{{params.timeout_ms}}",
34
+ "intent": "Import the token by address on the selected network and verify its metadata",
35
+ "next": "capture-imported-token"
36
+ },
37
+ "capture-imported-token": {
38
+ "action": "ui.screenshot",
39
+ "path": "screenshots/assets-address-import.png",
40
+ "label": "Address-imported token visible",
41
+ "intent": "Preserve reviewer-visible address import evidence",
42
+ "next": "done"
43
+ },
44
+ "done": { "action": "end", "status": "pass" }
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
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.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "symbol": { "type": "string", "default": "ETH" },
10
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
+ }
12
+ },
13
+ "workflow": {
14
+ "entry": "open-wallet",
15
+ "nodes": {
16
+ "open-wallet": {
17
+ "action": "ui.navigate",
18
+ "page": "home",
19
+ "timeout_ms": "{{params.timeout_ms}}",
20
+ "intent": "Open the all-network asset list",
21
+ "next": "open-first-asset"
22
+ },
23
+ "open-first-asset": {
24
+ "action": "ui.press",
25
+ "test_id": "multichain-token-list-button",
26
+ "settle": true,
27
+ "intent": "Open the first visible funded asset through a trusted pointer",
28
+ "next": "assert-details"
29
+ },
30
+ "assert-details": {
31
+ "action": "metamask.assets.read_details",
32
+ "expected_symbol": "{{params.symbol}}",
33
+ "require_chart": true,
34
+ "require_market_cap": true,
35
+ "intent": "Prove live asset price history and market data render without malformed values",
36
+ "next": "capture-details"
37
+ },
38
+ "capture-details": {
39
+ "action": "ui.screenshot",
40
+ "path": "screenshots/assets-token-details.png",
41
+ "label": "Assets release token details",
42
+ "intent": "Preserve reviewer-visible token details evidence",
43
+ "next": "done"
44
+ },
45
+ "done": { "action": "end", "status": "pass" }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token hide and re-add",
4
+ "description": "Hides one imported token and re-enables it through Manage tokens, proving both home-list states.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "query": { "type": "string", "default": "DAI" },
10
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
+ }
12
+ },
13
+ "workflow": {
14
+ "entry": "open-wallet",
15
+ "nodes": {
16
+ "open-wallet": {
17
+ "action": "ui.navigate",
18
+ "page": "home",
19
+ "intent": "Open the all-network asset list",
20
+ "next": "hide-token"
21
+ },
22
+ "hide-token": {
23
+ "action": "metamask.assets.set_token_visibility",
24
+ "query": "{{params.query}}",
25
+ "visible": false,
26
+ "timeout_ms": "{{params.timeout_ms}}",
27
+ "intent": "Disable the imported token and prove its row disappears",
28
+ "next": "capture-hidden"
29
+ },
30
+ "capture-hidden": {
31
+ "action": "ui.screenshot",
32
+ "path": "screenshots/assets-token-hidden.png",
33
+ "label": "Token hidden",
34
+ "intent": "Preserve reviewer-visible hidden state",
35
+ "next": "readd-token"
36
+ },
37
+ "readd-token": {
38
+ "action": "metamask.assets.set_token_visibility",
39
+ "query": "{{params.query}}",
40
+ "visible": true,
41
+ "timeout_ms": "{{params.timeout_ms}}",
42
+ "intent": "Re-enable the token and prove its metadata row returns",
43
+ "next": "capture-restored"
44
+ },
45
+ "capture-restored": {
46
+ "action": "ui.screenshot",
47
+ "path": "screenshots/assets-token-restored.png",
48
+ "label": "Token restored",
49
+ "intent": "Preserve reviewer-visible restored state",
50
+ "next": "done"
51
+ },
52
+ "done": { "action": "end", "status": "pass" }
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token list",
4
+ "description": "Opens the wallet token list and proves selected live assets render formatted fiat and price-change values through visible UI.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "symbols": {
10
+ "type": "array",
11
+ "items": { "type": "string" },
12
+ "default": ["USDC", "BNB"]
13
+ },
14
+ "minimum_asset_count": {
15
+ "type": "integer",
16
+ "minimum": 1,
17
+ "default": 2
18
+ },
19
+ "minimum_price_change_count": {
20
+ "type": "integer",
21
+ "minimum": 0,
22
+ "default": 1
23
+ },
24
+ "minimum_without_price_change_count": {
25
+ "type": "integer",
26
+ "minimum": 0,
27
+ "default": 1
28
+ },
29
+ "require_price_change_styling": {
30
+ "type": "boolean",
31
+ "default": false
32
+ },
33
+ "timeout_ms": {
34
+ "type": "integer",
35
+ "minimum": 1000,
36
+ "default": 45000
37
+ }
38
+ }
39
+ },
40
+ "workflow": {
41
+ "entry": "open-wallet",
42
+ "nodes": {
43
+ "open-wallet": {
44
+ "action": "ui.navigate",
45
+ "page": "home",
46
+ "timeout_ms": "{{params.timeout_ms}}",
47
+ "intent": "Open the wallet token list through visible product navigation",
48
+ "next": "assert-token-list"
49
+ },
50
+ "assert-token-list": {
51
+ "action": "metamask.assets.read_visible_state",
52
+ "minimum_asset_count": "{{params.minimum_asset_count}}",
53
+ "minimum_price_change_count": "{{params.minimum_price_change_count}}",
54
+ "minimum_without_price_change_count": "{{params.minimum_without_price_change_count}}",
55
+ "require_symbols": "{{params.symbols}}",
56
+ "require_fiat": true,
57
+ "require_price_change_styling": "{{params.require_price_change_styling}}",
58
+ "max_items": 100,
59
+ "intent": "Prove selected live assets, formatted fiat, price changes, and clean values are visible",
60
+ "next": "capture-token-list"
61
+ },
62
+ "capture-token-list": {
63
+ "action": "ui.screenshot",
64
+ "path": "screenshots/assets-token-list.png",
65
+ "label": "Assets release token list",
66
+ "intent": "Preserve reviewer-visible proof of the live token list",
67
+ "next": "done"
68
+ },
69
+ "done": {
70
+ "action": "end",
71
+ "status": "pass"
72
+ }
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token persistence",
4
+ "description": "Locks and unlocks the wallet, then proves an imported token and its management toggle persisted.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "query": { "type": "string", "default": "DAI" },
10
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
+ }
12
+ },
13
+ "workflow": {
14
+ "entry": "open-wallet",
15
+ "nodes": {
16
+ "open-wallet": {
17
+ "action": "ui.navigate",
18
+ "page": "home",
19
+ "intent": "Open the all-network asset list",
20
+ "next": "assert-prestate"
21
+ },
22
+ "assert-prestate": {
23
+ "action": "metamask.assets.set_token_visibility",
24
+ "query": "{{params.query}}",
25
+ "visible": true,
26
+ "require_unchanged": true,
27
+ "timeout_ms": "{{params.timeout_ms}}",
28
+ "intent": "Prove the imported token is enabled before the lock cycle",
29
+ "next": "capture-before"
30
+ },
31
+ "capture-before": {
32
+ "action": "ui.screenshot",
33
+ "path": "screenshots/assets-token-before-lock.png",
34
+ "label": "Imported token before lock",
35
+ "intent": "Preserve pre-lock token evidence",
36
+ "next": "lock-wallet"
37
+ },
38
+ "lock-wallet": {
39
+ "action": "metamask.wallet.lock",
40
+ "intent": "Lock the wallet through the visible global menu",
41
+ "next": "unlock-wallet"
42
+ },
43
+ "unlock-wallet": {
44
+ "action": "metamask.wallet.ensure_unlocked",
45
+ "intent": "Unlock the same persisted profile",
46
+ "next": "open-after-unlock"
47
+ },
48
+ "open-after-unlock": {
49
+ "action": "ui.navigate",
50
+ "page": "home",
51
+ "intent": "Reopen the token list after unlock",
52
+ "next": "assert-persisted"
53
+ },
54
+ "assert-persisted": {
55
+ "action": "metamask.assets.set_token_visibility",
56
+ "query": "{{params.query}}",
57
+ "visible": true,
58
+ "require_unchanged": true,
59
+ "timeout_ms": "{{params.timeout_ms}}",
60
+ "intent": "Prove the token row and enabled management toggle persisted",
61
+ "next": "capture-after"
62
+ },
63
+ "capture-after": {
64
+ "action": "ui.screenshot",
65
+ "path": "screenshots/assets-token-after-unlock.png",
66
+ "label": "Imported token after unlock",
67
+ "intent": "Preserve post-unlock persistence evidence",
68
+ "next": "done"
69
+ },
70
+ "done": { "action": "end", "status": "pass" }
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
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.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "query": { "type": "string", "default": "DAI" },
10
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
11
+ }
12
+ },
13
+ "workflow": {
14
+ "entry": "open-wallet",
15
+ "nodes": {
16
+ "open-wallet": {
17
+ "action": "ui.navigate",
18
+ "page": "home",
19
+ "intent": "Open the all-network asset list",
20
+ "next": "import-token"
21
+ },
22
+ "import-token": {
23
+ "action": "metamask.assets.set_token_visibility",
24
+ "query": "{{params.query}}",
25
+ "visible": true,
26
+ "timeout_ms": "{{params.timeout_ms}}",
27
+ "intent": "Find the token through the live API and enable its management toggle",
28
+ "next": "capture-imported-token"
29
+ },
30
+ "capture-imported-token": {
31
+ "action": "ui.screenshot",
32
+ "path": "screenshots/assets-imported-token.png",
33
+ "label": "Imported token visible",
34
+ "intent": "Preserve reviewer-visible import evidence",
35
+ "next": "done"
36
+ },
37
+ "done": { "action": "end", "status": "pass" }
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release token sorting",
4
+ "description": "Exercises and verifies both token-list sort modes through visible product controls.",
5
+ "workflow": {
6
+ "entry": "open-wallet",
7
+ "nodes": {
8
+ "open-wallet": {
9
+ "action": "ui.navigate",
10
+ "page": "home",
11
+ "intent": "Open the all-network asset list",
12
+ "next": "verify-sorts"
13
+ },
14
+ "verify-sorts": {
15
+ "action": "metamask.assets.verify_sorting",
16
+ "intent": "Select A-Z and fiat high-low and assert the visible row order",
17
+ "next": "capture-sorted-list"
18
+ },
19
+ "capture-sorted-list": {
20
+ "action": "ui.screenshot",
21
+ "path": "screenshots/assets-sorted-high-low.png",
22
+ "label": "Assets sorted by declining balance",
23
+ "intent": "Preserve reviewer-visible sorted token list evidence",
24
+ "next": "done"
25
+ },
26
+ "done": { "action": "end", "status": "pass" }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Custom network balance stability",
4
+ "description": "Adds or selects one supported network through visible UI and proves its token row and balance persist through a settle window.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["network", "chain_id", "symbols"],
9
+ "properties": {
10
+ "network": { "type": "string" },
11
+ "chain_id": { "type": "integer", "minimum": 1 },
12
+ "symbols": { "type": "array", "items": { "type": "string" } },
13
+ "add_if_missing": { "type": "boolean", "default": true },
14
+ "settle_ms": { "type": "integer", "minimum": 0, "default": 30000 },
15
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
16
+ }
17
+ },
18
+ "workflow": {
19
+ "entry": "select-network",
20
+ "nodes": {
21
+ "select-network": {
22
+ "action": "ui.navigate",
23
+ "page": "network",
24
+ "network": "{{params.network}}",
25
+ "chain_id": "{{params.chain_id}}",
26
+ "add_if_missing": "{{params.add_if_missing}}",
27
+ "timeout_ms": "{{params.timeout_ms}}",
28
+ "intent": "Add when needed and select the requested network through supported visible controls",
29
+ "next": "assert-stability"
30
+ },
31
+ "assert-stability": {
32
+ "action": "metamask.networks.read_visible_state",
33
+ "network": "{{params.network}}",
34
+ "chain_id": "{{params.chain_id}}",
35
+ "require_symbols": "{{params.symbols}}",
36
+ "minimum_asset_count": 1,
37
+ "settle_ms": "{{params.settle_ms}}",
38
+ "intent": "Prove the selected network and its balance rows persist across the settle window without a price API error",
39
+ "next": "capture-network"
40
+ },
41
+ "capture-network": {
42
+ "action": "ui.screenshot",
43
+ "path": "screenshots/network-balance-stability.png",
44
+ "label": "Custom network balance stability",
45
+ "intent": "Preserve reviewer-visible proof of the stable network balance row",
46
+ "next": "done"
47
+ },
48
+ "done": { "action": "end", "status": "pass" }
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Perps release live limit order",
4
+ "description": "Places and cancels one small resting Perps limit order through visible product controls.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["confirm_live"],
9
+ "properties": {
10
+ "market": {
11
+ "type": "string",
12
+ "default": "BTC"
13
+ },
14
+ "amount": {
15
+ "type": "integer",
16
+ "minimum": 10,
17
+ "default": 10
18
+ },
19
+ "leverage": {
20
+ "type": "integer",
21
+ "minimum": 1,
22
+ "default": 3
23
+ },
24
+ "offset_pct": {
25
+ "type": "number",
26
+ "default": -2
27
+ },
28
+ "confirm_live": {
29
+ "type": "boolean"
30
+ }
31
+ }
32
+ },
33
+ "workflow": {
34
+ "entry": "open-market",
35
+ "nodes": {
36
+ "open-market": {
37
+ "action": "ui.navigate",
38
+ "page": "perps-market",
39
+ "market": "{{params.market}}",
40
+ "intent": "Open the requested live Perps market",
41
+ "next": "assert-clean"
42
+ },
43
+ "assert-clean": {
44
+ "action": "metamask.perps.read_visible_state",
45
+ "surface": "market-details",
46
+ "market": "{{params.market}}",
47
+ "maximum_order_count": 0,
48
+ "intent": "Prove no order is open before submission",
49
+ "next": "place-limit"
50
+ },
51
+ "place-limit": {
52
+ "action": "metamask.perps.place_order",
53
+ "market": "{{params.market}}",
54
+ "side": "long",
55
+ "amount": "{{params.amount}}",
56
+ "leverage": "{{params.leverage}}",
57
+ "order_type": "limit",
58
+ "offset_pct": "{{params.offset_pct}}",
59
+ "confirm_live": "{{params.confirm_live}}",
60
+ "timeout_ms": 45000,
61
+ "intent": "Submit one authorized resting limit order through visible controls",
62
+ "next": "assert-open"
63
+ },
64
+ "assert-open": {
65
+ "action": "metamask.perps.read_visible_state",
66
+ "surface": "market-details",
67
+ "market": "{{params.market}}",
68
+ "minimum_order_count": 1,
69
+ "maximum_position_count": 0,
70
+ "require_test_ids": ["perps-orders-section-header"],
71
+ "max_items": 200,
72
+ "intent": "Prove the live limit order appears in the market",
73
+ "next": "capture-open"
74
+ },
75
+ "capture-open": {
76
+ "action": "ui.screenshot",
77
+ "path": "screenshots/perps-live-limit-order.png",
78
+ "label": "Perps live limit order",
79
+ "intent": "Preserve reviewer-visible proof of the resting order",
80
+ "next": "cancel-order"
81
+ },
82
+ "cancel-order": {
83
+ "action": "metamask.perps.close_orders",
84
+ "market": "{{params.market}}",
85
+ "confirm_live": "{{params.confirm_live}}",
86
+ "timeout_ms": 30000,
87
+ "intent": "Cancel the authorized live limit order through visible controls",
88
+ "next": "assert-canceled"
89
+ },
90
+ "assert-canceled": {
91
+ "action": "metamask.perps.read_visible_state",
92
+ "surface": "market-details",
93
+ "market": "{{params.market}}",
94
+ "maximum_order_count": 0,
95
+ "intent": "Prove the order card disappears after cancellation",
96
+ "next": "done"
97
+ },
98
+ "done": {
99
+ "action": "end",
100
+ "status": "pass"
101
+ }
102
+ }
103
+ }
104
+ }