@deeeed/metamask-harness 0.38.1 → 0.40.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 (104) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/adapters/extension/lib/playwright-cdp.cjs +17 -1
  3. package/adapters/extension/sidepanel-toggle.sh +135 -13
  4. package/dist/adapters/mobile/release-artifact.js +65 -0
  5. package/dist/adapters.js +27 -17
  6. package/dist/command-contract.js +10 -2
  7. package/dist/commands/call.js +7 -4
  8. package/dist/commands/launch/index.js +55 -3
  9. package/dist/commands/parse-args.js +6 -0
  10. package/dist/commands/run-engine.js +75 -39
  11. package/dist/funding-execution-context.js +1386 -0
  12. package/dist/live-adapter-contract.js +3 -1
  13. package/dist/metamask-action-validation.js +170 -3
  14. package/dist/mm-harness-cli.js +8 -2
  15. package/dist/recipe-security.js +5 -12
  16. package/dist/runner.js +102 -6
  17. package/docs/RECIPES.md +74 -1
  18. package/docs/RELEASE-QA-CAPABILITY-MAP.md +6 -5
  19. package/library/actions/extension/assets/open_details.mjs +30 -0
  20. package/library/actions/extension/assets/set_token_visibility.mjs +5 -0
  21. package/library/actions/extension/networks/add_chainlist.mjs +4 -0
  22. package/library/actions/extension/networks/add_custom.mjs +4 -0
  23. package/library/actions/extension/networks/custom_network.mjs +48 -1
  24. package/library/actions/extension/perps/assert_visible_consistency.mjs +366 -0
  25. package/library/actions/extension/perps/close_visible_position.mjs +299 -37
  26. package/library/actions/extension/perps/compare_provider_market.mjs +77 -0
  27. package/library/actions/extension/perps/edit_margin.mjs +285 -44
  28. package/library/actions/extension/perps/mutation-receipt.mjs +781 -0
  29. package/library/actions/extension/perps/perps.mjs +1029 -363
  30. package/library/actions/extension/perps/read_funds_confirmation.mjs +126 -13
  31. package/library/actions/extension/perps/read_snapshot.mjs +124 -3
  32. package/library/actions/extension/perps/read_visible_state.mjs +63 -5
  33. package/library/actions/extension/perps/search_markets.mjs +32 -0
  34. package/library/actions/extension/perps/select_activity_filter.mjs +81 -18
  35. package/library/actions/extension/perps/select_market_filter.mjs +48 -4
  36. package/library/actions/extension/perps/set_market_favorite.mjs +6 -1
  37. package/library/actions/extension/perps/update_position_tpsl.mjs +251 -69
  38. package/library/actions/extension/perps/visible-mutation-identity.mjs +164 -0
  39. package/library/actions/extension/platform/cdp.mjs +88 -9
  40. package/library/actions/extension/settings/set_basic_functionality.mjs +35 -7
  41. package/library/actions/extension/swap_bridge/read_visible_state.mjs +2 -6
  42. package/library/actions/extension/swap_bridge/set_amount.mjs +11 -2
  43. package/library/actions/extension/ui/navigate.mjs +45 -5
  44. package/library/actions/extension/wallet/import.mjs +70 -29
  45. package/library/actions/extension/wallet/lock.mjs +62 -5
  46. package/library/actions/extension/wallet/visible-session.mjs +218 -0
  47. package/library/actions/mobile/assets/import_custom_token.mjs +181 -0
  48. package/library/actions/mobile/assets/open_details.mjs +43 -0
  49. package/library/actions/mobile/assets/read_details.mjs +96 -0
  50. package/library/actions/mobile/assets/set_token_visibility.mjs +302 -0
  51. package/library/actions/mobile/assets/verify_sorting.mjs +104 -0
  52. package/library/actions/mobile/networks/add_custom.mjs +125 -0
  53. package/library/actions/mobile/networks/network-management.mjs +132 -0
  54. package/library/actions/mobile/networks/read_visible_state.mjs +43 -0
  55. package/library/actions/mobile/networks/remove_custom.mjs +100 -0
  56. package/library/actions/mobile/perps/search_markets.mjs +46 -0
  57. package/library/actions/mobile/perps/set_market_favorite.mjs +117 -0
  58. package/library/actions/mobile/platform/native-session-name.mjs +14 -0
  59. package/library/actions/mobile/platform/native-session.mjs +59 -0
  60. package/library/actions/mobile/platform/observe-ui.mjs +9 -1
  61. package/library/actions/mobile/swap_bridge/native-session.mjs +10 -45
  62. package/library/actions/mobile/swap_bridge/select_assets.mjs +15 -1
  63. package/library/actions/mobile/swap_bridge/set_amount.mjs +1 -1
  64. package/library/actions/mobile/swap_bridge/set_max_amount.mjs +55 -0
  65. package/library/actions/mobile/swap_bridge/set_slippage.mjs +96 -0
  66. package/library/actions/mobile/swap_bridge/submit_transaction.mjs +141 -0
  67. package/library/actions/mobile/ui/native-navigation.mjs +120 -23
  68. package/library/actions/mobile/ui/navigate.mjs +13 -2
  69. package/library/actions/mobile/wallet/import.mjs +17 -10
  70. package/library/actions/mobile/wallet/lock.mjs +14 -0
  71. package/library/actions/mobile/wallet/native-ui.mjs +88 -15
  72. package/library/actions/shared/perps/visible-state.mjs +33 -11
  73. package/library/actions/shared/swap-bridge/visible-state.mjs +15 -0
  74. package/library/manifests/extension.action-manifest.json +1707 -1241
  75. package/library/manifests/mobile.action-manifest.json +308 -1
  76. package/library/recipes/assets/release-token-details.recipe.json +5 -4
  77. package/library/recipes/assets/release-token-hide-readd.recipe.json +2 -0
  78. package/library/recipes/{assets → extension/assets}/release-custom-network-token-persistence.recipe.json +1 -0
  79. package/library/recipes/{perps → extension/perps}/release-activity-filters.recipe.json +5 -5
  80. package/library/recipes/{perps → extension/perps}/release-funds-flows.recipe.json +3 -3
  81. package/library/recipes/extension/perps/release-live-limit-order.recipe.json +24 -19
  82. package/library/recipes/extension/perps/release-market-filters.recipe.json +97 -0
  83. package/library/recipes/extension/perps/release-order-entry.recipe.json +4 -1
  84. package/library/recipes/extension/perps/release-order-validation.recipe.json +53 -14
  85. package/library/recipes/extension/perps/release-visible-consistency.recipe.json +47 -0
  86. package/library/recipes/extension/perps/source-dev-snapshot-consistency.recipe.json +76 -0
  87. package/library/recipes/mobile/networks/release-custom-network-persistence.recipe.json +90 -0
  88. package/library/recipes/mobile/networks/release-multichain-visibility.recipe.json +58 -0
  89. package/library/recipes/perps/release-live-market-order.recipe.json +30 -13
  90. package/library/recipes/perps/release-market-details.recipe.json +1 -1
  91. package/library/recipes/perps/release-market-search.recipe.json +8 -4
  92. package/library/recipes/perps/release-watchlist.recipe.json +31 -19
  93. package/library/recipes/swap-bridge/release-custom-slippage.recipe.json +5 -13
  94. package/library/recipes/swap-bridge/release-quote.recipe.json +1 -0
  95. package/library/recipes/wallet/import.recipe.json +4 -14
  96. package/package.json +1 -1
  97. package/library/actions/extension/assets/finish_send.mjs +0 -128
  98. package/library/actions/extension/swap_bridge/submit_transaction.mjs +0 -363
  99. package/library/actions/extension/ui/activate_and_observe.mjs +0 -96
  100. package/library/recipes/assets/release-custom-gas-send.recipe.json +0 -88
  101. package/library/recipes/assets/release-native-max-cancel.recipe.json +0 -70
  102. package/library/recipes/assets/release-native-max-send.recipe.json +0 -78
  103. package/library/recipes/assets/release-own-account-send.recipe.json +0 -80
  104. package/library/recipes/extension/runner/action-validation.recipe.json +0 -343
