@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
@@ -399,7 +399,7 @@
399
399
  "properties": {
400
400
  "page": {
401
401
  "type": "string",
402
- "enum": ["home", "perps", "perps-market"]
402
+ "enum": ["home", "perps", "perps-market-list", "perps-market", "swap"]
403
403
  },
404
404
  "market": {
405
405
  "type": "string"
@@ -1316,6 +1316,22 @@
1316
1316
  "default": false,
1317
1317
  "description": "Enable MetaMetrics during visible onboarding."
1318
1318
  },
1319
+ "biometrics": {
1320
+ "type": "boolean",
1321
+ "enum": [false],
1322
+ "default": false,
1323
+ "description": "Biometric authentication is disabled because unattended recipes cannot satisfy the device prompt."
1324
+ },
1325
+ "notifications": {
1326
+ "type": "boolean",
1327
+ "default": false,
1328
+ "description": "Enable push notifications during Mobile onboarding; defaults off."
1329
+ },
1330
+ "skip_wallet_tour": {
1331
+ "type": "boolean",
1332
+ "default": true,
1333
+ "description": "Skip the Mobile wallet-home tour after onboarding; defaults on so recipes reach a usable wallet."
1334
+ },
1319
1335
  "interests": {
1320
1336
  "type": "array",
1321
1337
  "items": {
@@ -1464,6 +1480,224 @@
1464
1480
  ],
1465
1481
  "execution_capabilities": []
1466
1482
  },
1483
+ "metamask.assets.read_visible_state": {
1484
+ "description": "Read and assert bounded visible wallet assets from an opaque Mobile runtime through native accessibility.",
1485
+ "schema": {
1486
+ "type": "object",
1487
+ "properties": {
1488
+ "minimum_asset_count": {
1489
+ "type": "integer",
1490
+ "minimum": 0,
1491
+ "default": 0
1492
+ },
1493
+ "minimum_price_change_count": {
1494
+ "type": "integer",
1495
+ "minimum": 0,
1496
+ "default": 0
1497
+ },
1498
+ "minimum_without_price_change_count": {
1499
+ "type": "integer",
1500
+ "minimum": 0,
1501
+ "default": 0
1502
+ },
1503
+ "require_symbols": {
1504
+ "type": "array",
1505
+ "items": { "type": "string" },
1506
+ "maxItems": 50
1507
+ },
1508
+ "require_fiat": {
1509
+ "type": "boolean",
1510
+ "default": false
1511
+ },
1512
+ "require_price_change_styling": {
1513
+ "type": "boolean",
1514
+ "default": false
1515
+ },
1516
+ "max_items": {
1517
+ "type": "integer",
1518
+ "minimum": 1,
1519
+ "default": 100
1520
+ }
1521
+ },
1522
+ "additionalProperties": false
1523
+ },
1524
+ "examples": [
1525
+ {
1526
+ "action": "metamask.assets.read_visible_state",
1527
+ "minimum_asset_count": 2,
1528
+ "require_symbols": ["USDC", "BNB"],
1529
+ "require_fiat": true,
1530
+ "minimum_price_change_count": 1,
1531
+ "minimum_without_price_change_count": 1,
1532
+ "intent": "Assert live wallet assets through native accessibility",
1533
+ "next": "done"
1534
+ }
1535
+ ],
1536
+ "execution_capabilities": ["host-read-export"]
1537
+ },
1538
+ "metamask.swap_bridge.read_visible_state": {
1539
+ "description": "Read and assert the visible Swap surface from an opaque Mobile runtime through native accessibility.",
1540
+ "schema": {
1541
+ "type": "object",
1542
+ "properties": {
1543
+ "source_symbol": { "type": "string" },
1544
+ "destination_symbol": { "type": "string" },
1545
+ "require_amount_inputs": { "type": "boolean", "default": true },
1546
+ "require_settings": { "type": "boolean", "default": false }
1547
+ },
1548
+ "additionalProperties": false
1549
+ },
1550
+ "examples": [
1551
+ {
1552
+ "action": "metamask.swap_bridge.read_visible_state",
1553
+ "require_amount_inputs": true,
1554
+ "require_settings": true,
1555
+ "intent": "Assert the visible Swap surface",
1556
+ "next": "done"
1557
+ }
1558
+ ],
1559
+ "execution_capabilities": ["host-read-export"]
1560
+ },
1561
+ "metamask.swap_bridge.select_assets": {
1562
+ "description": "Select exact Swap source and destination assets through native accessibility.",
1563
+ "schema": {
1564
+ "type": "object",
1565
+ "properties": {
1566
+ "source_symbol": { "type": "string" },
1567
+ "destination_symbol": { "type": "string" },
1568
+ "source_chain": { "type": "string" },
1569
+ "destination_chain": { "type": "string" },
1570
+ "source_query": { "type": "string" },
1571
+ "destination_query": { "type": "string" },
1572
+ "source_asset_id": { "type": "string" },
1573
+ "destination_asset_id": { "type": "string" },
1574
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
1575
+ },
1576
+ "required": ["source_symbol", "destination_symbol", "source_chain", "destination_chain"],
1577
+ "additionalProperties": false
1578
+ },
1579
+ "examples": [{
1580
+ "action": "metamask.swap_bridge.select_assets",
1581
+ "source_symbol": "ETH",
1582
+ "destination_symbol": "WETH",
1583
+ "source_chain": "eip155:1",
1584
+ "destination_chain": "eip155:1",
1585
+ "intent": "Select the funded Swap pair",
1586
+ "next": "done"
1587
+ }],
1588
+ "execution_capabilities": ["app-mutation"]
1589
+ },
1590
+ "metamask.swap_bridge.set_amount": {
1591
+ "description": "Enter a positive Swap amount through native accessibility and wait for a quote or explicit no-route state.",
1592
+ "schema": {
1593
+ "type": "object",
1594
+ "properties": {
1595
+ "amount": { "type": "number", "minimum": 0.00000001 },
1596
+ "wait_for_quote": { "type": "boolean", "default": true },
1597
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
1598
+ },
1599
+ "required": ["amount"],
1600
+ "additionalProperties": false
1601
+ },
1602
+ "examples": [{
1603
+ "action": "metamask.swap_bridge.set_amount",
1604
+ "amount": 0.0001,
1605
+ "intent": "Enter a capped Swap amount and wait for the quote",
1606
+ "next": "done"
1607
+ }],
1608
+ "execution_capabilities": ["app-mutation"]
1609
+ },
1610
+ "metamask.perps.read_visible_state": {
1611
+ "description": "Read and assert bounded visible Perps UI state from an opaque Mobile runtime through native accessibility.",
1612
+ "schema": {
1613
+ "type": "object",
1614
+ "properties": {
1615
+ "surface": {
1616
+ "type": "string",
1617
+ "enum": ["auto", "home", "market-list", "market-details", "order-entry", "activity", "funds"],
1618
+ "default": "auto"
1619
+ },
1620
+ "market": {
1621
+ "type": "string",
1622
+ "description": "Optional market that must be present in the visible state."
1623
+ },
1624
+ "minimum_market_count": {
1625
+ "type": "integer",
1626
+ "minimum": 0,
1627
+ "default": 0
1628
+ },
1629
+ "maximum_market_count": {
1630
+ "type": "integer",
1631
+ "minimum": 0,
1632
+ "default": 200
1633
+ },
1634
+ "minimum_position_count": {
1635
+ "type": "integer",
1636
+ "minimum": 0,
1637
+ "default": 0
1638
+ },
1639
+ "maximum_position_count": {
1640
+ "type": "integer",
1641
+ "minimum": 0,
1642
+ "default": 200
1643
+ },
1644
+ "minimum_order_count": {
1645
+ "type": "integer",
1646
+ "minimum": 0,
1647
+ "default": 0
1648
+ },
1649
+ "maximum_order_count": {
1650
+ "type": "integer",
1651
+ "minimum": 0,
1652
+ "default": 200
1653
+ },
1654
+ "minimum_activity_count": {
1655
+ "type": "integer",
1656
+ "minimum": 0,
1657
+ "default": 0
1658
+ },
1659
+ "forbid_test_ids": {
1660
+ "type": "array",
1661
+ "items": { "type": "string" },
1662
+ "maxItems": 100
1663
+ },
1664
+ "require_test_ids": {
1665
+ "type": "array",
1666
+ "items": { "type": "string" },
1667
+ "maxItems": 100
1668
+ },
1669
+ "require_features": {
1670
+ "type": "array",
1671
+ "items": {
1672
+ "type": "string",
1673
+ "enum": ["activity", "balance", "chart", "long-short", "market-list", "order-entry", "price", "price-change", "stats"]
1674
+ },
1675
+ "maxItems": 9
1676
+ },
1677
+ "include_offscreen": {
1678
+ "type": "boolean",
1679
+ "default": true
1680
+ },
1681
+ "max_items": {
1682
+ "type": "integer",
1683
+ "minimum": 1,
1684
+ "default": 100
1685
+ }
1686
+ },
1687
+ "additionalProperties": false
1688
+ },
1689
+ "examples": [
1690
+ {
1691
+ "action": "metamask.perps.read_visible_state",
1692
+ "surface": "market-details",
1693
+ "market": "ETH",
1694
+ "require_features": ["price", "stats", "long-short"],
1695
+ "intent": "Assert the selected live Perps market through native accessibility",
1696
+ "next": "done"
1697
+ }
1698
+ ],
1699
+ "execution_capabilities": ["host-read-export"]
1700
+ },
1467
1701
  "metamask.perps.read_positions": {
1468
1702
  "description": "mobile Read live Perps positions; without a selector, return all live positions.",
1469
1703
  "schema": {
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release custom-gas token send",
4
+ "description": "Applies a custom gas limit to a tiny token send and proves the 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
+ "gas_limit": { "type": ["string", "number"], "default": 70000 },
16
+ "confirm_live": { "type": "boolean", "default": false },
17
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 120000 }
18
+ }
19
+ },
20
+ "workflow": {
21
+ "entry": "select-source",
22
+ "nodes": {
23
+ "select-source": {
24
+ "action": "metamask.wallet.select_account",
25
+ "address": "{{params.source_address}}",
26
+ "intent": "Select the funded source account",
27
+ "next": "select-network"
28
+ },
29
+ "select-network": {
30
+ "action": "ui.navigate",
31
+ "page": "network",
32
+ "network": "{{params.network}}",
33
+ "chain_id": "{{params.chain_id}}",
34
+ "add_if_missing": false,
35
+ "timeout_ms": "{{params.timeout_ms}}",
36
+ "intent": "Select the funded token network",
37
+ "next": "prepare-send"
38
+ },
39
+ "prepare-send": {
40
+ "action": "metamask.assets.prepare_send",
41
+ "symbol": "{{params.symbol}}",
42
+ "recipient": "{{params.recipient}}",
43
+ "amount": "{{params.amount}}",
44
+ "timeout_ms": "{{params.timeout_ms}}",
45
+ "intent": "Prepare the tiny token send",
46
+ "next": "review-send"
47
+ },
48
+ "review-send": {
49
+ "action": "metamask.assets.review_send",
50
+ "timeout_ms": "{{params.timeout_ms}}",
51
+ "intent": "Open the send confirmation",
52
+ "next": "set-custom-gas"
53
+ },
54
+ "set-custom-gas": {
55
+ "action": "metamask.assets.set_custom_gas",
56
+ "gas_limit": "{{params.gas_limit}}",
57
+ "timeout_ms": "{{params.timeout_ms}}",
58
+ "intent": "Apply and prove the requested custom gas limit",
59
+ "next": "capture-confirmation"
60
+ },
61
+ "capture-confirmation": {
62
+ "action": "ui.screenshot",
63
+ "path": "screenshots/assets-custom-gas-confirmation.png",
64
+ "label": "Custom-gas token send confirmation",
65
+ "intent": "Preserve the custom-gas review evidence",
66
+ "next": "finish-send"
67
+ },
68
+ "finish-send": {
69
+ "action": "metamask.assets.finish_send",
70
+ "decision": "confirm",
71
+ "symbol": "{{params.symbol}}",
72
+ "amount": "{{params.amount}}",
73
+ "confirm_live": "{{params.confirm_live}}",
74
+ "timeout_ms": "{{params.timeout_ms}}",
75
+ "intent": "Confirm the authorized tiny custom-gas send and prove Activity details",
76
+ "next": "capture-confirmed"
77
+ },
78
+ "capture-confirmed": {
79
+ "action": "ui.screenshot",
80
+ "path": "screenshots/assets-custom-gas-confirmed.png",
81
+ "label": "Custom-gas token send confirmed",
82
+ "intent": "Preserve the confirmed custom-gas transaction evidence",
83
+ "next": "done"
84
+ },
85
+ "done": { "action": "end", "status": "pass" }
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,106 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release custom-network token persistence",
4
+ "description": "Adds PulseChain and PLSX, proves both survive lock/unlock, then removes the custom network.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "network": { "type": "string", "default": "PulseChain" },
10
+ "rpc_url": { "type": "string", "default": "https://rpc.pulsechain.com" },
11
+ "chain_id": { "type": "integer", "minimum": 1, "default": 369 },
12
+ "native_symbol": { "type": "string", "default": "PLS" },
13
+ "explorer_url": { "type": "string", "default": "https://scan.pulsechain.com" },
14
+ "token_address": { "type": "string", "default": "0x95B303987A60C71504D99Aa1b13B4DA07b0790ab" },
15
+ "token_symbol": { "type": "string", "default": "PLSX" },
16
+ "token_decimals": { "type": "integer", "minimum": 0, "default": 18 },
17
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
18
+ }
19
+ },
20
+ "workflow": {
21
+ "entry": "open-wallet",
22
+ "nodes": {
23
+ "open-wallet": {
24
+ "action": "ui.navigate",
25
+ "page": "home",
26
+ "intent": "Open the wallet before custom-network setup",
27
+ "next": "add-network"
28
+ },
29
+ "add-network": {
30
+ "action": "metamask.networks.add_custom",
31
+ "network": "{{params.network}}",
32
+ "rpc_url": "{{params.rpc_url}}",
33
+ "chain_id": "{{params.chain_id}}",
34
+ "symbol": "{{params.native_symbol}}",
35
+ "explorer_url": "{{params.explorer_url}}",
36
+ "timeout_ms": "{{params.timeout_ms}}",
37
+ "intent": "Add and select the custom network through visible settings",
38
+ "next": "import-token"
39
+ },
40
+ "import-token": {
41
+ "action": "metamask.assets.import_custom_token",
42
+ "network": "{{params.network}}",
43
+ "chain_id": "{{params.chain_id}}",
44
+ "address": "{{params.token_address}}",
45
+ "expected_symbol": "{{params.token_symbol}}",
46
+ "decimals": "{{params.token_decimals}}",
47
+ "timeout_ms": "{{params.timeout_ms}}",
48
+ "intent": "Import the custom-network token and verify its metadata",
49
+ "next": "capture-before"
50
+ },
51
+ "capture-before": {
52
+ "action": "ui.screenshot",
53
+ "path": "screenshots/custom-network-token-before-lock.png",
54
+ "label": "Custom network token before lock",
55
+ "intent": "Preserve pre-lock PulseChain and PLSX evidence",
56
+ "next": "lock-wallet"
57
+ },
58
+ "lock-wallet": {
59
+ "action": "metamask.wallet.lock",
60
+ "intent": "Lock the wallet through visible UI",
61
+ "next": "unlock-wallet"
62
+ },
63
+ "unlock-wallet": {
64
+ "action": "metamask.wallet.ensure_unlocked",
65
+ "intent": "Unlock the same persisted profile",
66
+ "next": "select-persisted-network"
67
+ },
68
+ "select-persisted-network": {
69
+ "action": "ui.navigate",
70
+ "page": "network",
71
+ "network": "{{params.network}}",
72
+ "chain_id": "{{params.chain_id}}",
73
+ "add_if_missing": false,
74
+ "timeout_ms": "{{params.timeout_ms}}",
75
+ "intent": "Prove the custom network persisted and select it",
76
+ "next": "assert-persisted-token"
77
+ },
78
+ "assert-persisted-token": {
79
+ "action": "metamask.networks.read_visible_state",
80
+ "network": "{{params.network}}",
81
+ "chain_id": "{{params.chain_id}}",
82
+ "require_symbols": ["{{params.token_symbol}}"],
83
+ "minimum_asset_count": 1,
84
+ "settle_ms": 1000,
85
+ "intent": "Prove the custom token persisted on the custom network",
86
+ "next": "capture-after"
87
+ },
88
+ "capture-after": {
89
+ "action": "ui.screenshot",
90
+ "path": "screenshots/custom-network-token-after-unlock.png",
91
+ "label": "Custom network token after unlock",
92
+ "intent": "Preserve post-unlock PulseChain and PLSX evidence",
93
+ "next": "remove-network"
94
+ },
95
+ "remove-network": {
96
+ "action": "metamask.networks.remove_custom",
97
+ "network": "{{params.network}}",
98
+ "chain_id": "{{params.chain_id}}",
99
+ "timeout_ms": "{{params.timeout_ms}}",
100
+ "intent": "Remove the custom network and its token during cleanup",
101
+ "next": "done"
102
+ },
103
+ "done": { "action": "end", "status": "pass" }
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release native Max cancellation",
4
+ "description": "Prepares a native Max send, proves the fee-adjusted review, and cancels without broadcasting.",
5
+ "paramsSchema": {
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "source_address": { "type": "string", "default": "0x8dc623e964475d4d669da601fd15ea9125469003" },
10
+ "network": { "type": "string", "default": "Ethereum" },
11
+ "chain_id": { "type": "integer", "minimum": 1, "default": 1 },
12
+ "symbol": { "type": "string", "default": "ETH" },
13
+ "recipient": { "type": "string", "default": "0x5993d2153f080470bfe765ae81f4fa5fa2080916" },
14
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 60000 }
15
+ }
16
+ },
17
+ "workflow": {
18
+ "entry": "select-source",
19
+ "nodes": {
20
+ "select-source": {
21
+ "action": "metamask.wallet.select_account",
22
+ "address": "{{params.source_address}}",
23
+ "intent": "Select the funded source account",
24
+ "next": "select-network"
25
+ },
26
+ "select-network": {
27
+ "action": "ui.navigate",
28
+ "page": "network",
29
+ "network": "{{params.network}}",
30
+ "chain_id": "{{params.chain_id}}",
31
+ "add_if_missing": false,
32
+ "timeout_ms": "{{params.timeout_ms}}",
33
+ "intent": "Select the native asset network",
34
+ "next": "prepare-max"
35
+ },
36
+ "prepare-max": {
37
+ "action": "metamask.assets.prepare_send",
38
+ "symbol": "{{params.symbol}}",
39
+ "recipient": "{{params.recipient}}",
40
+ "max": true,
41
+ "timeout_ms": "{{params.timeout_ms}}",
42
+ "intent": "Prepare a fee-adjusted native Max send",
43
+ "next": "review-max"
44
+ },
45
+ "review-max": {
46
+ "action": "metamask.assets.review_send",
47
+ "timeout_ms": "{{params.timeout_ms}}",
48
+ "intent": "Prove the Max amount and network fee at review",
49
+ "next": "capture-max"
50
+ },
51
+ "capture-max": {
52
+ "action": "ui.screenshot",
53
+ "path": "screenshots/assets-native-max-review.png",
54
+ "label": "Native Max send review",
55
+ "intent": "Preserve the fee-adjusted Max evidence",
56
+ "next": "cancel-max"
57
+ },
58
+ "cancel-max": {
59
+ "action": "metamask.assets.finish_send",
60
+ "decision": "cancel",
61
+ "symbol": "{{params.symbol}}",
62
+ "amount": "max",
63
+ "timeout_ms": "{{params.timeout_ms}}",
64
+ "intent": "Cancel the Max send without broadcasting",
65
+ "next": "done"
66
+ },
67
+ "done": { "action": "end", "status": "pass" }
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
3
+ "title": "Assets release native Max self-send",
4
+ "description": "Submits a native Max self-send 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": "Ethereum" },
11
+ "chain_id": { "type": "integer", "minimum": 1, "default": 1 },
12
+ "symbol": { "type": "string", "default": "ETH" },
13
+ "confirm_live": { "type": "boolean", "default": false },
14
+ "timeout_ms": { "type": "integer", "minimum": 1000, "default": 120000 }
15
+ }
16
+ },
17
+ "workflow": {
18
+ "entry": "select-source",
19
+ "nodes": {
20
+ "select-source": {
21
+ "action": "metamask.wallet.select_account",
22
+ "address": "{{params.source_address}}",
23
+ "intent": "Select the funded source account",
24
+ "next": "select-network"
25
+ },
26
+ "select-network": {
27
+ "action": "ui.navigate",
28
+ "page": "network",
29
+ "network": "{{params.network}}",
30
+ "chain_id": "{{params.chain_id}}",
31
+ "add_if_missing": false,
32
+ "timeout_ms": "{{params.timeout_ms}}",
33
+ "intent": "Select the native asset network",
34
+ "next": "prepare-max"
35
+ },
36
+ "prepare-max": {
37
+ "action": "metamask.assets.prepare_send",
38
+ "symbol": "{{params.symbol}}",
39
+ "recipient": "{{params.source_address}}",
40
+ "max": true,
41
+ "timeout_ms": "{{params.timeout_ms}}",
42
+ "intent": "Prepare a native Max self-send",
43
+ "next": "review-max"
44
+ },
45
+ "review-max": {
46
+ "action": "metamask.assets.review_send",
47
+ "timeout_ms": "{{params.timeout_ms}}",
48
+ "intent": "Prove the confirmation amount and network fee",
49
+ "next": "capture-confirmation"
50
+ },
51
+ "capture-confirmation": {
52
+ "action": "ui.screenshot",
53
+ "path": "screenshots/assets-native-max-send-confirmation.png",
54
+ "label": "Native Max self-send confirmation",
55
+ "intent": "Preserve the reviewed Max evidence",
56
+ "next": "finish-send"
57
+ },
58
+ "finish-send": {
59
+ "action": "metamask.assets.finish_send",
60
+ "decision": "confirm",
61
+ "symbol": "{{params.symbol}}",
62
+ "amount": "max",
63
+ "confirm_live": "{{params.confirm_live}}",
64
+ "timeout_ms": "{{params.timeout_ms}}",
65
+ "intent": "Submit the authorized Max self-send and prove confirmed Activity details",
66
+ "next": "capture-confirmed"
67
+ },
68
+ "capture-confirmed": {
69
+ "action": "ui.screenshot",
70
+ "path": "screenshots/assets-native-max-send-confirmed.png",
71
+ "label": "Native Max self-send confirmed",
72
+ "intent": "Preserve the confirmed self-send evidence",
73
+ "next": "done"
74
+ },
75
+ "done": { "action": "end", "status": "pass" }
76
+ }
77
+ }
78
+ }