@deeeed/metamask-harness 0.48.0 → 0.49.1

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 (177) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/commands/help.js +17 -5
  3. package/dist/funding-execution-context.js +19 -4
  4. package/dist/metamask-action-validation.js +3 -2
  5. package/dist/mm-harness-cli.js +2 -1
  6. package/docs/RECIPES.md +2 -2
  7. package/library/actions/core/perps/_controller.mjs +14 -24
  8. package/library/actions/core/perps/assert_orders.mjs +3 -5
  9. package/library/actions/core/perps/assert_positions.mjs +3 -5
  10. package/library/actions/core/perps/close_orders.mjs +28 -4
  11. package/library/actions/core/perps/close_positions.mjs +53 -12
  12. package/library/actions/core/perps/edit_order.mjs +2 -0
  13. package/library/actions/core/perps/ensure_orders.mjs +3 -4
  14. package/library/actions/core/perps/ensure_positions.mjs +4 -5
  15. package/library/actions/core/perps/place_order.mjs +7 -14
  16. package/library/actions/core/perps/read_account.mjs +2 -0
  17. package/library/actions/core/perps/read_orders.mjs +2 -0
  18. package/library/actions/core/perps/read_positions.mjs +3 -1
  19. package/library/actions/core/perps/read_snapshot.mjs +3 -0
  20. package/library/actions/core/perps/start_state.mjs +3 -14
  21. package/library/actions/core/perps/teardown_state.mjs +3 -14
  22. package/library/actions/core/perps/update_position_tpsl.mjs +13 -19
  23. package/library/actions/core/wallet/list_accounts.mjs +3 -0
  24. package/library/actions/extension/analytics/consent.mjs +2 -0
  25. package/library/actions/extension/analytics/set_consent.mjs +2 -0
  26. package/library/actions/extension/assets/home-token-identity.mjs +1 -0
  27. package/library/actions/extension/assets/import_custom_token.mjs +2 -0
  28. package/library/actions/extension/assets/open_details.mjs +1 -0
  29. package/library/actions/extension/assets/prepare_send.mjs +1 -0
  30. package/library/actions/extension/assets/read_details.mjs +1 -0
  31. package/library/actions/extension/assets/read_visible_state.mjs +1 -0
  32. package/library/actions/extension/assets/review_send.mjs +1 -0
  33. package/library/actions/extension/assets/select_network_scope.mjs +1 -0
  34. package/library/actions/extension/assets/send.mjs +2 -0
  35. package/library/actions/extension/assets/set_custom_gas.mjs +1 -0
  36. package/library/actions/extension/assets/set_token_visibility.mjs +2 -0
  37. package/library/actions/extension/assets/verify_sorting.mjs +1 -0
  38. package/library/actions/extension/deeplink/open.mjs +1 -0
  39. package/library/actions/extension/networks/add_chainlist.mjs +2 -0
  40. package/library/actions/extension/networks/add_custom.mjs +2 -0
  41. package/library/actions/extension/networks/custom_network.mjs +2 -0
  42. package/library/actions/extension/networks/read_visible_state.mjs +1 -0
  43. package/library/actions/extension/networks/remove_custom.mjs +1 -0
  44. package/library/actions/extension/performance/_navigation-memory.mjs +2 -0
  45. package/library/actions/extension/performance/compare_idle_navigation_memory.mjs +2 -0
  46. package/library/actions/extension/performance/measure_detached_dom.mjs +2 -0
  47. package/library/actions/extension/performance/measure_navigation_memory.mjs +2 -0
  48. package/library/actions/extension/perps/assert_orders.mjs +1 -0
  49. package/library/actions/extension/perps/assert_positions.mjs +1 -0
  50. package/library/actions/extension/perps/assert_visible_consistency.mjs +2 -0
  51. package/library/actions/extension/perps/close_orders.mjs +4 -1
  52. package/library/actions/extension/perps/close_positions.mjs +1 -0
  53. package/library/actions/extension/perps/close_visible_position.mjs +159 -10
  54. package/library/actions/extension/perps/compare_provider_market.mjs +2 -0
  55. package/library/actions/extension/perps/edit_margin.mjs +2 -0
  56. package/library/actions/extension/perps/ensure_orders.mjs +1 -0
  57. package/library/actions/extension/perps/ensure_positions.mjs +1 -0
  58. package/library/actions/extension/perps/mutation-receipt.mjs +54 -3
  59. package/library/actions/extension/perps/open_balance_action.mjs +1 -0
  60. package/library/actions/extension/perps/open_position_action.mjs +1 -0
  61. package/library/actions/extension/perps/perps.mjs +401 -25
  62. package/library/actions/extension/perps/place_order.mjs +1 -0
  63. package/library/actions/extension/perps/read_eligibility.mjs +1 -0
  64. package/library/actions/extension/perps/read_funds_confirmation.mjs +2 -0
  65. package/library/actions/extension/perps/read_orders.mjs +1 -0
  66. package/library/actions/extension/perps/read_positions.mjs +1 -0
  67. package/library/actions/extension/perps/read_snapshot.mjs +2 -0
  68. package/library/actions/extension/perps/read_visible_state.mjs +2 -0
  69. package/library/actions/extension/perps/search_markets.mjs +1 -0
  70. package/library/actions/extension/perps/select_activity_filter.mjs +1 -0
  71. package/library/actions/extension/perps/select_market_filter.mjs +1 -0
  72. package/library/actions/extension/perps/set_market_favorite.mjs +1 -0
  73. package/library/actions/extension/perps/state.mjs +1 -0
  74. package/library/actions/extension/perps/update_position_tpsl.mjs +2 -0
  75. package/library/actions/extension/perps/visible-mutation-identity.mjs +2 -0
  76. package/library/actions/extension/platform/cdp.mjs +29 -2
  77. package/library/actions/extension/settings/set_basic_functionality.mjs +1 -0
  78. package/library/actions/extension/swap_bridge/quote-state.mjs +2 -0
  79. package/library/actions/extension/swap_bridge/read_visible_state.mjs +1 -0
  80. package/library/actions/extension/swap_bridge/select_assets.mjs +1 -0
  81. package/library/actions/extension/swap_bridge/set_amount.mjs +1 -0
  82. package/library/actions/extension/swap_bridge/set_max_amount.mjs +1 -0
  83. package/library/actions/extension/swap_bridge/set_slippage.mjs +1 -0
  84. package/library/actions/extension/ui/locators.mjs +1 -0
  85. package/library/actions/extension/ui/navigate.mjs +2 -0
  86. package/library/actions/extension/wallet/ensure_unlocked.mjs +2 -0
  87. package/library/actions/extension/wallet/import.mjs +2 -0
  88. package/library/actions/extension/wallet/list_accounts.mjs +1 -0
  89. package/library/actions/extension/wallet/lock.mjs +2 -0
  90. package/library/actions/extension/wallet/read_state.mjs +1 -0
  91. package/library/actions/extension/wallet/reset.mjs +2 -0
  92. package/library/actions/extension/wallet/secret-input.mjs +2 -0
  93. package/library/actions/extension/wallet/select_account.mjs +2 -0
  94. package/library/actions/extension/wallet/setup.mjs +1 -0
  95. package/library/actions/extension/wallet/state.mjs +2 -0
  96. package/library/actions/extension/wallet/visible-session.mjs +2 -0
  97. package/library/actions/mobile/analytics/consent-settings.mjs +1 -0
  98. package/library/actions/mobile/analytics/set_consent.mjs +1 -0
  99. package/library/actions/mobile/app/network-control.mjs +2 -0
  100. package/library/actions/mobile/app/network.mjs +1 -0
  101. package/library/actions/mobile/app/network_assert.mjs +1 -0
  102. package/library/actions/mobile/app/network_capture.mjs +1 -0
  103. package/library/actions/mobile/assets/import_custom_token.mjs +2 -0
  104. package/library/actions/mobile/assets/open_details.mjs +1 -0
  105. package/library/actions/mobile/assets/read_details.mjs +1 -0
  106. package/library/actions/mobile/assets/read_visible_state.mjs +1 -0
  107. package/library/actions/mobile/assets/set_token_visibility.mjs +2 -0
  108. package/library/actions/mobile/assets/verify_sorting.mjs +90 -7
  109. package/library/actions/mobile/deeplink/open.mjs +1 -0
  110. package/library/actions/mobile/networks/add_custom.mjs +1 -0
  111. package/library/actions/mobile/networks/network-management.mjs +1 -0
  112. package/library/actions/mobile/networks/read_visible_state.mjs +1 -0
  113. package/library/actions/mobile/networks/remove_custom.mjs +1 -0
  114. package/library/actions/mobile/perps/assert_orders.mjs +1 -0
  115. package/library/actions/mobile/perps/assert_positions.mjs +1 -0
  116. package/library/actions/mobile/perps/capture_performance.mjs +1 -0
  117. package/library/actions/mobile/perps/close_orders.mjs +1 -0
  118. package/library/actions/mobile/perps/close_positions.mjs +1 -0
  119. package/library/actions/mobile/perps/ensure_orders.mjs +1 -0
  120. package/library/actions/mobile/perps/ensure_positions.mjs +1 -0
  121. package/library/actions/mobile/perps/measure_homepage_visible.mjs +1 -0
  122. package/library/actions/mobile/perps/performance-capture.mjs +2 -0
  123. package/library/actions/mobile/perps/perps.mjs +6 -2
  124. package/library/actions/mobile/perps/place_order.mjs +1 -0
  125. package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +2 -0
  126. package/library/actions/mobile/perps/read-visible-state-loop.mjs +2 -0
  127. package/library/actions/mobile/perps/read_orders.mjs +1 -0
  128. package/library/actions/mobile/perps/read_positions.mjs +1 -0
  129. package/library/actions/mobile/perps/read_visible_state.mjs +1 -0
  130. package/library/actions/mobile/perps/search_markets.mjs +1 -0
  131. package/library/actions/mobile/perps/set_market_favorite.mjs +2 -0
  132. package/library/actions/mobile/platform/bridge.mjs +16 -4
  133. package/library/actions/mobile/platform/native-session-name.mjs +1 -0
  134. package/library/actions/mobile/platform/native-session.mjs +2 -0
  135. package/library/actions/mobile/platform/observe-ui.mjs +2 -0
  136. package/library/actions/mobile/platform/tool-paths.mjs +1 -0
  137. package/library/actions/mobile/swap_bridge/native-session.mjs +1 -0
  138. package/library/actions/mobile/swap_bridge/read_visible_state.mjs +1 -0
  139. package/library/actions/mobile/swap_bridge/select_assets.mjs +2 -0
  140. package/library/actions/mobile/swap_bridge/set_amount.mjs +1 -0
  141. package/library/actions/mobile/swap_bridge/set_max_amount.mjs +1 -0
  142. package/library/actions/mobile/swap_bridge/set_slippage.mjs +1 -0
  143. package/library/actions/mobile/swap_bridge/submit_transaction.mjs +2 -0
  144. package/library/actions/mobile/ui/locators.mjs +1 -0
  145. package/library/actions/mobile/ui/native-navigation.mjs +2 -0
  146. package/library/actions/mobile/ui/navigate.mjs +2 -0
  147. package/library/actions/mobile/wallet/ensure_unlocked.mjs +2 -0
  148. package/library/actions/mobile/wallet/home.mjs +1 -0
  149. package/library/actions/mobile/wallet/import.mjs +2 -0
  150. package/library/actions/mobile/wallet/list_accounts.mjs +1 -0
  151. package/library/actions/mobile/wallet/lock.mjs +1 -0
  152. package/library/actions/mobile/wallet/native-ui.mjs +2 -0
  153. package/library/actions/mobile/wallet/read_state.mjs +2 -0
  154. package/library/actions/mobile/wallet/reset-helper.mjs +1 -0
  155. package/library/actions/mobile/wallet/reset.mjs +1 -0
  156. package/library/actions/mobile/wallet/select_account.mjs +2 -0
  157. package/library/actions/mobile/wallet/setup.mjs +2 -0
  158. package/library/actions/shared/analytics/assert_events.mjs +3 -0
  159. package/library/actions/shared/analytics/consent.mjs +3 -0
  160. package/library/actions/shared/analytics/read_events.mjs +2 -0
  161. package/library/actions/shared/analytics/start_capture.mjs +3 -0
  162. package/library/actions/shared/app/network-artifact.mjs +2 -0
  163. package/library/actions/shared/app/network-assert.mjs +2 -0
  164. package/library/actions/shared/assets/visible-state.mjs +2 -0
  165. package/library/actions/shared/deeplink/url.mjs +3 -0
  166. package/library/actions/shared/networks/visible-state.mjs +2 -0
  167. package/library/actions/shared/perps/visible-state.mjs +2 -0
  168. package/library/actions/shared/swap-bridge/transaction.mjs +3 -0
  169. package/library/actions/shared/swap-bridge/visible-state.mjs +2 -0
  170. package/library/actions/shared/ui/locators.mjs +2 -0
  171. package/library/actions/shared/wallet/import-source.mjs +3 -0
  172. package/library/manifests/core.action-manifest.json +20 -0
  173. package/library/manifests/extension.action-manifest.json +2 -2
  174. package/library/manifests/mobile.action-manifest.json +3 -3
  175. package/library/recipes/mobile/app/{lifecycle.android-smoke.recipe.json → lifecycle-smoke.recipe.json} +12 -11
  176. package/package.json +1 -1
  177. package/site/assets/help-recipes.json +188 -35
@@ -1,3 +1,6 @@
1
+ // Persist trusted mutation intent, accepted order identities and observed outcomes.
2
+ // Resume observation without redispatching an already recorded operation.
3
+
1
4
  import { createHash } from 'node:crypto';
2
5
  import { constants as fsConstants } from 'node:fs';
3
6
  import {
@@ -461,7 +464,8 @@ function validateIdentity(input, identity) {
461
464
  || !/^(?:market|limit|close|margin|tpsl)$/u.test(value.orderType)
462
465
  || !/^(?:new|modify|close)$/u.test(value.positionMode)
463
466
  || !/^(?:0|[1-9][0-9]{0,29})$/u.test(value.roundingToleranceBaseUnits)
464
- || (value.limitPrice !== null && !/^[1-9][0-9]*(?:\.[0-9]{1,6})?$/u.test(value.limitPrice))
467
+ || (value.limitPrice !== null && (!/^(?:0|[1-9][0-9]*)(?:\.[0-9]{1,6})?$/u.test(value.limitPrice)
468
+ || !(Number(value.limitPrice) > 0)))
465
469
  || (value.offsetPct !== null && !/^-?[0-9]+(?:\.[0-9]{1,6})?$/u.test(value.offsetPct))
466
470
  || (value.partialCloseAmount !== null && !/^[1-9][0-9]*(?:\.[0-9]{1,6})?$/u.test(value.partialCloseAmount))) {
467
471
  throw new Error('External mutation receipt operation parameters are invalid.');
@@ -738,8 +742,54 @@ export async function recordExternalMutationCleanupCandidate(input, receipt, can
738
742
  });
739
743
  }
740
744
 
745
+ async function recordSubmissionAcceptance(input, receipt, acceptance) {
746
+ const { venueOrderId, status, requestId, serviceWorkerTargetId, asset, size, limitPriceBaseUnits, filledSize, averagePrice } = acceptance;
747
+ const closing = receipt.record.identity.operation === 'perps-close-position';
748
+ const market = closing || receipt.record.identity.operation === 'perps-market-order';
749
+ const sizing = closing ? receipt.record.facts?.closeSizing
750
+ : market ? receipt.record.facts?.marketSizing : receipt.record.facts?.limitSizing;
751
+ if (!['perps-limit-order', 'perps-market-order', 'perps-close-position'].includes(receipt.record.identity.operation)
752
+ || receipt.record.identity.provider !== 'hyperliquid'
753
+ || Number(sizing?.size) !== Number(size)
754
+ || (closing && sizing?.side !== (receipt.record.identity.side === 'long' ? 'short' : 'long'))
755
+ || !/^[1-9][0-9]{0,19}$/u.test(String(venueOrderId)) || !['resting', 'filled'].includes(status)
756
+ || !/^[A-Za-z0-9._:-]{1,128}$/u.test(String(requestId))
757
+ || !/^[A-Za-z0-9._:-]{1,128}$/u.test(String(serviceWorkerTargetId))
758
+ || !Number.isInteger(asset) || asset < 0 || asset > 100_000
759
+ || !/^(?:0|[1-9][0-9]{0,19})(?:\.[0-9]{1,8})?$/u.test(String(size)) || !(Number(size) > 0)
760
+ || !BASE_UNITS.test(String(limitPriceBaseUnits))) {
761
+ throw recoveryError(receipt, 'submission acceptance has invalid order identity');
762
+ }
763
+ if (market && status === 'filled' && (!/^(?:0|[1-9][0-9]{0,19})(?:\.[0-9]{1,8})?$/u.test(String(filledSize))
764
+ || !(Number(filledSize) > 0) || Number(filledSize) > Number(size)
765
+ || !/^(?:0|[1-9][0-9]{0,19})(?:\.[0-9]{1,18})?$/u.test(String(averagePrice)) || !(Number(averagePrice) > 0))) {
766
+ throw recoveryError(receipt, 'market acceptance has invalid filled size or price');
767
+ }
768
+ const destination = await receiptDestination(input);
769
+ const current = await readPublished(destination);
770
+ if (!current || current.sha256 !== receipt.sha256 || current.record?.state !== 'outcome-unknown') {
771
+ throw recoveryError(receipt, 'the receipt changed before submission acceptance was recorded');
772
+ }
773
+ const record = { ...current.record, acceptance: {
774
+ venueOrderId, status, requestId, serviceWorkerTargetId, asset, size, limitPriceBaseUnits,
775
+ ...(market && status === 'filled' ? { filledSize, averagePrice } : {}),
776
+ } };
777
+ const staged = await stagedRecord(destination.directory, record);
778
+ try {
779
+ await rename(staged.stagedPath, destination.absolute);
780
+ await durableDirectorySync(destination.directory);
781
+ } finally {
782
+ await rm(staged.stagingDirectory, { recursive: true, force: true });
783
+ }
784
+ const published = await readPublished(destination);
785
+ if (!published || canonical(published.record) !== canonical(record)) {
786
+ throw recoveryError(receipt, 'submission acceptance could not be reread');
787
+ }
788
+ return { ...published, resumed: receipt.resumed };
789
+ }
790
+
741
791
  export async function runGuardedExternalMutation({ input, identity, dispatch, observe, publicationFacts, receiptIo }) {
742
- const receipt = await beginExternalMutation(input, identity, receiptIo, publicationFacts);
792
+ let receipt = await beginExternalMutation(input, identity, receiptIo, publicationFacts);
743
793
  if (receipt.record?.state === 'observed-policy-violation') {
744
794
  throw new Error('External mutation receipt records an observed policy violation and is cleanup-only.');
745
795
  }
@@ -748,7 +798,8 @@ export async function runGuardedExternalMutation({ input, identity, dispatch, ob
748
798
  }
749
799
  if (!receipt.resumed) {
750
800
  try {
751
- await dispatch();
801
+ const acceptance = await dispatch();
802
+ if (acceptance?.venueOrderId) receipt = await recordSubmissionAcceptance(input, receipt, acceptance);
752
803
  } catch (error) {
753
804
  if (error instanceof ExternalMutationNotDispatchedError) {
754
805
  await markExternalMutationNotDispatched(input, receipt, error, receiptIo);
@@ -1,3 +1,4 @@
1
+ // Open the Perps deposit or withdrawal flow through balance controls and report the displayed page.
1
2
  import { dataTestId, runAdapter, withExtensionPage } from '../platform/cdp.mjs';
2
3
 
3
4
  const ACTIONS = new Map([
@@ -1,3 +1,4 @@
1
+ // Navigate to a market position and open its requested modification form without submitting it.
1
2
  import { dataTestId, marketSymbol, runAdapter, withExtensionPage } from '../platform/cdp.mjs';
2
3
 
3
4
  const ACTIONS = new Map([