@@ -407,6 +407,14 @@
407
407
  "symbol": {
408
408
  "type": "string"
409
409
  },
410
+ "mode": {
411
+ "type": "string",
412
+ "enum": [
413
+ "lite",
414
+ "pro"
415
+ ],
416
+ "default": "lite"
417
+ },
410
418
  "url": {
411
419
  "type": "string"
412
420
  },
@@ -1400,6 +1408,22 @@
1400
1408
  ],
1401
1409
  "execution_capabilities": ["app-mutation"]
1402
1410
  },
1411
+ "metamask.wallet.lock": {
1412
+ "description": "Lock the Mobile wallet through the visible menu and confirm the login screen.",
1413
+ "schema": {
1414
+ "type": "object",
1415
+ "properties": {
1416
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1417
+ },
1418
+ "additionalProperties": false
1419
+ },
1420
+ "examples": [{
1421
+ "action": "metamask.wallet.lock",
1422
+ "intent": "Lock the wallet through visible native controls",
1423
+ "next": "done"
1424
+ }],
1425
+ "execution_capabilities": ["app-mutation"]
1426
+ },
1403
1427
  "metamask.wallet.select_account": {
1404
1428
  "description": "mobile action to select a wallet account by address, id, or display name.",
1405
1429
  "schema": {
@@ -1535,6 +1559,184 @@
1535
1559
  ],
1536
1560
  "execution_capabilities": ["host-read-export"]
1537
1561
  },
