[pull] main from MetaMask:main#595
Merged
Merged
Conversation
) - refactor(analytics): migrate Batch 2-11: metamask-earn (#26292) ## **Description** Phase 2 analytics migration (Batch 2-11): migrate Stake/Earn's `useMetrics` hook and `MetaMetrics.getInstance()` calls from the legacy MetaMetrics system to the new analytics system. **Reason**: Deprecate MetaMetrics in favour of the shared analytics utility and AnalyticsController. **Changes**: Stake components and hooks now use `useAnalytics` from `hooks/useAnalytics/useAnalytics` and import `MetaMetricsEvents` directly from `core/Analytics`; `withMetaMetrics` utility now uses `analytics.trackEvent()` and `AnalyticsEventBuilder` instead of `MetaMetrics.getInstance().trackEvent()` and `MetricsEventBuilder`; test mocks updated accordingly. ### Changes **Source files (6)**: - `LearnMoreModalFooter.tsx`, `StakingButtons.tsx`, `StakingBalance.tsx`, `StakeButton/index.tsx`: replaced `useMetrics` with `useAnalytics`; `MetaMetricsEvents` now imported from `core/Analytics` - `usePoolStakedDeposit/index.ts`: replaced `useMetrics` with `useAnalytics` (also migrated as it's the source for a listed test file) - `withMetaMetrics.ts`: replaced `MetaMetrics.getInstance().trackEvent()` with `analytics.trackEvent()` and `MetricsEventBuilder` with `AnalyticsEventBuilder` **Test files (3)**: - `StakeButton.test.tsx`: replaced `useMetrics` mock with `useAnalytics` mock; added transitive `useMetrics` mock for unmigrated `useStablecoinLendingRedirect` dependency; replaced `MetricsEventBuilder` with `AnalyticsEventBuilder` - `usePoolStakedDeposit.test.tsx`: replaced `useMetrics` mock/import with `useAnalytics`; replaced `MetricsEventBuilder` with `AnalyticsEventBuilder` - `withMetaMetrics.test.ts`: replaced `MetaMetrics.getInstance()` spy with `analytics` module mock; updated `MetaMetricsEvents` import from `core/Analytics` ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-298 (Batch 2-11) ## **Manual testing steps** ```gherkin Feature: Stake/Earn analytics Scenario: user triggers a stake/earn flow event Given app is open and user is in a stake/earn flow When user performs an action that triggers analytics (e.g. stake button, unstake button, learn more, view staked positions) Then the event is tracked on Mixpanel ``` ## **Screenshots/Recordings** N/A – analytics migration, no UI change. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > This is a broad analytics plumbing migration across Stake/Earn UI and transaction hooks; risk is mainly missed/changed event emission or metadata due to swapped builders and tracking surfaces, not user-facing flow changes. > > **Overview** > Migrates Stake/Earn (Earn CTA, staking balance/buttons, learn-more modal, and pooled-stake deposit hook) from legacy `useMetrics`/`MetaMetrics.getInstance()` tracking to the new analytics stack via `useAnalytics`, `analytics.trackEvent`, and `AnalyticsEventBuilder`. > > Updates related unit tests to mock `useAnalytics`/`analytics` instead of `useMetrics`/MetaMetrics, including a new mock for `useStablecoinLendingRedirect` to avoid transitive legacy metrics behavior and keep navigation assertions stable. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8971698. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [b5b8c71](b5b8c71) Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com>
) - refactor(analytics): migrate Batch 3-1: mobile-platform (#26312) ## **Description** Phase 3 analytics migration (Batch 3-1): migrate Authentication core's `Authentication.ts` from `MetaMetrics.getInstance()` to the new analytics system. **Reason**: Deprecate MetaMetrics in favour of the shared analytics utility and AnalyticsController. **Changes**: `Authentication.ts` now uses `analytics.isEnabled()` from `app/util/analytics/analytics` instead of `MetaMetrics.getInstance().isEnabled()`; test mocks updated to mock the analytics utility instead of MetaMetrics. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-301 (Batch 3-1) ## **Manual testing steps** ```gherkin Feature: Authentication analytics Scenario: user triggers an authentication flow event Given app is open and user is in an authentication flow When user performs an action that triggers analytics (e.g. unlock wallet, login) Then the event is tracked on Mixpanel ``` ## **Screenshots/Recordings** N/A – analytics migration, no UI change. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small refactor limited to the metrics-consent check after unlocking the wallet; main risk is a regression in opt-in navigation if `analytics.isEnabled()` differs from the old `MetaMetrics` behavior. > > **Overview** > `Authentication.unlockWallet` now uses the shared `analytics.isEnabled()` helper (from `util/analytics/analytics`) instead of `MetaMetrics.getInstance().isEnabled()` when deciding whether to route users to the metrics opt-in screen after login. > > Unit tests were updated to mock and spy on the new `analytics` helper rather than `MetaMetrics`, keeping the same enabled/disabled behavior expectations. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a7de545. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [e4effa3](e4effa3) Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com>
…Action cp-7.67.0 (#26457) - chore: New Crowdin translations by Github Action cp-7.67.0 (#26152) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Localization-only JSON string changes; low functional risk aside from potential missing/renamed keys affecting UI text rendering. > > **Overview** > Updates German locale strings (`locales/languages/de.json`) with a large batch of Crowdin changes, including **new translation keys** for features like Market Insights, homepage sections, device authentication/biometrics messaging, network management, and MetaMask Card freeze/unfreeze flows. > > Also revises many existing strings (mostly English-to-German fixes and copy updates) across swap/bridge, perps activity, QR scanning, permissions/connect flows, and various error/toast messages, with some removals/renames (e.g., `merkl_rewards`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e3e2bd4. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> [9b792be](9b792be) Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
… to fix stale cache on slow connections cp-7.67.0 (#26334) - fix(perps): connection-aware ensureReady() to fix stale cache on slow connections cp-7.67.0 (#26324) ## **Description** Fixes [TAT-2597](https://consensys-mesh.atlassian.net/browse/TAT-2597) and [TAT-2598](https://consensys-mesh.atlassian.net/browse/TAT-2598): After the preload PR merged, slow connections caused StreamChannels to exhaust 150 polling retries (30s) in `ensureReady()` and silently give up, leaving users with stale REST cache and no live WebSocket data — positions not appearing after trade, missing prices. **Root Cause:** `StreamChannel.ensureReady()` used blind polling (`isReady` every 200ms × 150 retries) with no awareness of WebSocket connection state. On slow connections, the connection had not even established yet, so polling burned through all retries before data could arrive. **Fix:** - `PerpsConnectionManager.waitForConnection()` — exposes init/reconnect promises so channels can `await` instead of blind-polling - `StreamChannel.ensureReady()` — detects `isConnecting` state and awaits the connection promise via `awaitConnectionThenConnect()` **Result:** PriceStreamChannel retries dropped from **33 → 0** on device after this fix. ## **Changelog** CHANGELOG entry: Fixed stale cache on slow connections where positions and prices were not updating after a trade ## **Related issues** Fixes: [TAT-2597](https://consensys-mesh.atlassian.net/browse/TAT-2597), [TAT-2598](https://consensys-mesh.atlassian.net/browse/TAT-2598) ## **Manual testing steps** ```gherkin Feature: Perps live data on slow connections Scenario: user opens a trade on a slow connection Given the app is connected to a slow 3G network And the user has navigated to the Perps trading screen When user opens a new position Then the position appears immediately in the positions list And price stream connects without excessive retries Scenario: user recovers from network drop Given the user is viewing live perps positions And the network connection drops momentarily When the network connection is restored Then live WebSocket data resumes without stale cache ``` ## **Screenshots/Recordings** ### **Before** <!-- PriceStreamChannel: 33 retries before data appears, positions missing on slow connections --> ### **After** <!-- PriceStreamChannel: 0 retries, positions appear immediately --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. [TAT-2597]: https://consensyssoftware.atlassian.net/browse/TAT-2597?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TAT-2598]: https://consensyssoftware.atlassian.net/browse/TAT-2598?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TAT-2597]: https://consensyssoftware.atlassian.net/browse/TAT-2597?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes connection/retry timing and sequencing for Perps WebSocket subscriptions; regressions could delay or prevent live data if the new await/sentinel logic misfires under edge cases (disconnects, rapid resubscribe). > > **Overview** > Perps stream channels now become **connection-aware**: `StreamChannel.ensureReady()` detects `PerpsConnectionManager`'s `isConnecting` state and waits on a new `waitForConnection()` promise, then retries `connect()` (with duplicate-wait suppression and polling fallback on rejection). > > Retry scheduling was tightened by clearing `deferConnect` timers on fire and centralizing the retry delay via `PERPS_CONSTANTS.ConnectRetryDelayMs`; `MarketDataChannel` now uses this constant as well. Tests were expanded to cover the new await/deferral behavior and the new `PerpsConnectionManager.waitForConnection()` contract. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 39e206b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [43cf1d8](43cf1d8) [TAT-2597]: https://consensyssoftware.atlassian.net/browse/TAT-2597?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TAT-2598]: https://consensyssoftware.atlassian.net/browse/TAT-2598?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [TAT-2597]: https://consensyssoftware.atlassian.net/browse/TAT-2597?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com>
…66.0 (#26337) - fix: Fix StorageService Key Encoding cp-7.66.0 (#26268) ## **Description** ### Problem The `redux-persist-filesystem-storage` library has two problematic behaviors when handling arbitrary keys in `StorageService`: 1. **Slashes (`/`) create subdirectories**: Keys containing slashes are stored in subdirectories, making them unreachable via `getAllKeys`. This breaks the `clear` method for affected keys. 2. **Hyphens (`-`) get corrupted**: The library's internal `fromFileName` function converts hyphens to colons (`:`), meaning keys like `simple-key` are returned as `simple:key` by `getAllKeys`. This causes a permanent mismatch between stored keys and returned keys. ### Solution This PR introduces URI-style encoding for problematic characters in **both namespace and key** portions of storage keys: - `/` → `%2F` (prevents subdirectory creation) - `-` → `%2D` (prevents hyphen-to-colon corruption) - `%` → `%25` (prevents double-encoding issues) The encoding is applied via shared utility functions (`encodeStorageKey`/`decodeStorageKey`) used by both: - `mobileStorageAdapter` in `storage-service-init.ts` - Migration 118 which stores snap source code ### Backward Compatibility **This change is backward compatible and will NOT break existing production keys.** - Existing keys like `storageService:TokenListController:tokensChainsCache:0x1` are **unaffected** because: - The namespace (`TokenListController`) has no special characters → encoding produces identical output - Colons (`:`) are **not encoded** - they pass through unchanged - The key portion (`tokensChainsCache:0x1`) contains no hyphens or slashes - **Strings without `-`, `/`, or `%` characters produce identical output when encoded** - This means all current production keys work exactly as before, while future keys with special characters will be handled correctly ### Examples ``` # No special characters → unchanged (backward compatible) storageService:TokenListController:tokensChainsCache:0x1 → storageService:TokenListController:tokensChainsCache:0x1 # Snap ID with slashes and hyphens → encoded storageService:SnapController:npm:@metamask/bip32-keyring-snap → storageService:SnapController:npm:@MetaMask%2Fbip32%2Dkeyring%2Dsnap # Namespace with hyphen → encoded storageService:Some-Controller:some-key → storageService:Some%2DController:some%2Dkey # Key with slashes → encoded (prevents subdirectory creation) storageService:TestController:nested/path/key → storageService:TestController:nested%2Fpath%2Fkey ``` ### Files Changed | File | Change | |------|--------| | `app/core/Engine/utils/storage-service-utils.ts` | New utility with `encodeStorageKey`/`decodeStorageKey` functions | | `app/core/Engine/utils/storage-service-utils.test.ts` | 35 unit tests for the encoding utilities | | `app/core/Engine/controllers/storage-service-init.ts` | Apply encoding in `mobileStorageAdapter` methods | | `app/core/Engine/controllers/storage-service-init.test.ts` | 22 new tests for key and namespace encoding behavior | | `app/store/migrations/119.ts` | Encode snap IDs when storing snap source code | ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: StorageService key handling issues with `redux-persist-filesystem-storage` ## **Manual testing steps** ```gherkin Feature: StorageService key encoding Scenario: Keys with hyphens are stored and retrieved correctly Given the app is running When StorageService stores a key containing hyphens (e.g., "npm:@metamask/bip32-keyring-snap") Then the key is encoded as "npm:@MetaMask%2Fbip32%2Dkeyring%2Dsnap" on disk And getAllKeys returns the original key "npm:@metamask/bip32-keyring-snap" And getItem with the original key returns the stored data Scenario: Keys with slashes are stored and retrieved correctly Given the app is running When StorageService stores a key containing slashes (e.g., "nested/path/key") Then the key is stored as a single file (not in subdirectories) And getAllKeys returns the original key "nested/path/key" And clear removes the key correctly Scenario: Existing keys with colons remain unchanged Given existing production keys like "storageService:TokenListController:tokensChainsCache:0x1" When the app starts with this fix Then the existing keys are still accessible And no migration is required for existing data ``` ## **Screenshots/Recordings** N/A - No UI changes ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how persistent storage keys are constructed and enumerated, which could impact read/write/clear behavior for stored controller data if encoding is applied inconsistently or assumptions about existing on-disk keys differ. > > **Overview** > Fixes mobile `StorageService` persistence by **encoding both `namespace` and `key` components** before writing to `redux-persist-filesystem-storage` (and decoding on `getAllKeys`) to avoid `/` creating subdirectories and `-` being corrupted. > > Introduces shared `encodeStorageKey`/`decodeStorageKey` utilities and updates migration `119` to encode snap IDs when persisting snap `sourceCode`; expands/updates unit tests to cover encoding/decoding behavior and the updated migration expectations. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit bb0e8d6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> [5d11a21](5d11a21) Co-authored-by: Andre Pimenta <andrepimenta7@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…r account switch (#26349) - fix: cp-7.66.0 refresh staked balance after account switch (#26332) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** fix refresh staking balance after account switch <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: fix refresh staking balance after account switch ## **Related issues** Fixes: #26323 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/1a720a48-83e6-45e0-84e7-29b2cb3479e7 ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/826a347b-e003-4bd6-8816-8bec2b66c423 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small, localized change to a `useEffect` dependency plus a new test; main risk is accidental extra refresh calls impacting performance or causing redundant network requests. > > **Overview** > Refresh behavior on the `Wallet` screen is updated so `AccountTrackerController.refresh` is re-triggered when `selectedInternalAccount` changes (added to the relevant `useEffect` dependency list), fixing stale balance/staking data after an account switch. > > Tests are updated to cover this regression by asserting `refresh` is called again when `AccountsController.internalAccounts.selectedAccount` changes, and snapshots are updated accordingly. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a15a4d1. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [c70f38d](c70f38d) Co-authored-by: Salim TOUBAL <salim.toubal@outlook.com>
…ount with getClaimPayoutFromReceipt cp-7.66.0 (#26361) - refactor(musd): replace decodeMerklClaimAmount with getClaimPayoutFromReceipt cp-7.66.0 (#26342) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The mUSD claim transaction amount was displaying the cumulative total reward (from Merkl distributor calldata `amounts[0]`) instead of the actual per-transaction payout. This caused incorrect amounts in the Activity list and transaction detail views — e.g., if a user made multiple claims, each one would show the running total rather than what was actually claimed in that specific transaction. The fix introduces `getClaimPayoutFromReceipt()` which extracts the real payout from the ERC-20 `Transfer` event in the transaction receipt logs (emitted when the Merkl distributor transfers mUSD to the user). This is used as the primary source for confirmed transactions across: - Activity list (`decodeMusdClaimTx`) - Transaction detail hero (`useClaimAmount`) - Confirmation flow (`useMerklClaimAmount`) ## **Changelog** CHANGELOG entry: Fixed mUSD claim transactions showing incorrect cumulative total instead of per-transaction payout amount ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: mUSD claim transaction amount display Scenario: user views a confirmed mUSD claim transaction in Activity Given user has made one or more mUSD claim transactions from this device And at least one claim transaction is confirmed When user navigates to the Activity tab Then the claim transaction shows the correct per-transaction payout amount (not cumulative total) Scenario: user views claim transaction details Given user has a confirmed mUSD claim transaction visible in Activity When user taps on the claim transaction Then the detail view shows the correct claimed amount matching the actual payout Scenario: user views a pending mUSD claim in the Activity list Given user has a pending mUSD claim transaction When user views the transaction in Activity Then the amount shows "Not available" until the transaction confirms And once confirmed, the correct payout amount appears ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how `musdClaim` amounts are derived in Activity/details/confirmation flows, relying on receipt log parsing and BigInt decoding; incorrect log matching or missing receipts could cause amounts to be blank or wrong. > > **Overview** > **Fixes incorrect mUSD claim amounts** by switching from decoding the Merkl claim calldata (cumulative total) to extracting the per-transaction payout from the ERC-20 `Transfer` event in the transaction receipt via new `getClaimPayoutFromReceipt()`. > > Updates `musdClaim` display/amount computation in the Activity list (`decodeMusdClaimTx`), transaction details hero (`useClaimAmount`), and confirmation flow hook (`useMerklClaimAmount`, which now prefers receipt payout when confirmed and falls back to the async unclaimed-amount calculation when pending). Tests are updated to validate receipt-log extraction and the new UI behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c66b845. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [0ef570f](0ef570f) Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com>
…28hj-76wf cp-7.66.0 (#26427) - chore: allow list audit finding GHSA-378v-28hj-76wf cp-7.66.0 (#26386) add bn.js affected by an infinite loop. No fix available yet (latest is 5.2.1, affected <=5.2.3). Suppressing for now to unblock CI. GHSA-378v-28hj-76wf <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Configuration-only change to suppress a specific audit warning; no runtime logic changes, but it reduces audit signal for this known issue. > > **Overview** > Updates Yarn config to ignore the `bn.js` npm audit advisory `GHSA-378v-28hj-76wf` (ID `1113402`) in `npmAuditIgnoreAdvisories`, to unblock CI until a fix is available. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6560f97. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [ebce642](ebce642) Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
…ted to super bowl banner on carousel (#26375) - chore(predict): cp-7.66.0 remove code related to super bowl banner on carousel (#26363) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** The Carousel previously had special handling for the Predict Superbowl banner: it could replace the entire carousel with a single `PredictMarketSportCardWrapper` when a Superbowl slide with a `marketId` was present, and hid that slide from the normal carousel. This change removes that integration. **What changed:** - **Carousel (`index.tsx`):** Removed Predict/Superbowl imports, the `predictSuperbowlSlide` and `predictSuperbowlMarketId` memos, the early return that rendered `PredictMarketSportCardWrapper`, the filter that excluded `PREDICT_SUPERBOWL_VARIABLE_NAME` from visible slides, and the `handleSportCardDismiss` / `handlePredictSuperbowlLoad` callbacks (including "Banner Display" tracking for the Superbowl card). - **Tests (`index.test.tsx`):** Removed the `PredictMarketSportCardWrapper` mock, the `PREDICT_SUPERBOWL_VARIABLE_NAME` import, and the entire "Carousel Predict Superbowl Integration" describe block and its five tests (render with/without marketId, props, tracking). The Carousel no longer has any Superbowl-specific behavior; any such slides from Contentful would now be treated as normal carousel slides. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Removes a time-bound/feature-specific code path and its tests without touching core navigation or data handling; main risk is unintended behavior if Contentful still serves Superbowl slides. > > **Overview** > Removes the Carousel’s special-case Predict Superbowl behavior so it no longer replaces the carousel with a `PredictMarketSportCardWrapper` when a Superbowl slide is present. > > This deletes Superbowl-specific slide detection/metadata handling, explicit filtering of the Superbowl slide from `visibleSlides`, and related dismiss/load callbacks + “Banner Display” tracking. The test suite is updated by dropping the Predict Superbowl mock and all associated integration tests. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4bde723. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [6eb88ac](6eb88ac) Co-authored-by: Caainã Jeronimo <caainaje@gmail.com>
…sion and musd_claim transaction types to transaction-controller metrics_properties (#26433) - feat: cp-7.66.0 MUSD-357 added musd_conversion and musd_claim transaction types to transaction-controller metrics_properties (#26383) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Added musd_conversion and musd_claim transaction types to transaction-controller metrics_properties <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: added musd_conversion and musd_claim transaction types to transaction-controller metrics_properties ## **Related issues** Fixes: [MUSD-357: Add musdConversion and musdClaim Transaction Types to "Transaction *" Events](https://consensyssoftware.atlassian.net/browse/MUSD-357) ## **Manual testing steps** ```gherkin Feature: mUSD transaction analytics classification Scenario: user submits mUSD conversion or claim transaction Given user has an mUSD conversion or mUSD claim transaction in the wallet flow When the wallet emits general transaction lifecycle events Then analytics include a specific transaction_type value And transaction_type is "musd_conversion" for conversion transactions And transaction_type is "musd_claim" for claim transactions ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Small, additive change limited to analytics `transaction_type` labeling plus test coverage; low risk aside from potential downstream dashboard/event-name expectations. > > **Overview** > Adds analytics classification for nested mUSD transactions by mapping `TransactionType.musdConversion` and `TransactionType.musdClaim` to `transaction_type` values `musd_conversion` and `musd_claim` in `getTransactionTypeValue`. > > Extends the existing parameterized test to cover these new nested transaction type mappings. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 3aa4ee5. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [435a464](435a464) Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com>
This PR updates the change log for 7.66.0. (Hotfix - no test plan generated.) Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
sync release/7.67.0 with stable
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry:
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: my feature name
Scenario: user [verb for user action]
Given [describe expected initial app state]
When user [verb for user action]
Then [describe expected outcome]
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
<!-- [screenshots/recordings] -->
### **After**
<!-- [screenshots/recordings] -->
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
---------
Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com>
Co-authored-by: Caainã Jeronimo <caainaje@gmail.com>
Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com>
Co-authored-by: Prithpal Sooriya <prithpal.sooriya@consensys.net>
Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Co-authored-by: Juanmi <95381763+juanmigdr@users.noreply.github.com>
Co-authored-by: Bruno Nascimento <brunonascimentodev@gmail.com>
Co-authored-by: Ale Machado <alejandro@macha.do>
Co-authored-by: Bryan Fullam <bryan.fullam@consensys.net>
Co-authored-by: Aslau Mario-Daniel <marioaslau@gmail.com>
Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
Co-authored-by: Cal-L <cal.leung@consensys.net>
Co-authored-by: Bruno Nascimento <bruno.nascimento@consensys.net>
Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com>
Co-authored-by: OGPoyraz <omergoktugpoyraz@gmail.com>
Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net>
Co-authored-by: Florin Dzeladini <florin.dzeladini@consensys.net>
Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com>
Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com>
Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com>
Co-authored-by: sahar-fehri <sahar.fehri@consensys.net>
Co-authored-by: George Weiler <georgejweiler@gmail.com>
Co-authored-by: George Marshall <george.marshall@consensys.net>
Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com>
Co-authored-by: sophieqgu <37032128+sophieqgu@users.noreply.github.com>
Co-authored-by: Wei Sun <wei.sun@consensys.net>
Co-authored-by: ieow <4881057+ieow@users.noreply.github.com>
Co-authored-by: himanshu <himanshuchawla2014@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Andre Pimenta <andrepimenta7@gmail.com>
Co-authored-by: Salim TOUBAL <salim.toubal@outlook.com>
Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com>
Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com>
- feat: Fix for Pull to Refresh IAB gesture bug (#26373) ## **Description** Pull-to-refresh gesture was intercepting taps on buttons near the top of the page (e.g., Polymarket "Sign Up" / "Log In" buttons). The gesture handler called `stateManager.activate()` immediately in `onTouchesDown` for the pull zone (`y < 50px`), stealing the touch from the WebView before knowing whether the user intended to tap or pull. ### Changes **Deferred activation for pull-to-refresh**: Instead of activating immediately, the gesture enters a `pending_refresh` state in `onTouchesDown`. New `onTouchesMove` and `onTouchesUp` handlers measure the movement delta: - Downward movement >10px → activate pull-to-refresh - Horizontal/upward movement >10px → fail and let WebView handle - Finger lifts with <10px movement (tap) → fail and let WebView handle **`Gesture.Simultaneous` instead of `Gesture.Race`**: Deferred activation requires that the Native gesture (WebView scroll) does not cancel our Pan while it is deciding. `Gesture.Simultaneous` allows both to run independently — taps pass through to the WebView while our Pan stays in BEGAN state deciding, and when Pan activates for a real pull at the top of the page, the WebView has nothing to scroll so both coexist without visual conflict. ### Why not other approaches - `Gesture.Race` + deferred activation: Native wins the race and cancels Pan before `onTouchesMove` fires - `Gesture.Race` + immediate activation + synthetic JS click replay: Pull-to-refresh works but synthetic events have `isTrusted = false` — React ignores them - `Gesture.Exclusive` + deferred activation: Blocks Native while Pan is in BEGAN — nothing works ## **Changelog** CHANGELOG entry: Fixed pull-to-refresh gesture intercepting taps on buttons near the top of the page in the in-app browser ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-352 ## **Manual testing steps** ```gherkin Feature: Browser gesture tap passthrough Scenario: User taps a button near the top of a webpage Given the user is on polymarket.com in the in-app browser And the page is scrolled to the top (not scrolled at all) When user taps the "Log In" or "Sign Up" button Then the login/signup modal should appear Scenario: User pulls to refresh from the top of the page Given the user is on any webpage in the in-app browser And the page is scrolled to the top When user places finger near the top of the page and drags downward Then the refresh indicator should appear And the page should reload when pulled past the threshold Scenario: User swipes back from the left edge Given the user has navigated to at least one page in the in-app browser When user swipes from the left edge of the screen toward the right Then the browser should navigate back to the previous page Scenario: User swipes forward from the right edge Given the user has navigated back at least once in the in-app browser When user swipes from the right edge of the screen toward the left Then the browser should navigate forward Scenario: User scrolls normally in the center of the page Given the user is on any webpage in the in-app browser When user scrolls up or down in the center of the page Then the page should scroll normally without triggering any gestures ``` ## **Screenshots/Recordings** ### **Before** <!-- Tapping buttons near the top of the page (e.g. Polymarket Sign Up/Log In) shows button animation but does not trigger the action --> ### **After** <!-- Tapping the same buttons now correctly opens the login/signup flow --> https://github.com/user-attachments/assets/75c70094-6f39-4086-aab4-368cc6b81177 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes low-level gesture coordination between the WebView native handler and a manual-activation Pan gesture, which could affect navigation/scroll/tap behavior across devices. Added tests reduce regression risk but gesture interactions are inherently sensitive to edge cases. > > **Overview** > Fixes an in-app browser bug where pull-to-refresh could steal taps near the top of the page by introducing **deferred pull-to-refresh activation**: touches in the pull zone now enter a `pending_refresh` state and only activate refresh after moving downward more than `PULL_MOVE_ACTIVATION` (10px), while horizontal/upward movement or lifting the finger fails the gesture and lets the WebView handle the tap. > > Switches WebView gesture composition from `Gesture.Race` to `Gesture.Simultaneous` so the WebView’s native gesture can continue receiving taps while the Pan gesture decides whether to activate, and extends unit tests/mocks to cover the new `onTouchesMove`/`onTouchesUp` paths and the new constant. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit af9d1b7. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> [9b336fc](9b336fc) Co-authored-by: Aslau Mario-Daniel <marioaslau@gmail.com> Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
This reverts commit 56dff68.
…into release/7.66.1
Resolved conflicts between stable (7.67.3) and release/7.68.0: Build/version: take release/7.68.0 versions (7.68.0, build 3939) - android/app/build.gradle, ios project, bitrise.yml Dependencies: take release/7.68.0 versions - package.json: assets-controllers v100.0.3, smart-transactions v22.6.0, transaction-controller v62.19.0, transaction-pay-controller v16.1.2 - yarn.lock: take release/7.68.0 Source code: take release/7.68.0 (newer analytics hooks, nav types, auth) - DaimoPayModal, VerifyIdentity: useAnalytics over useMetrics - PerpsOrderView: removed NavigationProp generic (nav v6 prep) - Login: added useAuthCapabilities - Authentication.test: type fix (undefined as never) - babel.config.tests: added rewards/card env var exclusions Config: OTA_VERSION kept at v7.67.2 (latest from stable) Locales: take release/7.68.0 (14 language files with newer translations) Made-with: Cursor
## Summary This PR syncs the latest changes from `stable` into `release/7.68.0`. ## Why is this needed? `release/7.68.0` is missing 74 commits from `stable`, including: - release: 7.67.0 (#26310) - release: 7.67.1 (#26799) - release: 7.67.2 (#26985) - release: 7.67.3 (#27040) - Associated hotfixes and cherry-picks (Perps connection recovery, Snaps controller bump, OTA updates, etc.) ## Action Required **Please review and resolve any merge conflicts manually.** If there are conflicts, they will appear in this PR. Resolve them to ensure the release branch has all the latest fixes from stable. **Merge with \"Create a merge commit\" — do NOT squash.** <!-- CURSOR_SUMMARY --> --- > [!NOTE] > <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is generating a summary for commit 3f6baad. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com> Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com> Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: MetaMask Bot <37885440+metamaskbot@users.noreply.github.com> Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com> Co-authored-by: Andre Pimenta <andrepimenta7@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Salim TOUBAL <salim.toubal@outlook.com> Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com> Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com> Co-authored-by: Caainã Jeronimo <caainaje@gmail.com> Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com> Co-authored-by: Aslau Mario-Daniel <marioaslau@gmail.com> Co-authored-by: Prithpal Sooriya <prithpal.sooriya@consensys.net> Co-authored-by: Michal Szorad <michal.szorad@consensys.net> Co-authored-by: Juanmi <95381763+juanmigdr@users.noreply.github.com> Co-authored-by: Bruno Nascimento <brunonascimentodev@gmail.com> Co-authored-by: Ale Machado <alejandro@macha.do> Co-authored-by: Bryan Fullam <bryan.fullam@consensys.net> Co-authored-by: Mark Stacey <markjstacey@gmail.com> Co-authored-by: Cal-L <cal.leung@consensys.net> Co-authored-by: Bruno Nascimento <bruno.nascimento@consensys.net> Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com> Co-authored-by: OGPoyraz <omergoktugpoyraz@gmail.com> Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net> Co-authored-by: Florin Dzeladini <florin.dzeladini@consensys.net> Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com> Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com> Co-authored-by: sahar-fehri <sahar.fehri@consensys.net> Co-authored-by: George Weiler <georgejweiler@gmail.com> Co-authored-by: George Marshall <george.marshall@consensys.net> Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com> Co-authored-by: sophieqgu <37032128+sophieqgu@users.noreply.github.com> Co-authored-by: Wei Sun <wei.sun@consensys.net> Co-authored-by: ieow <4881057+ieow@users.noreply.github.com> Co-authored-by: himanshu <himanshuchawla2014@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Bernardo Garces Chapero <bernardo.chapero@consensys.net> Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com> Co-authored-by: Brian August Nguyen <brianacnguyen@gmail.com> Co-authored-by: Alejandro Garcia <alejandro.garcia@consensys.net> Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>
This PR updates the change log for 7.68.0. (Hotfix - no test plan generated.) Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: chloeYue <chloe.gao@consensys.net>
# 🚀 v7.68.0 Testing & Release Quality Process Hi Team, As part of our new **MetaMask Release Quality Process**, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment. --- ## 📋 Key Processes ### Testing Strategy - **Developer Teams:** Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows. - **QA Team:** Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing. - **Customer Success Team:** Validate new functionalities and provide feedback to support release monitoring. ### GitHub Signoff - Each team must **sign off on the Release Candidate (RC)** via GitHub by the end of the validation timeline (**Tuesday EOD PT**). - Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed. ### Issue Resolution - **Resolve all Release Blockers** (Sev0 and Sev1) by **Tuesday EOD PT**. - For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines. ### Cherry-Picking Criteria - Only **critical fixes** meeting outlined criteria will be cherry-picked. - Developers must ensure these fixes are thoroughly reviewed, tested, and merged by **Tuesday EOD PT**. --- ## 🗓️ Timeline and Milestones 1. **Today (Friday):** Begin Release Candidate validation. 2. **Tuesday EOD PT:** Finalize RC with all fixes and cherry-picks. 3. **Wednesday:** Buffer day for final checks. 4. **Thursday:** Submit release to app stores and begin rollout to 1% of users. 5. **Monday:** Scale deployment to 10%. 6. **Tuesday:** Full rollout to 100%. --- ## ✅ Signoff Checklist Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion: # Team sign-off checklist - [x] Accounts Framework - [x] Assets - [x] Bots Team - [x] Card - [x] Confirmations - [x] Core Platform - [x] Design System - [x] Earn - [x] Extension Platform - [x] Mobile Platform - [x] Mobile UX - [x] Networks - [x] Onboarding - [x] Perps - [x] Predict - [x] Ramp - [x] Rewards - [x] Social & AI - [x] Swaps and Bridge - [x] Transactions - [x] Wallet Integrations This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀 Feel free to reach out if you have questions or need clarification. Many thanks in advance # Reference - Testing plan sheet - https://docs.google.com/spreadsheets/d/1tsoodlAlyvEUpkkcNcbZ4PM9HuC9cEM80RZeoVv5OCQ/edit?gid=404070372#gid=404070372
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Migrated `Label` component (core UX scope). ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-276 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/50065c3f-8fe8-4ad6-908a-08e4a0ae7d2d" /> ### **After** <img width="1206" height="2622" alt="image" src="https://github.com/user-attachments/assets/4fbe9805-1ecf-418f-9ecd-555a266b042e" /> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI-only change that swaps `Label` implementations and updates props/snapshots; no business logic or data/auth flows are modified. > > **Overview** > Migrates `Label` usage in `ChoosePassword`, `ManualBackupStep1`, `OAuthRehydration`, and `ResetPassword` from the local component-library to `@metamask/design-system-react-native`. > > Updates `Label` props to the design-system API (e.g., `fontWeight` and `DSTextColor.TextDefault`) and refreshes Jest snapshots to reflect the resulting style output changes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fa7ff7c. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Replaces the sticky "Buy/Sell" footer buttons in the token details treatment variant with "Swap/Buy": * **Swap** uses the existing swap navigation (goToSwaps() with no overrides — source = current token, dest = swap UI default) * **Buy** redirects to on-ramp (fiat purchase), matching the existing Cash Buy behavior Button visibility is conditional on two signals: * **Swap** shown when user has eligible tokens to swap from (hasEligibleSwapTokens). Per Swaps lead guidance, the Swap button is no longer gated on chain support — even if the current token's chain isn't natively supported by Swaps, the user is routed into the Swap flow which defaults to Ethereum pre-fills. * **Buy** shown when ramp supports the token (isBuyable), or as a fallback when user has no swap-eligible tokens — ensuring there is always at least one CTA in the sticky footer. No changes to the control variant (legacy inline action buttons). ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Updated token details sticky footer from Buy/Sell to Swap/Buy buttons ## **Related issues** Fixes: #27326 ## **Manual testing steps** ```gherkin Feature: Token details sticky Swap/Buy footer Scenario: user sees both Swap and Buy Given user has ETH and USDC in wallet When user opens a ramp-supported token (e.g. LINK) Then sticky footer shows "Swap" and "Buy" And tapping Swap opens bridge UI with source = LINK And tapping Buy opens the on-ramp flow Scenario: user sees Swap only when ramp unsupported Given user has ETH and USDC in wallet When user opens a token not supported by ramp providers Then sticky footer shows only "Swap" Scenario: user sees Swap on unsupported chain Given user has ETH on Ethereum mainnet When user opens a native token on Fantom (unsupported by Swaps) Then sticky footer still shows "Swap" And tapping Swap routes to Swap flow with Ethereum pre-fills Scenario: user sees Buy only when no swap-eligible tokens Given user has an empty wallet or only holds the viewed token When user opens a ramp-supported token Then sticky footer shows only "Buy" Scenario: user sees Buy as fallback Given user has an empty wallet When user opens a token not supported by ramp providers Then sticky footer shows only "Buy" And the ramp screen handles notifying the user it is unsupported Scenario: trending token swap direction Given user has ETH and taps a token from trending feed When user taps Swap in the sticky footer Then bridge UI opens with source = ETH, dest = trending token ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> <img width="381" height="775" alt="Screenshot 2026-03-11 at 09 24 41" src="https://github.com/user-attachments/assets/dc45c238-5b39-40df-8ecb-4e379aaea7ef" /> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Updates token details treatment CTA logic and navigation, which can affect conversion flows (swaps/on-ramp) and button visibility across tokens/chains. Risk is moderate due to UX/flow changes but limited to the A/B treatment and covered by updated unit tests. > > **Overview** > Updates the Token Details *treatment* sticky footer to show **`Swap`/`Buy`** CTAs instead of `Buy`/`Sell`. `Swap` now routes via `goToSwaps()` and is shown when `useTokenActions` reports `hasEligibleSwapTokens`; `Buy` routes to on-ramp via `onBuy` and is shown when the token is ramp-buyable (`useTokenBuyability`) or as a fallback when no swap-eligible tokens exist. > > Extends `useTokenActions` to expose `hasEligibleSwapTokens` and updates `TokenDetails.test.tsx` to reflect the new button set and visibility matrix. Also adjusts the provider selection empty-state copy to use `fiat_on_ramp_aggregator.no_providers_available` when quotes are not shown. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 652129d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
…#26964) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** This PR improves the resilience of Android Google OAuth (ACM) error handling and adds proper Sentry error segregation for OAuth login failures. **Problem:** 1. Android Credential Manager (ACM) errors with unrecognized message formats fall through to `UnknownError`, bypassing the browser fallback — leaving users stuck with a cryptic error instead of getting the browser-based OAuth alternative. 2. All OAuth errors (iOS and Android, all providers) are grouped into a single Sentry issue because `captureException` uses the same stack trace fingerprint, making it impossible to distinguish platform-specific or provider-specific failures. 3. `OAuthError` message construction produces ugly double-prefixed strings like `"Unknown error - Error: e1 error..."` when wrapping Error objects. **Solution:** - **Broadened ACM regex patterns** — `CANCEL` is now more specific (avoids false positives), and `NO_PROVIDER_DEPENDENCIES` catches more message variants across Android versions/vendors. - **UnknownError browser fallback** — Any unrecognized ACM error on Android Google now triggers the browser-based OAuth fallback instead of surfacing a dead-end error to the user. - **Sentry fingerprinting** — `handleOAuthLoginError` now includes `oauth_platform`, `oauth_provider`, `oauth_error_code`, and `oauth_is_fallback` tags, with a custom fingerprint that groups errors by platform + provider + error code. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Fixed Android Google sign-in errors not falling back to browser-based login for unrecognized credential manager failures ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TO-564 ## **Manual testing steps** ```gherkin Feature: Android Google ACM browser fallback Scenario: user signs in with Google on Android when ACM fails with unrecognized error Given user is on the Onboarding screen on an Android device And the Android Credential Manager is unavailable or returns an unrecognized error When user taps "Continue with Google" Then the app should automatically fall back to browser-based Google OAuth And the user should be able to complete sign-in via the browser ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/700c76f7-322e-4cb0-b5b1-4806939fd5ca https://github.com/user-attachments/assets/19276c56-635a-4c7f-82e6-8825f8b5b0f2 <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touching social login error handling and fallback paths can change user sign-in behavior on Android and alters Sentry reporting; scope is contained to onboarding OAuth flows and error classification. > > **Overview** > Ensures **Android Google sign-in** falls back to browser-based OAuth not only for known ACM failures, but also for `UnknownError` cases that previously surfaced as dead-end errors. > > Improves observability by adding provider/platform/error-code tags and a custom Sentry fingerprint in `handleOAuthLoginError`, and refines Android ACM regex matching (cancel + provider dependency variants). Also cleans up `OAuthError` message formatting to avoid double-prefixed error strings, and adds tests covering the new Android-only `UnknownError` fallback behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 62dcde6. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Summary
- Adds `.claude/commands/e2e-test.md` — new Claude skill (`/e2e-test`)
that guides through adding Detox E2E tests end-to-end
- Adds `.ai/skills/e2e-test/` — multi-AI skill definition (Cursor,
Copilot, Windsurf) with detailed reference docs
## What the skill does
The skill walks an AI agent through the full E2E test creation loop:
1. **Plan** — determine smoke vs regression, choose feature folder and
tag
2. **Infrastructure** — create/reuse Page Objects
(`tests/page-objects/`), selectors (`*.testIds.ts`), and API mocks
3. **Write spec** — `withFixtures` + `FixtureBuilder` + POM, mandatory
descriptions on all gestures/assertions
4. **Lint + TSC** — run before executing the test
5. **Run locally** — `detox test -c ios.sim.main --testPathPattern=...`
6. **Iterate** — analyze failure → fix → re-lint → re-run until green
## Reference docs structure
```
.ai/skills/e2e-test/
├── SKILL.md ← 10 golden rules + workflow overview + quick commands
└── references/
├── writing-tests.md ← spec templates, FixtureBuilder patterns
├── page-objects.md ← POM structure, Matchers/Gestures/Assertions API
├── mocking.md ← testSpecificMock, feature flags, HTTP mocking
└── running-tests.md ← detox commands, common failures & fixes, retry pattern
```
## Related
Follows the same pattern as PR #27013 (component-view-test skill
reorganization).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Documentation-only additions and pointer updates; no runtime code
paths or test framework behavior changes.
>
> **Overview**
> Introduces a new canonical `e2e-test` agent skill under
`.agents/skills/e2e-test/`, including a decision tree, “golden rules”,
and focused reference guides for writing specs, page objects/selectors,
mocking, and running/debugging Detox.
>
> Hooks the skill into agent tooling via
`.agents/skills/e2e-test/agents/openai.yaml`, adds a thin
redirect/enforcement stub at `.claude/skills/e2e-test/SKILL.md`, and
updates `tests/AGENTS.md` to point contributors/agents to the new
canonical skill.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3deb799. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…27377) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> This PR adds a rule to ensure `react-native-gesture-handler`'s `ScrollView` is used with `BottomSheet`. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: documentation-only change with no runtime/code-path impact. Only affects developer guidance and review checklist items. > > **Overview** > Adds a new *Platform-Specific Gotcha* to the UI development guidelines specifying that `ScrollView` used inside a `BottomSheet` must be imported from `react-native-gesture-handler` (to avoid Android scrolling issues), including a correct/incorrect import example. > > Updates the pre-commit checklist to include verifying this `ScrollView` import rule. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6e32e1e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…27245) ## **Description** Claims ownership of onboarding and SRP-related screens for the `@MetaMask/web3auth` team in CODEOWNERS. These screens are part of the onboarding flow that web3auth is responsible for, but were previously unowned. ### Screens added: | Screen | Path | |--------|------| | OnboardingSheet | `app/components/Views/OnboardingSheet` | | ChoosePassword | `app/components/Views/ChoosePassword` | | ManualBackupStep1 | `app/components/Views/ManualBackupStep1` | | ManualBackupStep2 | `app/components/Views/ManualBackupStep2` | | ManualBackupStep3 | `app/components/Views/ManualBackupStep3` | | AccountBackupStep1 | `app/components/Views/AccountBackupStep1` | | AccountBackupStep1B | `app/components/Views/AccountBackupStep1B` | | ImportFromSecretRecoveryPhrase | `app/components/Views/ImportFromSecretRecoveryPhrase` | | ImportNewSecretRecoveryPhrase | `app/components/Views/ImportNewSecretRecoveryPhrase` | | SelectSRP | `app/components/Views/SelectSRP` | | SrpInput | `app/components/Views/SrpInput` | | RestoreWallet | `app/components/Views/RestoreWallet` | | WalletCreationError | `app/components/Views/WalletCreationError` | | OAuthRehydration | `app/components/Views/OAuthRehydration` | | SocialLoginIosUser | `app/components/Views/SocialLoginIosUser` | | RevealPrivateCredential | `app/components/Views/RevealPrivateCredential` | ### Also cleaned up: - Removed `OnboardingCarousel` entry (directory no longer exists) ## **Changelog** CHANGELOG entry: null ## **Related issues** N/A — Housekeeping to ensure proper code review routing. ## **Manual testing steps** No testing required — CODEOWNERS-only change. ## **Screenshots/Recordings** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md) - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on this PR - [x] I've manually tested this PR - [x] I've confirmed there are no breaking changes ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
…27275) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: remove thrown exceptions in migration 121 when `NetworkEnablementController` is absent or `NetworkEnablementController.nativeAssetIdentifiers` is missing. ## **Related issues** Fixes: #27325 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` (if we want to test it since it is a log message thing) - Reset data. - Find a version of the app prior the creation of `NetworkEnablementController` and install it. - Update to latest. - The error message will appear in the logs. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Limits Sentry reporting in migration `121` by no longer emitting exceptions for expected/benign missing-state cases; migration behavior/data transforms are otherwise unchanged. > > **Overview** > Migration `121` no longer calls `captureException` when `NetworkEnablementController` is absent or when `NetworkEnablementController.nativeAssetIdentifiers` is missing; these cases now silently short-circuit. > > Tests for migration `121` are updated to assert **no** Sentry exception is captured for those missing-field scenarios, while retaining exception expectations for type-mismatch cases. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5b65b69. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Added new automated tests metrics to follow trends: - qa metrics script extended - artifact names changed <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** - revisit jobs and artefacts manually ✅ - check new metrics output ✅ ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [ ] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches multiple GitHub Actions workflows and artifact naming/patterns; misalignment could break test report downloads, rerun merging, or metrics generation even though it doesn’t affect production code. > > **Overview** > Updates QA stats collection to emit **namespaced** metrics (`component_view`, `unit`, `e2e`, `performance`) and to derive counts directly from CI artifacts: per-feature Jest counts from shard `coverage-*` artifacts, executed E2E counts parsed from JUnit XML (with main vs flask + platform health signals), and performance scenario counts by scanning `tests/performance` specs. Metrics are now omitted when artifacts/tests are missing rather than defaulting to zero. > > Adjusts CI workflows to support this data: unit/CV shards now include `jest-results.json` inside `coverage-*` artifacts, and E2E workflows standardize artifact naming via a new `artifact_name_prefix` input (default `main-`, blank for flask), update download patterns accordingly, rename the fixture-validation artifact, and rebuild merged JUnit XML after re-run result merging. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit beebe26. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This PR syncs the stable branch to main for version 7.70.0. *Synchronization Process:* - Fetches the latest changes from the remote repository - Resets the branch to match the stable branch - Attempts to merge changes from main into the branch - Handles merge conflicts if they occur *File Preservation:* Preserves specific files from the stable branch: - CHANGELOG.md - bitrise.yml - android/app/build.gradle - ios/MetaMask.xcodeproj/project.pbxproj - package.json Indicates the next version candidate of main to 7.70.0 --------- Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com> Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com> Co-authored-by: runway-github[bot] <73448015+runway-github[bot]@users.noreply.github.com> Co-authored-by: Nico MASSART <NicolasMassart@users.noreply.github.com> Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: abretonc7s <107169956+abretonc7s@users.noreply.github.com> Co-authored-by: Andre Pimenta <andrepimenta7@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Salim TOUBAL <salim.toubal@outlook.com> Co-authored-by: Patryk Łucka <5708018+PatrykLucka@users.noreply.github.com> Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com> Co-authored-by: Caainã Jeronimo <caainaje@gmail.com> Co-authored-by: Matthew Grainger <46547583+Matt561@users.noreply.github.com> Co-authored-by: Aslau Mario-Daniel <marioaslau@gmail.com> Co-authored-by: Prithpal Sooriya <prithpal.sooriya@consensys.net> Co-authored-by: Michal Szorad <michal.szorad@consensys.net> Co-authored-by: Juanmi <95381763+juanmigdr@users.noreply.github.com> Co-authored-by: Bruno Nascimento <brunonascimentodev@gmail.com> Co-authored-by: Ale Machado <alejandro@macha.do> Co-authored-by: Bryan Fullam <bryan.fullam@consensys.net> Co-authored-by: Mark Stacey <markjstacey@gmail.com> Co-authored-by: Cal-L <cal.leung@consensys.net> Co-authored-by: Bruno Nascimento <bruno.nascimento@consensys.net> Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com> Co-authored-by: OGPoyraz <omergoktugpoyraz@gmail.com> Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net> Co-authored-by: Florin Dzeladini <florin.dzeladini@consensys.net> Co-authored-by: Nick Gambino <35090461+gambinish@users.noreply.github.com> Co-authored-by: Vince Howard <vincenguyenhoward@gmail.com> Co-authored-by: sahar-fehri <sahar.fehri@consensys.net> Co-authored-by: George Weiler <georgejweiler@gmail.com> Co-authored-by: George Marshall <george.marshall@consensys.net> Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com> Co-authored-by: sophieqgu <37032128+sophieqgu@users.noreply.github.com> Co-authored-by: Wei Sun <wei.sun@consensys.net> Co-authored-by: ieow <4881057+ieow@users.noreply.github.com> Co-authored-by: himanshu <himanshuchawla2014@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: chloeYue <105063779+chloeYue@users.noreply.github.com> Co-authored-by: Bernardo Garces Chapero <bernardo.chapero@consensys.net> Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com> Co-authored-by: Brian August Nguyen <brianacnguyen@gmail.com> Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com> Co-authored-by: Jyoti Puri <jyotipuri@gmail.com> Co-authored-by: dan437 <80175477+dan437@users.noreply.github.com> Co-authored-by: Luis Taniça <matallui@gmail.com> Co-authored-by: Alejandro Garcia <alejandro.garcia@consensys.net> Co-authored-by: chloeYue <chloe.gao@consensys.net>
…ons in E2E CI (#27352) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> **Problem** All iOS E2E tests were failing with: main-qa-MetaMask.app is missing its bundle executable at "main-qa-MetaMask.app/MetaMask" Two issues in the artifact upload/download pipeline: 1. Case mismatch — Xcode on the case-insensitive build runner stored the binary as metamask (lowercase) while CFBundleExecutable in Info.plist declared it as MetaMask. actions/upload-artifact packaged the file under its actual on-disk name. xcrun simctl install on the test runner validates the bundle with a case-sensitive directory lookup, found no entry named MetaMask, and reported it as missing. 2. Permissions stripped — actions/upload-artifact does not preserve execute bits when creating the ZIP, so the binary arrived on the test runner as -rw-r--r-- instead of -rwxr-xr-x. Fix - Before upload (build-ios-e2e.yml): read CFBundleExecutable from Info.plist, locate the binary case-insensitively, rename to the correct case via a two-step move (required on case-insensitive APFS), then chmod +x - After download (run-e2e-workflow.yml): chmod +x as a safety net, with the same case-fix logic - Repack path (scripts/repack.js): chmod 755 on the repacked binary so the cache-hit code path is also covered ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches iOS E2E build/test workflows and cached artifact handling; missteps could break CI pipelines or increase rebuild frequency, but changes are localized to automation scripts. > > **Overview** > Improves iOS E2E artifact reliability by **normalizing the app bundle executable name and permissions** before upload and again after download, preventing `simctl install` failures due to case-mismatched binaries and stripped execute bits. > > Updates iOS build caching by introducing `IOS_APP_CACHE_VERSION` in cache keys (plus a centralized `XCODE_CACHE_VERSION` env), and hardens `scripts/repack.js` to verify the repacked `.app` contains the expected bundle executable and to restore its execute permissions, failing fast if `@expo/repack-app` drops the binary. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 750b422. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->
## **Description**
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->
Filling PR descriptions thoroughly seems tedious and time-consuming,
which often results in incomplete templates, missing changelog entries,
or skipped manual testing steps.
By giving AI coding agents structured skills for each part of the PR
workflow, developers can generate complete, standards-compliant PR
descriptions with minimal effort — removing friction and making it easy
to do the right thing every time.
This PR adds a comprehensive suite of agent skills in
`.agents/skills/pr-*/SKILL.md` that provide step-by-step instructions
for:
- **`pr-title`** — generate conventional commit PR titles from diff
analysis
- **`pr-description`** — orchestrate full PR description generation
following the repo template
- **`pr-changelog`** — determine user-facing impact and write CHANGELOG
entries
- **`pr-issue-search`** — find related GitHub issues or Jira tickets
from branch name, commits, or keyword search
- **`pr-manual-testing`** — generate Gherkin-format manual testing
scenarios from code changes
- **`pr-readiness-check`** — scan branch diff for missing tests, JSDoc,
or guideline violations
- **`pr-codeowners`** — identify code owners and map them to Slack group
handles
- **`pr-create`** — validate preconditions, generate description, create
draft PR, and produce Slack review request message
- **`pr-review-queue`** — add PRs to the MetaMask project board with
priority and date fields
Each skill is self-contained and composable — `pr-create` and
`pr-description` orchestrate the others as sub-skills.
## **Changelog**
<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`
If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`
(This helps the Release Engineer do their job more quickly and
accurately)
-->
CHANGELOG entry: null
## **Related issues**
Refs: MCWP-392
## **Manual testing steps**
```gherkin
Feature: AI agent PR workflow skills
Scenario: agent uses pr-create skill to open a draft PR
Given I am on a feature branch with committed changes
And the branch is pushed to origin
When an AI agent invokes the pr-create skill
Then a draft PR should be created on GitHub
And the PR description should follow the repository template
And the PR title should follow conventional commit format
```
## **Screenshots/Recordings**
<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->
### **Before**
N/A
### **After**
This PR is generated using the new skills suite form the PR itself
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- Generated with the help of the pr-description AI skill -->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk because this PR only adds new markdown-based agent
instructions and does not change application or CI/runtime behavior.
>
> **Overview**
> Introduces a new `.agents/skills/pr-*` documentation suite that
defines repeatable agent workflows for PR tasks: generating
`pr-title`/`pr-description`, producing a `CHANGELOG entry`, finding
related issues, writing Gherkin manual testing steps, running a
non-blocking readiness scan, mapping changed files to CODEOWNERS/Slack
handles, creating draft PRs, and adding PRs to the MetaMask review queue
project.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f860fc8. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…et (#27317) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Updates the Predict Unavailable bottom sheet to use the shared `HeaderCompactStandard` component instead of `BottomSheetHeader`, aligning with patterns used elsewhere. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/issues?jql=issueKey%20in%20(DSYS-555%2CDSYS-556%2CDSYS-557%2CDSYS-558%2CDSYS-559)&selectedIssue=DSYS-559 ## **Manual testing steps** ```gherkin Feature: Predict headers Scenario: Predict Unavailable sheet shows HeaderCompactStandard Given the app is open and Predict is available When Predict Unavailable bottom sheet is shown (e.g. when Predict is unavailable in region) Then the sheet header shows HeaderCompactStandard with title and close button And content and footer padding look correct ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="1290" height="2796" alt="Simulator Screenshot - iPhone 15 Pro Max - 2026-03-10 at 16 20 57" src="https://github.com/user-attachments/assets/7a47b69b-b54d-45b3-ada2-96c01c4f7aa3" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk UI refactor that swaps the bottom-sheet header component and tweaks spacing/text color, with no changes to data flow or business logic. > > **Overview** > Updates the Predict Unavailable bottom sheet to use the shared `HeaderCompactStandard` header (title + close) instead of `BottomSheetHeader`, aligning the sheet with newer header patterns. > > Also tweaks layout styling by adjusting horizontal padding on the description and footer and changing the description text color to `text-alternative`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e34e35b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Disable slide-to-dismiss behavior of swaps keypad to prevent potential double triggers of keypad keys due to bottom sheet dismissal gesture handler event. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: disable slide-to-dismiss behavior of swaps keypad ## **Related issues** Fixes: #26746 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes bottom-sheet gesture behavior for the swap/bridge keypad, which could affect how users dismiss the keypad and interact with inputs. Test updates reduce flakiness but rely on mocked bridge status responses and new timeouts that could mask regressions. > > **Overview** > Disables the `SwapsKeypad` slide/pan interaction by setting `BottomSheetDialog` `isInteractable={false}` to prevent gesture-handler double-firing of keypad button presses. > > Updates `SwapsKeypad` unit tests to capture and assert the `BottomSheetDialog` configuration, and adjusts bridge smoke-test stability by replacing a fixed delay with visibility assertions, adding confirmed-status verification, and mocking `getTxStatus` to return a complete bridge status response. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0724794. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Davide Brocchetto <davide.brocchetto@consensys.net>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** Fixes a bug where the max button was no longer showing on select networks. <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: #27381 ## **Manual testing steps** ```gherkin Feature: swap max button Scenario: user is using the swaps experience Given the chain they are on supports gasless When user selects tokens Then the max button should be visible ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes the gating logic for showing the Bridge/Swap “Max” option for native assets, so regressions could hide/show the button on certain networks depending on `gasIncluded`/`gasIncluded7702` selector outputs. > > **Overview** > Updates `useShouldRenderMaxOption` to **stop depending on Smart Transactions/send-bundle support and quote sponsorship** and instead show the Max option for native assets when `selectGasIncludedQuoteParams` indicates `gasIncluded` or `gasIncluded7702`. > > Refactors the corresponding hook tests to mock the new selector shape and to cover gas-included vs 7702-enabled vs disabled scenarios (including non‑EVM native tokens), removing the old STX/send-bundle assertions. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e2b4a06. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Introduced changes: - Permissions: New adapter method `ensurePermissions()` is called before transport checks in `retryEnsureDeviceReady`. And adds Android permission handling (Bluetooth on Android 12+, location on older Android). - Disconnect: Ledger BLE teardown uses `TransportBLE.disconnectDevice(deviceId)` instead of `transport.close()` for immediate disconnect. Cancelling “awaiting confirmation” also triggers a best-effort adapter disconnect. ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MUL-1580 ## **Manual testing steps** no manual testing steps ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes affect BLE connection lifecycle and Android permission prompting, which can alter user flow and connection stability; coverage is included but behavior depends on platform permission APIs and device/OS quirks. > > **Overview** > Improves the hardware-wallet connection retry path by introducing a new `HardwareWalletAdapter.ensurePermissions()` contract and calling it before transport checks in `retryEnsureDeviceReady`, aborting the retry if the user must be redirected to OS Settings. > > For Ledger BLE, adds Android permission prompting (Android 12+ Bluetooth permissions, older Android location permission) and updates transport teardown to prefer `TransportBLE.disconnectDevice(deviceId)` over `transport.close()` to force immediate disconnects; the awaiting-confirmation cancel path now also triggers a best-effort adapter disconnect. Tests/mocks are updated accordingly (Ledger adapter, provider, non-hardware adapter). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 2a94bd7. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** 1. **What is the reason for the change?** The redesigned homepage needs a dedicated **Cash** section as the first section, surfacing mUSD (MetaMask USD) and guiding users to convert stablecoins and claim bonuses. 2. **What is the improvement/solution?** - **Cash section (homepage):** When mUSD conversion is enabled and user is geo-eligible, the first section is **"mUSD"**. It shows aggregated mUSD balance (Linea + Ethereum), annualized bonus copy (e.g. "Get 3% annualized bonus…" with the percentage in green), and a "Claim bonus" CTA on the row when a bonus is claimable. Tapping the section header navigates to the Cash token list. When the user has no mUSD, the section shows a **Get mUSD** empty state: the same annualized copy, a tappable mUSD token row that navigates to Token Details (Mainnet mUSD, same destination as trending tokens), and a "Get mUSD" button that routes to the Buy flow (when mUSD is buyable) or the Convert flow (when the user has convertible stablecoins e.g. USDC). - **Cash token list screen:** New full-view screen (`CashTokensFullView`) that shows only mUSD positions across supported networks (Ethereum Mainnet, Linea). When the user has no mUSD, the screen renders the same Get mUSD empty state (handled by `CashTokensFullView` via `useMusdBalance`); when the user has mUSD, it renders `Tokens` with `showOnlyMusd`. Same network filter as the main token list; no add-token or sort. No mUSD-specific empty-state logic inside `Tokens`. - **mUSD isolation:** mUSD is removed from the main Tokens section and from the generic full token list; it appears only in the Cash section and Cash full view. - **Implementation details:** `Tokens` supports a `showOnlyMusd` prop (filter list to mUSD, hide add/sort in control bar); `TokenListControlBar` supports `showAddToken` and `hideSort`. Empty state component `CashGetMusdEmptyState` is used on the homepage (in `CashSection`) and in `CashTokensFullView`; token row uses `NavigationService` to navigate to Token Details. New route `CASH_TOKENS_FULL_VIEW` and screen registration. Uses design-system components. Cash section does not expose a refresh ref (no-op removed). ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: Added a Cash section on the homepage that shows aggregated mUSD balance, annualized bonus copy for stablecoin holders, and a dedicated Cash token list view with network filter. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-527 ## **Manual testing steps** ```gherkin Feature: Homepage Cash section and Cash token list Scenario: User with mUSD conversion enabled and geo-eligible sees Cash section first Given the user has mUSD conversion feature enabled and is in an eligible region When the user opens the redesigned homepage Then the Cash section appears as the first section with title "Cash" And if the user has convertible stablecoins, the annualized bonus copy is shown (e.g. "Get 3% annualized bonus...") And if the user has mUSD balance, the aggregated mUSD row is shown with balance and optional "Claim bonus" Scenario: User navigates to Cash token list from section header Given the user is on the homepage with Cash section visible When the user taps the Cash section header (or the ">" affordance) Then the app navigates to the Cash token list screen And the screen shows only mUSD positions (per network) or the cash empty state when none And the network filter is visible and works; add-token and sort buttons are not shown Scenario: User with network filter applied sees mUSD when opening Cash list Given the user has a network filter applied (e.g. single network) and has mUSD on that network When the user opens the Cash token list from the homepage Then mUSD positions for the enabled network(s) are shown And the user can change the network filter from the control bar ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** https://github.com/user-attachments/assets/ed532349-cfcc-4495-9b38-6e97fbaec30f <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds new navigation routes and conditional token filtering (including excluding mUSD from main lists) gated by feature flags/geo eligibility, which could affect token visibility and analytics. Also changes fiat formatting to use `currencyDisplay: 'narrowSymbol'`, which may alter currency rendering across the app. > > **Overview** > Introduces a new **Cash (mUSD)** surface: a `CashSection` is added as the first homepage section when mUSD conversion is enabled and geo-eligible, showing either an aggregated mUSD row (with optional *Claim bonus*) or a *Get mUSD* empty state that deep-links to mUSD details and routes users into buy/convert flows with new `home_cash_section` analytics location. > > Adds a dedicated `CashTokensFullView` route/screen and extends `Tokens`/`TokenListControlBar` to support an mUSD-only list (`showOnlyMusd`) that hides add-token/sort and uses cash-specific empty state messaging; when the Cash section is rendered, mUSD is filtered out of the main tokens lists (including popular tokens) to avoid duplication. > > Updates mUSD-related token list items to show a non-clickable green `"3% bonus"` label for mUSD when no claimable reward exists (only when conversion + geo eligibility are true), expands/adjusts unit tests and snapshots accordingly, and tweaks `formatFiat` to prefer `Intl` narrow currency symbols. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit cc3ad61. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Pedro Pablo Aste Kompen <wachunei@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )