[pull] main from MetaMask:main#738
Merged
pull[bot] merged 13 commits intoReality2byte:mainfrom May 7, 2026
Merged
Conversation
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **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?
-->
OAuth client IDs for Google and Apple sign-in (`IOS_GOOGLE_CLIENT_ID`,
`IOS_GOOGLE_REDIRECT_URI`, `ANDROID_GOOGLE_CLIENT_ID`,
`ANDROID_GOOGLE_SERVER_CLIENT_ID`, `ANDROID_APPLE_CLIENT_ID`) were
previously sourced from `process.env`, requiring manual environment
variable configuration and risking misconfiguration across different
build types.
This PR moves those client IDs into the existing `OAUTH_CONFIG` object
in `config.ts`, keyed by build type (development, main_prod, main_uat,
main_dev, flask_prod, flask_uat, flask_dev). The constants in
`constants.ts` now read from `CURRENT_OAUTH_CONFIG` instead of
`process.env`, ensuring the correct client IDs are automatically
selected based on the build type. The corresponding environment variable
entries have been removed from `.js.env.example`.
## **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: Seedless onboarding OAuth login
Scenario: user signs in with Google on iOS
Given the app is built with a main production build type
When user taps "Sign in with Google" during onboarding
Then the Google OAuth flow uses the correct production client ID
And the user is authenticated successfully
Scenario: user signs in with Google on Android
Given the app is built with a main production build type
When user taps "Sign in with Google" during onboarding
Then the Google OAuth flow uses the correct production server client ID
And the user is authenticated successfully
Scenario: user signs in with Apple on Android
Given the app is built with a main production build type
When user taps "Sign in with Apple" during onboarding
Then the Apple OAuth flow uses the correct production Apple client ID
And the user is authenticated successfully
```
## **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**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] 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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] 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 OAuth configuration used for Google/Apple login; incorrect
client IDs/redirect URIs could break authentication in specific build
targets despite being mostly a config refactor.
>
> **Overview**
> OAuth client IDs/redirect URIs are now **defined per build type** in
`OAuthLoginHandlers/config.ts` and consumed via `CURRENT_OAUTH_CONFIG`
in `constants.ts`, instead of being read from `process.env`.
>
> The example env file removes the seedless-onboarding client ID
entries, and unit tests are updated to assert against
`OAUTH_CONFIG.main_prod` values for Android and legacy iOS Google config
selection.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fd46114. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**
The iOS production build in `build.yml` runs `pod install` without
caching `~/.cocoapods/repos` (the CocoaPods specs repository). Every run
downloads the full specs catalog from CDN, taking ~1m 36s.
This PR adds an `actions/cache@v4` step before `pod install` that caches
`~/.cocoapods/repos` keyed on `ios/Podfile.lock`. On cache hit, `pod
install` resolves specs locally instead of fetching from CDN. Uses
`continue-on-error: true` so cache failures never block the build.
This matches the existing pattern in
`.github/actions/setup-e2e-env/action.yml` (lines 382-391).
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: MCWP-574
## **Manual testing steps**
```gherkin
Feature: CocoaPods specs caching in iOS production build
Scenario: First run populates the cache (cache miss)
Given a production iOS build is triggered via workflow_dispatch
And no prior CocoaPods specs cache exists for the current Podfile.lock
When the "Restore CocoaPods specs cache (iOS)" step runs
Then the step logs show "Cache not found"
And "Install CocoaPods dependencies (iOS)" completes successfully at baseline timing (~1m 36s)
Scenario: Subsequent run restores the cache (cache hit)
Given a production iOS build is triggered via workflow_dispatch
And a CocoaPods specs cache exists from a previous run
When the "Restore CocoaPods specs cache (iOS)" step runs
Then the step logs show "Cache restored"
And "Install CocoaPods dependencies (iOS)" completes faster (~30s-1m less)
And the build produces a valid IPA artifact
Scenario: Cache failure does not block the build
Given the cache action encounters an error (network issue, quota exceeded)
When the "Restore CocoaPods specs cache (iOS)" step fails
Then the step is marked as successful due to continue-on-error: true
And "Install CocoaPods dependencies (iOS)" proceeds normally with a full CDN fetch
```
## **Screenshots/Recordings**
N/A - CI workflow change only, no UI impact.
### **Before**
### **After**
## **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.
## **Description**
The `prepare` and `emit-build-metadata` jobs in `build.yml` use
`fetch-depth: 0` (full git history clone), which takes ~1m 10s each
(median, n=21). Neither job performs any git history operations:
- `prepare`: reads `builds.yml` via `fs.readFileSync` and runs
`validate-build-config.js` (zero git commands)
- `emit-build-metadata`: runs `git rev-parse HEAD` (works on shallow
clones) and `get-build-metadata.sh` which only reads files (zero git
commands)
Removing `fetch-depth: 0` defaults to `fetch-depth: 1` (shallow clone),
reducing checkout from ~70s to ~10-15s per job.
**Expected saving:** ~1m 50s - 2m 10s per pipeline run across both jobs.
Also eliminates a tail-risk outlier where `emit-build-metadata` checkout
took 6m 45s.
Part of MCWP-574 (pipeline optimization series: PR 3 of 4).
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: MCWP-574
## **Manual testing steps**
```gherkin
Feature: Shallow clone in build pipeline
Scenario: prepare job completes with shallow clone
Given a production build is triggered via workflow_dispatch on build.yml
And skip_version_bump is true
When the prepare job runs
Then the actions/checkout step completes in ~10-15s (down from ~70s)
And the prepare job outputs are identical to a full-clone run
Scenario: emit-build-metadata job completes with shallow clone
Given a production build completes successfully
When the emit-build-metadata job runs
Then the actions/checkout step completes in ~10-15s
And built_commit_sha, semantic_version, and version codes are output correctly
Scenario: version-bump commit ref works with shallow clone
Given a production build is triggered with skip_version_bump false
When the prepare job checks out the version-bump commit hash
Then actions/checkout fetches the specific commit successfully
And the prepare job completes without errors
```
## **Screenshots/Recordings**
### **Before**
Not applicable (CI pipeline change, no UI).
### **After**
Not applicable (CI pipeline change, no UI).
## **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
- [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.
<!--
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 adds **component view tests (CVT)** for flows that were
previously covered by **smoke E2E** only, and **skips** those E2E cases
(eventually delete them). Smoke specs keep the original test bodies and
point to the CV file with `// Moved to cv tests (...)`.
Example: In network abstraction shard 1 we see a 4m reduction time
(android).
### E2E → component view test mapping
| File | Test Name | QA Comment | CV test file |
| --- | --- | --- | --- |
| view-defi-details.spec.ts | view DeFi position details | just checking
some data in the screen |
`app/components/UI/DeFiPositions/DeFiProtocolPositionDetails.view.test.tsx`
|
| view-market-insights.spec.ts | displays market insights content and
navigates to swap | |
`app/components/UI/MarketInsights/Views/MarketInsightsView/MarketInsightsView.view.test.tsx`
|
| view-market-insights.spec.ts | does not display entry card when API
returns no data | |
`app/components/UI/TokenDetails/components/AssetOverviewContent.view.test.tsx`
|
| view-market-insights.spec.ts | does not display entry card when
feature flag is disabled | |
`app/components/UI/TokenDetails/components/AssetOverviewContent.view.test.tsx`
|
| view-market-insights.spec.ts | navigates to buy screen when tapping
Buy button | |
`app/components/UI/MarketInsights/Views/MarketInsightsView/MarketInsightsView.view.test.tsx`
|
| view-market-insights.spec.ts | can tap thumbs up feedback button | |
`app/components/UI/MarketInsights/Views/MarketInsightsView/MarketInsightsView.view.test.tsx`
|
| send-btc-token.spec.ts | shows insufficient funds | This only does
validation on the input |
`app/components/Views/confirmations/components/send/send.non-evm.view.test.tsx`
|
| send-tron-token.spec.ts | shows insufficient funds | This only does
validation on the input |
`app/components/Views/confirmations/components/send/send.non-evm.view.test.tsx`
|
| send-erc20-token.spec.ts | should send USDC amount 50% to an address |
CV tests will handle these combinations |
`app/components/Views/confirmations/components/send/send.view.test.tsx`
|
| send-erc20-token.spec.ts | should send USDC send max to an address |
CV tests will handle these combinations |
`app/components/Views/confirmations/components/send/send.view.test.tsx`
|
| send-native-token.spec.ts | should send ETH to an address | PARTIALLY:
We should only cover ETH send, no need to cover 50% and Max |
`app/components/Views/confirmations/components/send/send.view.test.tsx`
|
| send-solana-token.spec.ts | should send solana to an address | This is
not actually sending anything, just checking that the text matches |
`app/components/Views/confirmations/components/send/send.non-evm.view.test.tsx`
|
| alert-system.spec.ts | should sign typed message | Moved to yes as per
team review |
`app/components/Views/confirmations/components/alert-banner/alert-system-typed-sign-blockaid.view.test.tsx`
|
| alert-system.spec.ts | should show security alert for malicious
request, acknowledge and confirm the signature | Moved to yes as per
team review |
`app/components/Views/confirmations/components/alert-banner/alert-system-typed-sign-blockaid.view.test.tsx`
|
| alert-system.spec.ts | should show security alert for error when
validating request fails | |
`app/components/Views/confirmations/components/alert-banner/alert-system-security-failed.view.test.tsx`
|
| alert-system.spec.ts | should show mismatch field alert, click the
alert, acknowledge and confirm the signature | As long as the component
is the same we can do this via CV test |
`app/components/Views/confirmations/components/alert-banner/alert-system-siwe-inline-mismatch.view.test.tsx`
|
| gas-fee-tokens-eip-7702-sponsored.spec.ts | fails transaction if error
occurs on API | |
`app/components/Views/confirmations/components/activity/eip-7702-sponsored-relay-api-failure.view.test.tsx`
|
| enable-notifications-after-onboarding.spec.ts | should enable
notifications and view feature announcements and wallet notifications |
Test is not doing what its title implies; skipped pending owner
discussion |
`app/components/Views/Notifications/NotificationsView.view.test.tsx` |
| notification-settings-flow.spec.ts | should enable notifications and
toggle feature announcements and account notifications | UI-only
validation, suitable for CV |
`app/components/Views/Settings/NotificationsSettings/NotificationsSettings.view.test.tsx`
|
| add-popular-networks.spec.ts | adds a popular network directly without
confirmation modal | This is not in prod anymore | *No matching
`*.view.test.tsx` on this branch* |
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes:
## **Manual testing steps**
```gherkin
Feature: N/A
Scenario: Automated tests only
Given developer checks out this branch
When they run yarn test:view for the touched view test files
Then tests pass
```
## **Screenshots/Recordings**
### **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
- [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.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **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 product risk since changes are test-only, but moderate test-suite
risk due to new integration-style view tests, new engine/nock mocks, and
`jest.config.view.js` forcing `IS_TEST=true` for feature-gated code
paths.
>
> **Overview**
> Adds **component-view (CV) test coverage** for several flows
previously validated only by smoke E2E: DeFi protocol position details,
token Market Insights (including entry card gating + swap/buy navigation
+ sources sheet + feedback), notifications list/details and notification
settings toggles, confirmation alert-system (typed-sign Blockaid
benign/malicious + SIWE domain mismatch inline + validation-failed
banner), and EIP-7702 sponsored send (failed activity status + “Paid by
MetaMask” fee row).
>
> Extends CV test infrastructure with new presets/helpers and mocks
(notifications state seeding, Market Insights navigation
renderer/preset, SnapController request interceptor, Sentinel
`/networks` nock mock), adds/normalizes several `testId` constants (send
50% button, confirmation transfer loader, status-icon tooltip), and sets
`process.env.IS_TEST=true` at view-jest config load time to satisfy
env-inlined feature gates.
>
> Removes or skips corresponding smoke E2E specs (or individual cases)
and updates fixtures/assertions (e.g., SIWE signer address) to align
with the new CV coverage.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
6098045. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
…liquidation and bonus messages (#29779) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** Turkish copy used `%{{variable}}` so a literal percent could sit before the interpolated value. **i18n-js** (used by `react-native-i18n`) treats `%` followed by `{` as the start of a `%{name}` placeholder, so `%{{...}}` was parsed as one invalid token and users saw messages like `[missing %{{apy}} value]` instead of the real value. All affected `tr.json` strings were updated to **`%%{variable}`**: a literal `%` plus the supported `%{variable}` interpolation, preserving “percent before number” wording while matching the same interpolation keys the app already passes (`apy`, `percentage`, `fee`, `distance`, etc.). No application code changes. ## **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 Turkish strings that showed broken i18n placeholders when a percent sign appeared before an interpolated value. ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Turkish locale i18n placeholders Scenario: APY and bonus copy interpolate with a leading percent Given the app language is set to Türkçe (tr) And the user opens a surface that shows Money APY label, MetaMask Card APY bullet, earn/mUSD bonus copy, bridge fee disclaimer, swap slippage errors, or perps liquidation distance strings When those screens render Then no string should contain a substring like "[missing" or "value]" And percent-prefixed values should show as "%" immediately followed by the numeric or formatted value (e.g. "%4" for APY), not a raw placeholder 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] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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 translation-only change that adjusts placeholder formatting; main risk is minor copy/interpolation regressions if any key names are mismatched. > > **Overview** > Fixes broken Turkish (`tr.json`) interpolations where a leading percent sign caused i18n placeholders like `%{{percentage}}` to be parsed incorrectly. > > Updates affected strings (perps liquidation/fees, swap/bridge fee and slippage messages, earn/mUSD bonus and APY/cashback labels) to use `%%{...}` so the UI shows a literal `%` followed by the interpolated value. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4a6b57e. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** ### Problem Android E2E runs are crashing with `Error: kill EPERM` in the "Set up E2E environment" step ([example](https://github.com/MetaMask/metamask-mobile/actions/runs/25337405885/job/74288509502?pr=29670)). This was introduced by #29236, which wrapped `sudo apt-get` inside `nick-fields/retry` with `timeout_minutes: 3`. **Root cause:** When the 3-minute timeout fires, `nick-fields/retry` calls `process.kill()` on the child process. But `sudo apt-get` runs as **root** while the Cirrus runner process runs as **admin** — Node.js gets `EPERM` (permission denied) on the kill syscall. This is a [known upstream bug](nick-fields/retry#124) (open since Oct 2023, 11 upvotes, unpatched). **Why the timeout fires:** `DPkg::Lock::Timeout=120` means `apt-get` can legitimately wait up to 120s for the dpkg lock on each of the two `sudo` calls (`update` + `install`). With slow Ubuntu mirrors on top, total time can approach or exceed 180s (3 min), triggering the timeout. The 3-minute value was tightened from the original 5-minute design in a follow-up commit on #29236, which didn't account for the double lock-wait scenario. ### Fix 1. **Restore `timeout_minutes` from 3 to 5** — gives 300s per attempt. Even worst-case (120s lock on update + 120s lock on install + 30s actual install = 270s) fits with 30s headroom. `apt-get` resolves on its own (success or dpkg lock timeout error) before the retry timeout fires, so the `process.kill()` path — and the EPERM bug — is never hit. 2. **Add `retry_on: error`** — only retry when `apt-get` exits with a non-zero code (mirror desync, lock timeout), not when `nick-fields/retry`'s own timeout fires. A timeout-triggered retry would crash with EPERM anyway, so this avoids a wasted attempt. ### Timing analysis | Scenario | Duration | Fits in 5 min? | |----------|----------|----------------| | Happy path (no lock, fast mirror) | 5-15s | Yes (295s margin) | | Lock on one call + normal mirror | 120s + 15s = 135s | Yes (165s margin) | | Lock on both calls + slow mirror | 240s + 30s = 270s | Yes (30s margin) | | Lock on both + very slow mirror | 240s + 60s = 300s | Boundary — but this is extremely unlikely | ## **Changelog** CHANGELOG entry: null ## **Related issues** Refs: INFRA-3580 Fixes regression from #29236 ## **Manual testing steps** N/A — CI infrastructure fix. Validated by any Android E2E workflow run. The timeout increase is transparent in the happy path (apt-get takes 5-15s). ## **Screenshots/Recordings** ### **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 - [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. Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk CI-only change that adjusts retry behavior for Linux `apt-get` during Android E2E setup; primary impact is longer waits before failing and fewer timeout-triggered retries. > > **Overview** > Reduces flaky Android E2E setup failures by updating the `setup-e2e-env` composite action to **increase** the `nick-fields/retry` `apt-get` wrapper timeout from 3 to 5 minutes. > > The retry wrapper is also configured with `retry_on: error` so retries only happen on non-zero exits, avoiding retries triggered by the action's own timeout. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8bcc995. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Cursor <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## **Description**
This PR fixes token logo rendering for non-native assets when
`asset.image` is empty (the issue affecting mUSD/Money integration).
The `AssetLogo` component now:
- computes a fallback icon URL via `getAssetImageUrl` when the primary
image is missing,
- only attempts fallback generation for valid CAIP or strict-hex chain
IDs,
- passes `imageSource={{ uri: imageUri }}` so undefined URI values are
handled directly by `AvatarToken`.
It also adds unit tests to cover fallback behavior and unsupported
chain-id behavior.
## **Changelog**
CHANGELOG entry: fix: fixed token list items to use a fallback icon when
token image URLs are missing
## **Related issues**
Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-3156
## **Manual testing steps**
```gherkin
Feature: Token list item image fallback
Scenario: Token with missing image URL still shows an icon
Given a token list item where asset.image is empty
When the token list item renders
Then AssetLogo resolves and uses a fallback image URL for valid chain IDs
And the token icon is shown instead of an empty image
Scenario: Unsupported chain id does not crash icon rendering
Given a token list item where asset.image is empty and chainId is unsupported
When the token list item renders
Then AssetLogo does not attempt invalid fallback URL generation
And AvatarToken renders safely when uri is undefined
```
## **Screenshots/Recordings**
### **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
- [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.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **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_AGENT_PR_BODY_END -->
<div><a
href="https://cursor.com/agents/bc-9a3458e2-b19c-40ef-b02b-feb8b7c2fa93"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a
href="https://cursor.com/background-agent?bcId=bc-9a3458e2-b19c-40ef-b02b-feb8b7c2fa93"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
…res that were disabled due to feature flag updates (#29154) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. --> ## **Description** Brings Predict E2E test feature flag mocks into parity with production values. Two remote feature flag overrides in predict smoke tests diverged from production after a feature flag registry sync ([PR #28444](#28444)). This PR aligns the mocks: - **`exploreSectionsOrder`**: Replaced the explicit section ordering arrays with `{}` in 4 predict smoke specs. On production this flag is empty; the app falls back to hardcoded defaults which produce the same layout. The Homepage component does not consume this flag at all — it only affects TrendingView/Explore, which these tests don't exercise. - **`predictLiveSports`**: Added `'nba'` to the leagues list (now `['nfl', 'nba']`) to match production. This causes NBA markets (Spurs vs. Pelicans) to render via `PredictGameDetailsContent`, which uses a different cash-out button test ID (`predict-picks-cash-out-button-{positionId}`). Updated the `PredictDetailsPage` page object with a new `tapGameCashOutButton(positionId)` method and updated `predict-cash-out.spec.ts` to use it. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [MMQA-1711](https://consensyssoftware.atlassian.net/browse/MMQA-1711) ## **Manual testing steps** <!-- Gherkin scenarios for this change --> **Feature: Predict E2E prod parity** **Scenario: Cash out on NBA game market uses correct button** - Given the predict smoke tests use production-parity feature flag mocks - When the predict-cash-out test runs against Spurs vs. Pelicans - Then the test taps the game-details cash-out button (PredictPickItem testID) - And the cash-out flow completes successfully **Scenario: Predict tests work without explicit exploreSectionsOrder** - Given exploreSectionsOrder is set to `{}` in all predict smoke specs - When any predict smoke test runs (cash-out, open-position, geo-restriction, withdraw) - Then the Homepage renders with the default section order - And the test navigates to predictions by test ID without issue ## **Screenshots/Recordings** ### **Before** N/A — test-only changes, no UI impact. ### **After** N/A — test-only changes, no UI impact. ## **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. [MMQA-1711]: https://consensyssoftware.atlassian.net/browse/MMQA-1711?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Test-only changes that adjust feature-flag mocks and E2E selectors; low product risk, but could affect Predict smoke test stability if testIDs/position IDs drift. > > **Overview** > Aligns Predict E2E remote feature-flag mocks with current production defaults by removing the `predictLiveSports` override from `remoteFeatureFlagPredictEnabled`. > > Updates Predict smoke specs to interact with the *game-details* UI: adds a shared `SPURS_PELICANS_POSITION_ID`, introduces `PredictDetailsPage.tapGameCashOutButton(positionId)` and `tapGameBetYesButton()`, and switches cash-out/position-opening tests to use the new testIDs for NBA/game markets. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f452736. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## **Description** Adds the missing collection name field to the NFT details screen. The data already existed on `collectible.collection.name`, but the screen did not render it. ## **Changelog** CHANGELOG entry: fix: NFT details did not show the collection name ## **Related issues** Fixes: #29362 https://consensyssoftware.atlassian.net/browse/ASSETS-3125 ## **Manual testing steps** ```gherkin Feature: NFT details collection metadata Scenario: User views an NFT details page Given the user has imported NFTs from a collection When user opens the details screen for one NFT Then the screen displays the collection name in the Collection section ``` ## **Screenshots/Recordings** ### **Before** ### **After** <img width="318" height="102" alt="Screenshot 2026-05-07 at 10 49 53" src="https://github.com/user-attachments/assets/6e3bd63d-e2db-46ab-990f-2e6d9f5193b7" /> ## **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 - [ ] 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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-2131bb9a-ffff-464e-9da8-8a287e0d8b37"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-2131bb9a-ffff-464e-9da8-8a287e0d8b37"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **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: Updated money account deposit. ## **Related issues** Depends on: #29561 Depends on: MetaMask/core#8687 ## **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** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [ ] 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. #### Performance checks (if applicable) - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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 Money Account deposit transaction construction and confirmation re-encoding, which can affect on-chain calldata and Pay gating via `requiredAssets`, though it is still using a zero-amount placeholder by default. > > **Overview** > Adds a Money Account deposit initiation path that submits an `addTransactionBatch` for approve+deposit with a **zero-amount placeholder**, navigates to the `CustomAmount` confirmation screen, and declares Pay `requiredAssets` using a shared deposit-asset helper. > > Implements real `updateMoneyAccountDepositTokenAmount` re-encoding: converts the user-entered human amount to USDC base units, calls `previewDeposit` to compute `minimumMint` (with slippage), and returns updated calldata for the nested approve/deposit calls; it no-ops when vault config/provider is unavailable. > > Refactors deposit asset handling into `getMoneyAccountDepositAssetAddress` (currently hardcoded USDC), skips the `previewDeposit` RPC for 0 amounts, updates/extends unit tests and confirmation mocks, and bumps `@metamask/transaction-controller` to `65.1.0`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5ef8804. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Jyoti Puri <jyotipuri@gmail.com>
## **Description** INFRA-3592 Phase 0 — adds a `runner_provider` control input (`current` | `namespace`, default `current`) to the Phase 1-4 entry-point and reusable workflows, threads forwarding through every in-scope caller, and wraps each in-scope `runs-on:` in an additive ternary that selects between the existing runner and the matching `namespace-profile-*` label. **No job is migrated. No default is changed.** With `runner_provider: current` (the default on every existing trigger) every ternary collapses to its prior literal/expression, so behavior is byte-identical to `main`. The `namespace` branch is reachable only via manual `workflow_dispatch`. Branch is the long-lived working surface for Phases 1-4; do not merge. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: [INFRA-3592](https://consensyssoftware.atlassian.net/browse/INFRA-3592) (parent epic INFRA-3511) ## **Manual testing steps** ```gherkin Feature: runner_provider trial control plane Scenario: dispatch on the current default — byte-identical Given the trial branch namespace-runner-trial When user runs `gh workflow run ci.yml --ref namespace-runner-trial -f runner_provider=current` Then every job runs on its existing GitHub-hosted / Cirrus runner And required-check context names match origin/main exactly Scenario: dispatch on namespace — plumbing reaches Namespace Given the trial branch and the MetaMask Actions allowlist already updated When user runs `gh workflow run ci.yml --ref namespace-runner-trial -f runner_provider=namespace` Then jobs are picked up by the namespace-profile-metamask-* runner that maps to each existing class And end-to-end success is not required at Phase 0 — composite-action assumptions land in Phase 2-4 ``` ## **Verification evidence (already executed)** Both scenarios above were dispatched against this branch — results recorded: | Scenario | Run | Result | | --- | --- | --- | | `runner_provider=namespace` (Namespace path) | [25319648133](https://github.com/MetaMask/metamask-mobile/actions/runs/25319648133) | Linux, iOS, Android jobs all picked up by the matching `namespace-profile-metamask-*` runner; secrets resolved end-to-end (`secrets: inherit` flowing); job names + required-check contexts unchanged | | `runner_provider=current` (existing runners) | [25320925061](https://github.com/MetaMask/metamask-mobile/actions/runs/25320925061) | 0 Namespace instances spawned in the dispatch window; every job ran on its prior GitHub-hosted / Cirrus runner | | Implicit `current` via PR-trigger (no input) | [25174041735](https://github.com/MetaMask/metamask-mobile/actions/runs/25174041735), [25162883313](https://github.com/MetaMask/metamask-mobile/actions/runs/25162883313) | Both `pull_request` runs on the branch completed successfully on existing runners — proves the byte-identical contract holds without a manual dispatch | Required-check parity verified statically against the 3 contexts on `main`'s branch protection (`check-template-and-add-labels`, `Check all jobs pass`, `CLABot`) — none renamed in this diff. Detailed cross-reference in INFRA-3592 [comment 417866 §5](https://consensyssoftware.atlassian.net/browse/INFRA-3592). ## **Screenshots/Recordings** N/A — CI infrastructure PR, no UI surface. ## **Notes for reviewers** - 6 commits, organised so each is independently reviewable: actionlint label registration → `workflow_dispatch` inputs → `workflow_call` inputs → caller forwarding → `runs-on` ternary → placeholder→canonical-label replacement. - Phase 7 callers (`runway-*`, `nightly-build`, `build-and-upload-to-testflight`, `push-eas-update`, `build-rc-auto`) are intentionally **not** modified — they continue to call without forwarding, callees default to `current`. - Composite actions are inventoried only — Phase 2/3/4/5/7 own their migration. - `actionlint -config-file .github/actionlint.yaml` produces byte-identical output to `origin/main` (84 lines, exit 1 from pre-existing warnings only — no new findings introduced by this PR). - Inventories captured (composite actions, caller graph, secrets/environments, concurrency groups, required-check contexts) — full tables in INFRA-3592 [comment 417866](https://consensyssoftware.atlassian.net/browse/INFRA-3592). - Branch was rebased onto current `main` after a conflict with [#29431](#29431) (e2e label rename). Conflict resolution was mechanical — main's renamed jobs (swap-, stake-, money-) had `runner_provider:` re-applied; no semantic decision involved. ## **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). - [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 (`team-dev-ops`, `size-M`) #### Performance checks (if applicable) N/A — workflow YAML only, no app code. ## **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. [INFRA-3592]: https://consensyssoftware.atlassian.net/browse/INFRA-3592?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches many GitHub Actions workflows and `runs-on` expressions, so miswiring could break CI execution or route jobs to the wrong runner. Default behavior remains `current`, but the new `namespace` path changes execution environment when manually dispatched. > > **Overview** > Introduces a new `runner_provider` input (default `current`, optional `namespace`) across in-scope entrypoint and reusable workflows, and forwards it through callers. > > Updates `runs-on` in `ci.yml`, `build.yml`, `setup-node-modules.yml`, and E2E build/test workflows to conditionally select between existing GitHub-hosted/Cirrus runners and new `namespace-profile-metamask-*` runner labels. > > Registers the new `namespace-profile-*` labels in `.github/actionlint.yaml`, and adds `workflow_dispatch` inputs to enable manual trial runs using the namespace provider. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit fffcc88. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
In short: the template must be materially complete (not just section
titles
present), all status checks must be currently passing, and the only
expected
follow-up commits must be reviewer-driven.
-->
## **Description**
Wires 5 events for Whats Happening analytics:
Card Scrolled to View, emitted via `useViewportTracking` in
WhatsHappeningCard
Opened — emitted in `WhatsHappeningSection` on card press and View All
Viewed — emitted in `WhatsHappeningDetailView` on initial mount and on
each carousel scroll
Interaction — emitted in `TokenRow`
Closed — emitted in `WhatsHappeningDetailView` on back press
## **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**
<!--
Every checklist item must be consciously assessed before marking this PR
as
"Ready for review". A checked box means you deliberately considered that
responsibility, not that you literally performed every action listed.
Unchecked boxes are ambiguous: they are not an implicit "N/A" and they
are not
a silent "skip". See `docs/readme/ready-for-review.md` for the full
checklist
semantics.
-->
- [ ] 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.
#### Performance checks (if applicable)
- [ ] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **Pre-merge reviewer checklist**
<!--
Reviewer checklist items follow the same semantics as the author
checklist: an
unchecked box is ambiguous, a checked box means the reviewer consciously
assessed that responsibility. See `docs/readme/ready-for-review.md`.
-->
- [ ] 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 analytics instrumentation across the Whats Happening homepage
section and detail flow, including new component props and
scroll/visibility hooks that could subtly affect rendering or event
duplication if indices/items drift.
>
> **Overview**
> Adds a full set of **MetaMetrics Whats Happening** events (new
constants in `MetaMetrics.events.ts`) and wires them through the
homepage section and detail experience.
>
> Homepage now tracks `WHATS_HAPPENING_OPENED` with an `entry_point` for
both card taps and *View more*, and cards emit
`WHATS_HAPPENING_CARD_SCROLLED_TO_VIEW` via `useViewportTracking`
(introducing a required `cardIndex` prop).
>
> Detail view now tracks `WHATS_HAPPENING_VIEWED` once on initial mount
and again when the carousel settles on a new index, and tracks
`WHATS_HAPPENING_CLOSED` on back. Token/perps CTAs and source link
presses now emit `WHATS_HAPPENING_INTERACTION` with standardized
properties via the new shared helper `getWhatsHappeningEventProps` (plus
`interaction_type` and asset/source fields).
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9d3ed1a. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description** INFRA-3593 Phase 1 — adds Namespace Cache Volumes integration to the Linux CI jobs on the `namespace-runner-trial` branch. When `runner_provider: namespace` is dispatched, the 8 Linux CI jobs that install dependencies now: 1. Mount a Namespace Cache Volume via `nscloud-cache-action` covering `~/.cache/yarn`, `.metamask`, `node_modules`, `.yarn/cache`, and `.yarn/install-state.gz` 2. Skip `actions/setup-node` Yarn caching (set to empty string) to avoid duplicate network-backed cache traffic 3. Skip `actions/cache` for `node_modules` in `component-view-tests` and `merge-unit-and-component-view-tests` (Namespace cache already covers it) When `runner_provider: current` (the default on every existing trigger), all ternaries collapse to their prior values and behavior is byte-identical to the base branch. **No job is renamed. No default is changed.** This is an additive, opt-in change activated only via manual `workflow_dispatch` with `runner_provider: namespace`. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: INFRA-3593 (parent epic INFRA-3511) Refs: INFRA-3592 (Phase 0, PR #29557) ## **Manual testing steps** ```gherkin Feature: Namespace Cache Volumes on Linux CI Scenario: dispatch with namespace provider — cache volumes active Given the branch phase1-namespace-linux-cache When user runs `gh workflow run ci.yml --ref phase1-namespace-linux-cache -f runner_provider=namespace` Then all 8 Linux CI jobs with dependencies use nscloud-cache-action And actions/setup-node Yarn caching is disabled (no duplicate cache traffic) And all jobs pass across every matrix shard (unit-tests x10, component-view-tests x2, scripts x6) Scenario: dispatch with current provider — byte-identical to base Given the branch phase1-namespace-linux-cache When user runs `gh workflow run ci.yml --ref phase1-namespace-linux-cache -f runner_provider=current` Then nscloud-cache-action steps are skipped (if condition is false) And actions/setup-node uses cache: yarn as before And actions/cache for node_modules runs as before And all jobs pass on GitHub-hosted runners Scenario: implicit current via PR/push trigger Given a push or pull_request event (no workflow_dispatch) Then inputs.runner_provider is undefined/empty And all ternaries collapse to existing behavior ``` ## **Screenshots/Recordings** ### **Before** N/A ### **After** N/A — CI infrastructure PR, no UI surface. ## **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. #### Performance checks (if applicable) N/A — workflow YAML only, no app code. ## **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. Made with [Cursor](https://cursor.com) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches many GitHub Actions workflows to optionally switch runner labels and caching behavior, which could break CI execution or cause cache-related flakiness when enabled. Default behavior remains unchanged unless `runner_provider=namespace` is explicitly selected. > > **Overview** > Introduces a `runner_provider` input (with `workflow_dispatch` choices where relevant) to route jobs between existing runners and new `namespace-profile-*` runner labels across `ci.yml`, reusable build workflows, and E2E smoke/regression workflows. > > When `runner_provider=namespace`, Linux CI jobs that install dependencies mount Namespace cache volumes via `namespacelabs/nscloud-cache-action`, disable `actions/setup-node` Yarn caching, and skip `actions/cache`-based `node_modules` restores in coverage-merge/component-view jobs; Node memory limits are also reduced on Namespace runners. > > Updates `actionlint` configuration to allow the new Namespace runner profile labels. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 3a52111. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Jose Luque <jose.luque@consensys.net> Co-authored-by: José Manuel <6741785+jluque0101@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.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 : )