1562
+ "metamask.assets.open_details": {
1563
+ "description": "Open one visible Mobile asset by symbol through native accessibility.",
1564
+ "schema": {
1565
+ "type": "object",
1566
+ "properties": {
1567
+ "symbol": { "type": "string" },
1568
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1569
+ },
1570
+ "required": ["symbol"],
1571
+ "additionalProperties": false
1572
+ },
1573
+ "examples": [{
1574
+ "action": "metamask.assets.open_details",
1575
+ "symbol": "ETH",
1576
+ "intent": "Open the funded ETH details",
1577
+ "next": "done"
1578
+ }],
1579
+ "execution_capabilities": ["app-mutation"]
1580
+ },
1581
+ "metamask.assets.read_details": {
1582
+ "description": "Read and assert the visible Mobile token details surface through native accessibility.",
1583
+ "schema": {
1584
+ "type": "object",
1585
+ "properties": {
1586
+ "expected_symbol": { "type": "string" },
1587
+ "require_chart": { "type": "boolean", "default": false },
1588
+ "require_market_cap": { "type": "boolean", "default": false },
1589
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1590
+ },
1591
+ "additionalProperties": false
1592
+ },
1593
+ "examples": [{
1594
+ "action": "metamask.assets.read_details",
1595
+ "expected_symbol": "ETH",
1596
+ "require_chart": true,
1597
+ "require_market_cap": true,
1598
+ "intent": "Prove current asset market data",
1599
+ "next": "done"
1600
+ }],
1601
+ "execution_capabilities": ["host-read-export"]
1602
+ },
1603
+ "metamask.assets.verify_sorting": {
1604
+ "description": "Select alphabetical and declining-fiat token sorting and assert the visible native row order.",
1605
+ "schema": {
1606
+ "type": "object",
1607
+ "properties": {
1608
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1609
+ },
1610
+ "additionalProperties": false
1611
+ },
1612
+ "examples": [{
1613
+ "action": "metamask.assets.verify_sorting",
1614
+ "intent": "Verify both token-list sort modes",
1615
+ "next": "done"
1616
+ }],
1617
+ "execution_capabilities": ["app-mutation"]
1618
+ },
1619
+ "metamask.assets.set_token_visibility": {
1620
+ "description": "Import or remove one Mobile token through visible native controls and verify the resulting state.",
1621
+ "schema": {
1622
+ "type": "object",
1623
+ "properties": {
1624
+ "query": { "type": "string" },
1625
+ "visible": { "type": "boolean" },
1626
+ "require_unchanged": { "type": "boolean", "default": false },
1627
+ "require_change": { "type": "boolean", "default": false },
1628
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 45000 }
1629
+ },
1630
+ "required": ["query", "visible"],
1631
+ "additionalProperties": false
1632
+ },
1633
+ "examples": [{
1634
+ "action": "metamask.assets.set_token_visibility",
1635
+ "query": "DAI",
1636
+ "visible": true,
1637
+ "intent": "Import DAI through visible token search",
1638
+ "next": "done"
1639
+ }],
1640
+ "execution_capabilities": ["app-mutation"]
1641
+ },
1642
+ "metamask.assets.import_custom_token": {
1643
+ "description": "Import one ERC-20 on a selected Mobile network through the visible custom-token form and verify its row.",
1644
+ "schema": {
1645
+ "type": "object",
1646
+ "properties": {
1647
+ "network": { "type": "string" },
1648
+ "chain_id": { "type": "integer", "minimum": 1 },
1649
+ "address": { "type": "string" },
1650
+ "expected_symbol": { "type": "string" },
1651
+ "decimals": { "type": "integer", "minimum": 0 },
1652
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
1653
+ },
1654
+ "required": ["network", "chain_id", "address", "expected_symbol"],
1655
+ "additionalProperties": false
1656
+ },
1657
+ "examples": [{
1658
+ "action": "metamask.assets.import_custom_token",
1659
+ "network": "Arbitrum",
1660
+ "chain_id": 42161,
1661
+ "address": "0xDA10009cbd5D07dd0CeCc66161FC93D7c9000da1",
1662
+ "expected_symbol": "DAI",
1663
+ "decimals": 18,
1664
+ "intent": "Import Arbitrum DAI by contract address",
1665
+ "next": "done"
1666
+ }],
1667
+ "execution_capabilities": ["app-mutation"]
1668
+ },
1669
+ "metamask.networks.read_visible_state": {
1670
+ "description": "Read one Mobile network from visible network settings and prove it persists across a bounded settle window.",
1671
+ "schema": {
1672
+ "type": "object",
1673
+ "properties": {
1674
+ "network": { "type": "string" },
1675
+ "chain_id": { "type": "integer", "minimum": 1 },
1676
+ "settle_ms": { "type": "integer", "minimum": 0, "default": 0 },
1677
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1678
+ },
1679
+ "required": ["network", "chain_id"],
1680
+ "additionalProperties": false
1681
+ },
1682
+ "examples": [{
1683
+ "action": "metamask.networks.read_visible_state",
1684
+ "network": "PulseChain",
1685
+ "chain_id": 369,
1686
+ "settle_ms": 1000,
1687
+ "intent": "Prove PulseChain remains in Mobile network settings",
1688
+ "next": "done"
1689
+ }],
1690
+ "execution_capabilities": ["host-read-export"]
1691
+ },
1692
+ "metamask.networks.add_custom": {
1693
+ "description": "Add or locate one custom Mobile network through visible native network settings.",
1694
+ "schema": {
1695
+ "type": "object",
1696
+ "properties": {
1697
+ "network": { "type": "string" },
1698
+ "rpc_url": { "type": "string" },
1699
+ "chain_id": { "type": "integer", "minimum": 1 },
1700
+ "symbol": { "type": "string" },
1701
+ "explorer_url": { "type": "string" },
1702
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
1703
+ },
1704
+ "required": ["network", "rpc_url", "chain_id", "symbol"],
1705
+ "additionalProperties": false
1706
+ },
1707
+ "examples": [{
1708
+ "action": "metamask.networks.add_custom",
1709
+ "network": "PulseChain",
1710
+ "rpc_url": "https://rpc.pulsechain.com",
1711
+ "chain_id": 369,
1712
+ "symbol": "PLS",
1713
+ "explorer_url": "https://scan.pulsechain.com",
1714
+ "intent": "Add PulseChain through Mobile network settings",
1715
+ "next": "done"
1716
+ }],
1717
+ "execution_capabilities": ["app-mutation"]
1718
+ },
1719
+ "metamask.networks.remove_custom": {
1720
+ "description": "Remove one custom Mobile network through visible native network settings.",
1721
+ "schema": {
1722
+ "type": "object",
1723
+ "properties": {
1724
+ "network": { "type": "string" },
1725
+ "chain_id": { "type": "integer", "minimum": 1 },
1726
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1727
+ },
1728
+ "required": ["network", "chain_id"],
1729
+ "additionalProperties": false
1730
+ },
1731
+ "examples": [{
1732
+ "action": "metamask.networks.remove_custom",
1733
+ "network": "PulseChain",
1734
+ "chain_id": 369,
1735
+ "intent": "Remove PulseChain through Mobile network settings",
1736
+ "next": "done"
1737
+ }],
1738
+ "execution_capabilities": ["app-mutation"]
1739
+ },
1538
1740
  "metamask.swap_bridge.read_visible_state": {
1539
1741
  "description": "Read and assert the visible Swap surface from an opaque Mobile runtime through native accessibility.",
1540
1742
  "schema": {
@@ -1543,7 +1745,9 @@
1543
1745
  "source_symbol": { "type": "string" },
1544
1746
  "destination_symbol": { "type": "string" },
1545
1747
  "require_amount_inputs": { "type": "boolean", "default": true },
1546
- "require_settings": { "type": "boolean", "default": false }
1748
+ "require_settings": { "type": "boolean", "default": false },
1749
+ "require_quote": { "type": "boolean", "default": false },
1750
+ "expected_slippage": { "type": "number", "minimum": 0 }
1547
1751
  },
1548
1752
  "additionalProperties": false
1549
1753
  },
@@ -1558,6 +1762,68 @@
1558
1762
  ],
1559
1763
  "execution_capabilities": ["host-read-export"]
1560
1764
  },
1765
+ "metamask.swap_bridge.set_slippage": {
1766
+ "description": "Set a custom Swap slippage percentage through native accessibility.",
1767
+ "schema": {
1768
+ "type": "object",
1769
+ "properties": {
1770
+ "percent": { "type": "number", "minimum": 0.01 },
1771
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1772
+ },
1773
+ "required": ["percent"],
1774
+ "additionalProperties": false
1775
+ },
1776
+ "examples": [{
1777
+ "action": "metamask.swap_bridge.set_slippage",
1778
+ "percent": 3,
1779
+ "intent": "Set the release checklist custom slippage value",
1780
+ "next": "done"
1781
+ }],
1782
+ "execution_capabilities": ["app-mutation"]
1783
+ },
1784
+ "metamask.swap_bridge.submit_transaction": {
1785
+ "description": "Submit an explicitly authorized live Mobile Swap and prove its terminal post-trade status and visible Activity entry.",
1786
+ "schema": {
1787
+ "type": "object",
1788
+ "properties": {
1789
+ "source_symbol": { "type": "string" },
1790
+ "destination_symbol": { "type": "string" },
1791
+ "amount": { "type": ["string", "number"] },
1792
+ "confirm_live": { "type": "boolean", "default": false },
1793
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 300000 }
1794
+ },
1795
+ "required": ["source_symbol", "destination_symbol", "amount"],
1796
+ "additionalProperties": false
1797
+ },
1798
+ "examples": [{
1799
+ "action": "metamask.swap_bridge.submit_transaction",
1800
+ "source_symbol": "ETH",
1801
+ "destination_symbol": "DAI",
1802
+ "amount": "0.00005",
1803
+ "confirm_live": true,
1804
+ "intent": "Submit the authorized release-check Swap and prove its Activity entry",
1805
+ "next": "done"
1806
+ }],
1807
+ "execution_capabilities": ["app-mutation", "external-mutation"]
1808
+ },
1809
+ "metamask.swap_bridge.set_max_amount": {
1810
+ "description": "Use the visible Swap Max control and wait for the derived live quote through native accessibility.",
1811
+ "schema": {
1812
+ "type": "object",
1813
+ "properties": {
1814
+ "wait_for_quote": { "type": "boolean", "default": true },
1815
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
1816
+ },
1817
+ "additionalProperties": false
1818
+ },
1819
+ "examples": [{
1820
+ "action": "metamask.swap_bridge.set_max_amount",
1821
+ "wait_for_quote": true,
1822
+ "intent": "Use the available token balance for the return Swap",
1823
+ "next": "done"
1824
+ }],
1825
+ "execution_capabilities": ["app-mutation"]
1826
+ },
1561
1827
  "metamask.swap_bridge.select_assets": {
1562
1828
  "description": "Select exact Swap source and destination assets through native accessibility.",
1563
1829
  "schema": {
@@ -1698,6 +1964,47 @@
1698
1964
  ],
1699
1965
  "execution_capabilities": ["host-read-export"]
1700
1966
  },
1967
+ "metamask.perps.search_markets": {
1968
+ "description": "Enter a Perps market query through native accessibility and prove visible results are returned.",
1969
+ "schema": {
1970
+ "type": "object",
1971
+ "properties": {
1972
+ "query": { "type": "string" },
1973
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1974
+ },
1975
+ "required": ["query"],
1976
+ "additionalProperties": false
1977
+ },
1978
+ "examples": [{
1979
+ "action": "metamask.perps.search_markets",
1980
+ "query": "Bitcoin",
1981
+ "intent": "Filter the visible Perps market list",
1982
+ "next": "done"
1983
+ }],
1984
+ "execution_capabilities": ["app-mutation"]
1985
+ },
1986
+ "metamask.perps.set_market_favorite": {
1987
+ "description": "Converge one visible Perps market watchlist state through native accessibility.",
1988
+ "schema": {
1989
+ "type": "object",
1990
+ "properties": {
1991
+ "market": { "type": "string" },
1992
+ "favorite": { "type": "boolean" },
1993
+ "require_unchanged": { "type": "boolean", "default": false },
1994
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 30000 }
1995
+ },
1996
+ "required": ["market", "favorite"],
1997
+ "additionalProperties": false
1998
+ },
1999
+ "examples": [{
2000
+ "action": "metamask.perps.set_market_favorite",
2001
+ "market": "BTC",
2002
+ "favorite": true,
2003
+ "intent": "Ensure BTC appears in the Perps watchlist",
2004
+ "next": "done"
2005
+ }],
2006
+ "execution_capabilities": ["app-mutation"]
2007
+ },
1701
2008
  "metamask.perps.read_positions": {
1702
2009
  "description": "mobile Read live Perps positions; without a selector, return all live positions.",
1703
2010
  "schema": {
@@ -21,10 +21,10 @@
21
21
  "next": "open-first-asset"
22
22
  },
23
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",
24
+ "action": "metamask.assets.open_details",
25
+ "symbol": "{{params.symbol}}",
26
+ "timeout_ms": "{{params.timeout_ms}}",
27
+ "intent": "Open the requested visible funded asset",
28
28
  "next": "assert-details"
29
29
  },
30
30
  "assert-details": {
@@ -32,6 +32,7 @@
32
32
  "expected_symbol": "{{params.symbol}}",
33
33
  "require_chart": true,
34
34
  "require_market_cap": true,
35
+ "timeout_ms": "{{params.timeout_ms}}",
35
36
  "intent": "Prove live asset price history and market data render without malformed values",
36
37
  "next": "capture-details"
37
38
  },
@@ -23,6 +23,7 @@
23
23
  "action": "metamask.assets.set_token_visibility",
24
24
  "query": "{{params.query}}",
25
25
  "visible": false,
26
+ "require_change": true,
26
27
  "timeout_ms": "{{params.timeout_ms}}",
27
28
  "intent": "Disable the imported token and prove its row disappears",
28
29
  "next": "capture-hidden"
@@ -38,6 +39,7 @@
38
39
  "action": "metamask.assets.set_token_visibility",
39
40
  "query": "{{params.query}}",
40
41
  "visible": true,
42
+ "require_change": true,
41
43
  "timeout_ms": "{{params.timeout_ms}}",
42
44
  "intent": "Re-enable the token and prove its metadata row returns",
43
45
  "next": "capture-restored"
@@ -33,6 +33,7 @@
33
33
  "chain_id": "{{params.chain_id}}",
34
34
  "symbol": "{{params.native_symbol}}",
35
35
  "explorer_url": "{{params.explorer_url}}",
36
+ "require_absent": true,
36
37
  "timeout_ms": "{{params.timeout_ms}}",
37
38
  "intent": "Add and select the custom network through visible settings",
38
39
  "next": "import-token"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Perps release activity filters",
4
- "description": "Opens live Perps activity and exercises the Trades, Orders, Funding, and Deposits filters through semantic visible controls.",
4
+ "description": "Selects the Trades, Orders, Funding, and Deposits controls and proves each selected label and route; populated or typed activity rows are not required.",
5
5
  "workflow": {
6
6
  "entry": "open-activity",
7
7
  "nodes": {
@@ -14,25 +14,25 @@
14
14
  "trades": {
15
15
  "action": "metamask.perps.select_activity_filter",
16
16
  "filter": "trades",
17
- "intent": "Show only trade-related Perps activity",
17
+ "intent": "Prove the Trades filter label and route",
18
18
  "next": "orders"
19
19
  },
20
20
  "orders": {
21
21
  "action": "metamask.perps.select_activity_filter",
22
22
  "filter": "orders",
23
- "intent": "Show only order-related Perps activity",
23
+ "intent": "Prove the Orders filter label and route",
24
24
  "next": "funding"
25
25
  },
26
26
  "funding": {
27
27
  "action": "metamask.perps.select_activity_filter",
28
28
  "filter": "funding",
29
- "intent": "Show only Perps funding activity",
29
+ "intent": "Prove the Funding filter label and route",
30
30
  "next": "deposits"
31
31
  },
32
32
  "deposits": {
33
33
  "action": "metamask.perps.select_activity_filter",
34
34
  "filter": "deposits",
35
- "intent": "Show only Perps deposit and withdrawal activity",
35
+ "intent": "Prove the Deposits filter label and route",
36
36
  "next": "capture"
37
37
  },
38
38
  "capture": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
3
  "title": "Perps release funds flows",
4
- "description": "Opens the live Perps deposit and withdraw confirmations, proves their loaded amount contexts, and dismisses each without submitting funds.",
4
+ "description": "Opens the live Perps deposit and withdraw forms, records the currently rendered preview fields, proves zero withdrawal is disabled, and dismisses both without submission.",
5
5
  "workflow": {
6
6
  "entry": "open-perps-deposit",
7
7
  "nodes": {
@@ -20,7 +20,7 @@
20
20
  "read-deposit": {
21
21
  "action": "metamask.perps.read_funds_confirmation",
22
22
  "mode": "deposit",
23
- "intent": "Prove the deposit amount, token, fee, and time context loaded",
23
+ "intent": "Prove the deposit form loaded and record any rendered preview fields",
24
24
  "next": "dismiss-deposit"
25
25
  },
26
26
  "dismiss-deposit": {
@@ -44,7 +44,7 @@
44
44
  "read-withdraw": {
45
45
  "action": "metamask.perps.read_funds_confirmation",
46
46
  "mode": "withdraw",
47
- "intent": "Prove available balance, receive token, fee, time, and final amount loaded",
47
+ "intent": "Prove the withdraw form loaded and record any rendered preview fields",
48
48
  "next": "enter-zero"
49
49
  },
50
50
  "enter-zero": {
@@ -5,7 +5,7 @@
5
5
  "paramsSchema": {
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
- "required": ["confirm_live"],
8
+ "required": ["confirm_live", "limit_price", "provider", "network"],
9
9
  "properties": {
10
10
  "market": {
11
11
  "type": "string",
@@ -19,15 +19,16 @@
19
19
  "leverage": {
20
20
  "type": "integer",
21
21
  "minimum": 1,
22
- "default": 3
23
- },
24
- "offset_pct": {
25
- "type": "number",
26
- "default": -2
22
+ "default": 1
27
23
  },
24
+ "provider": { "type": "string" },
25
+ "network": { "type": "string", "enum": ["mainnet", "testnet"] },
26
+ "limit_price": { "type": "string" },
27
+ "offset_pct": { "type": "number" },
28
28
  "confirm_live": {
29
29
  "type": "boolean"
30
- }
30
+ },
31
+ "identity_rounding_tolerance_base_units": { "type": "string", "default": "10000" }
31
32
  }
32
33
  },
33
34
  "workflow": {
@@ -38,14 +39,6 @@
38
39
  "page": "perps-market",
39
40
  "market": "{{params.market}}",
40
41
  "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
42
  "next": "place-limit"
50
43
  },
51
44
  "place-limit": {
@@ -54,9 +47,13 @@
54
47
  "side": "long",
55
48
  "amount": "{{params.amount}}",
56
49
  "leverage": "{{params.leverage}}",
50
+ "provider": "{{params.provider}}",
51
+ "network": "{{params.network}}",
57
52
  "order_type": "limit",
58
- "offset_pct": "{{params.offset_pct}}",
53
+ "limit_price": "{{params.limit_price}}",
59
54
  "confirm_live": "{{params.confirm_live}}",
55
+ "identity_rounding_tolerance_base_units": "{{params.identity_rounding_tolerance_base_units}}",
56
+ "submit_attempts": 1,
60
57
  "timeout_ms": 45000,
61
58
  "intent": "Submit one authorized resting limit order through visible controls",
62
59
  "next": "assert-open"
@@ -82,6 +79,13 @@
82
79
  "cancel-order": {
83
80
  "action": "metamask.perps.close_orders",
84
81
  "market": "{{params.market}}",
82
+ "side": "long",
83
+ "amount": "{{params.amount}}",
84
+ "leverage": "{{params.leverage}}",
85
+ "provider": "{{params.provider}}",
86
+ "network": "{{params.network}}",
87
+ "limit_price": "{{params.limit_price}}",
88
+ "identity_rounding_tolerance_base_units": "{{params.identity_rounding_tolerance_base_units}}",
85
89
  "confirm_live": "{{params.confirm_live}}",
86
90
  "timeout_ms": 30000,
87
91
  "intent": "Cancel the authorized live limit order through visible controls",
@@ -89,10 +93,11 @@
89
93
  },
90
94
  "assert-canceled": {
91
95
  "action": "metamask.perps.read_visible_state",
92
- "surface": "market-details",
93
- "market": "{{params.market}}",
96
+ "surface": "home",
97
+ "maximum_position_count": 0,
94
98
  "maximum_order_count": 0,
95
- "intent": "Prove the order card disappears after cancellation",
99
+ "require_features": ["balance", "market-list"],
100
+ "intent": "Prove global positions and orders remain empty after cancellation",
96
101
  "next": "done"
97
102
  },
98
103
  "done": {
@@ -0,0 +1,97 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Perps release market filters",
4
+ "description": "Exercises every stable live Perps market category through visible controls after resetting the market-list surface.",
5
+ "workflow": {
6
+ "entry": "open-perps",
7
+ "nodes": {
8
+ "open-perps": {
9
+ "action": "ui.navigate",
10
+ "page": "perps",
11
+ "intent": "Reset transient market-list state on the Perps home surface",
12
+ "next": "open-market-list"
13
+ },
14
+ "open-market-list": {
15
+ "action": "ui.navigate",
16
+ "page": "perps-market-list",
17
+ "intent": "Open the complete live Perps market selection",
18
+ "next": "wait-market-filter"
19
+ },
20
+ "wait-market-filter": {
21
+ "action": "ui.wait_for",
22
+ "test_id": "filter-select-button",
23
+ "expected": "visible",
24
+ "timeout_ms": 30000,
25
+ "intent": "Confirm the market filter control is ready",
26
+ "next": "all"
27
+ },
28
+ "all": {
29
+ "action": "metamask.perps.select_market_filter",
30
+ "filter": "all",
31
+ "minimum_market_count": 1,
32
+ "intent": "Prove the complete live market category",
33
+ "next": "crypto"
34
+ },
35
+ "crypto": {
36
+ "action": "metamask.perps.select_market_filter",
37
+ "filter": "crypto",
38
+ "minimum_market_count": 0,
39
+ "intent": "Prove the Crypto market category",
40
+ "next": "stocks"
41
+ },
42
+ "stocks": {
43
+ "action": "metamask.perps.select_market_filter",
44
+ "filter": "stocks",
45
+ "minimum_market_count": 0,
46
+ "intent": "Prove the Stocks market category",
47
+ "next": "pre-ipo"
48
+ },
49
+ "pre-ipo": {
50
+ "action": "metamask.perps.select_market_filter",
51
+ "filter": "pre-ipo",
52
+ "minimum_market_count": 0,
53
+ "intent": "Prove the Pre-IPO market category control",
54
+ "next": "index"
55
+ },
56
+ "index": {
57
+ "action": "metamask.perps.select_market_filter",
58
+ "filter": "index",
59
+ "minimum_market_count": 0,
60
+ "intent": "Prove the Index market category control",
61
+ "next": "etf"
62
+ },
63
+ "etf": {
64
+ "action": "metamask.perps.select_market_filter",
65
+ "filter": "etf",
66
+ "minimum_market_count": 0,
67
+ "intent": "Prove the ETF market category control",
68
+ "next": "commodities"
69
+ },
70
+ "commodities": {
71
+ "action": "metamask.perps.select_market_filter",
72
+ "filter": "commodities",
73
+ "minimum_market_count": 0,
74
+ "intent": "Prove the Commodities market category",
75
+ "next": "forex"
76
+ },
77
+ "forex": {
78
+ "action": "metamask.perps.select_market_filter",
79
+ "filter": "forex",
80
+ "minimum_market_count": 0,
81
+ "intent": "Prove the Forex market category",
82
+ "next": "capture"
83
+ },
84
+ "capture": {
85
+ "action": "ui.screenshot",
86
+ "path": "screenshots/perps-market-filters.png",
87
+ "label": "Perps release market filters",
88
+ "intent": "Preserve reviewer-visible proof of the final market filter",
89
+ "next": "done"
90
+ },
91
+ "done": {
92
+ "action": "end",
93
+ "status": "pass"
94
+ }
95
+ }
96
+ }
97
+ }