Skip to content

[pull] main from MetaMask:main#410

Merged
pull[bot] merged 5 commits into
Reality2byte:mainfrom
MetaMask:main
Dec 15, 2025
Merged

[pull] main from MetaMask:main#410
pull[bot] merged 5 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Dec 15, 2025

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 : )

brianacnguyen and others added 5 commits December 15, 2025 06:58
## **Description**

This PR refactors the `HeaderBase` component to use
`@metamask/design-system-react-native` components and Tailwind CSS
styling.

**Reason for change:**
- The existing `HeaderBase` component uses custom StyleSheet-based
styling which doesn't align with the design system migration goals
- The component API could be simplified for common use cases like adding
back/close buttons

**Improvements:**
- Migrates to design system components (`Box`, `Text`, `ButtonIcon`) and
Tailwind CSS (`twClassName`)
- Adds new simplified APIs: `startButtonIconProps` and
`endButtonIconProps[]` for common icon button use cases without needing
to create custom accessories
- Adds `twClassName` prop for Tailwind-based customization
- Adds optional `testID` prop for better test flexibility
- Removes `HeaderBase.styles.ts` in favor of inline Tailwind-based
layout
- Updates text variants to use design system variants
(`HeadingSm`/`HeadingLg`)
- Re-exports test IDs and types from `index.ts` for easier imports

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: HeaderBase component

  Scenario: user views a header with Compact variant (default)
    Given the app is open
    When user navigates to a screen using HeaderBase with Compact variant
    Then the title should be center-aligned with HeadingSm text

  Scenario: user views a header with Display variant
    Given the app is open
    When user navigates to a screen using HeaderBase with Display variant
    Then the title should be left-aligned with HeadingLg text

  Scenario: user taps header icon buttons
    Given a screen has HeaderBase with startButtonIconProps and endButtonIconProps
    When user taps the back icon
    Then the associated onPress handler should be called
```

## **Screenshots/Recordings**
### **Before**

<!-- [screenshots/recordings] -->

### **After**

https://github.com/user-attachments/assets/c99e5a85-c96e-48a2-b245-0205480f413c

Existing usages is still functional

https://github.com/user-attachments/assets/4cffee2c-9fb5-4a50-a459-1c4062eec004

<!-- [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]
> Refactors `HeaderBase` to use design-system components with Tailwind
styling, adds simplified icon-button APIs, removes legacy styles, and
updates tests/snapshots and usages across the app.
> 
> - **Component Library — HeaderBase**:
> - Migrate to `@metamask/design-system-react-native` (`Box`, `Text`,
`ButtonIcon`) and Tailwind via `twClassName`.
> - Add `startButtonIconProps` and `endButtonIconProps[]`; prioritize
custom accessories when both provided.
> - Add `testID` and `twClassName` props; re-export test IDs and types
from `index.ts`.
> - Map variants to design-system text (`HeadingSm`/`HeadingLg`); remove
`HeaderBase.styles.ts` in favor of inline Tailwind.
> - Implement equal-width accessory wrappers for centered titles;
support multiple end buttons (reversed render order).
> - **Stories/Docs**:
> - Rewrite stories showcasing variants, Tailwind usage, button-prop
variants, and custom children.
>   - Update README with new props, usage, and defaults.
> - **Tests**:
> - Overhaul `HeaderBase.test.tsx` to new API/behavior; remove obsolete
alignment tests in `BottomSheetHeader`.
> - Update mocks for Tailwind and design-system variants; export test
IDs for easier querying.
> - **Consumers/Styling**:
> - Apply `twClassName="h-auto"` or header tweaks in `Navbar`,
`TokensFullView`, `UpdateNeeded`, and clean up redundant header styles.
> - **Snapshots**:
> - Widespread snapshot updates reflecting new layout/typography
(center/left alignment, `height: 48`, padding separation, fontWeight
700, flex wrappers).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b995e9e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…3771)

## **Description**
It updates the
[previous](#23364)
GitHub workflow file with these things:
- Cursor CLI
- Creating a GitHub comment with a Cursor response

When there is a new issue that's either (sev1 or sev2), it's assigned to
the `team-confirmations` and it's not from an external contributor, it
will trigger a Cursor issue analysis.

## **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**



## **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]
> Updates the issue-analysis workflow to run Cursor CLI on qualifying
issues with stricter label gating, a read-only permissions allowlist,
safe data handling, and automatic posting of a formatted analysis
comment; also cleans up the prompt template.
> 
> - **GitHub Actions Workflow
(`.github/workflows/cursor-issue-analysis.yml`)**:
> - **Trigger/Gating**: Adds exclusion for `external-contributor`;
retains `team-confirmations` and (`Sev1-high` or `Sev2-normal`).
> - **Idempotency**: Checks for existing comment containing `## Cursor
Analysis` before running.
>   - **Cursor Integration**:
> - Configures strict `.cursor/permissions.json` allow/deny lists
(read-only paths; deny secrets/shell/write).
> - Installs and invokes `cursor-agent` with a composed prompt and
security notice.
> - **Data Handling**: Fetches issue via `gh`, base64-encodes/decodes
payloads to pass between steps safely.
> - **Output**: Posts a formatted comment with header, caution note,
analysis body, and footer.
>   - **Misc**: Removes sparse checkout; renames steps for clarity.
> - **Prompt Template (`.github/cursorPrompts/issue-analysis.md`)**:
> - Removes leading `@cursor` directive; retains structured analysis
instructions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a56620f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@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**

It was found on main branch that quote details are empty for swaps on
Solana network. This does not exist on any RC or production release.
After investigating the issue we pinpointed the root cause to be
introduced in commit . For non-EVM chains (e.g., Solana),
destAsset.address is in raw format (e.g., "EPj...") or zero address for
native tokens, while destToken.address uses CAIP format e.g.,
"solana:.../token:EPj..."). We should use destAsset.assetId (CAIP
format) for comparison and for EVM chains, use the original address
comparison.

<!--
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: fixes empty quote card details issue when swapping on
Solana network

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-3580

## **Manual testing steps**

```gherkin
Ensure that details for quotes are filled correctly.
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<img width="487" height="920" alt="Screenshot 2025-12-11 at 1 42 30 PM"
src="https://github.com/user-attachments/assets/79528e5c-fa7f-4835-b389-962e060acb08"
/>

<!-- [screenshots/recordings] -->

### **After**
<img width="487" height="920" alt="Screenshot 2025-12-11 at 2 00 27 PM"
src="https://github.com/user-attachments/assets/63d33ad5-9cf8-4260-8e98-366601451291"
/>

<!-- [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]
> Fixes Solana quote details by comparing non-EVM destination tokens via
CAIP `assetId` (with `isNonEvmChainId`) and updates tests to use
CAIP-formatted addresses.
> 
> - **Bridge Quote Data**:
> - Use `isNonEvmChainId` and compare non-EVM dest assets via CAIP
`destAsset.assetId` (fallback to `address`), keeping address comparison
for EVM.
> - Ensure `destTokenAmount` is computed only when selected dest token
matches the quote’s dest asset (prevents stale/incorrect decimals).
> - **Tests**:
> - Update Solana cases to use CAIP-formatted `destToken.address`
matching quote `assetId`.
> - Adjust expectations and comments; add coverage for validation flows
and unchanged loading/error states.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
27809dc. 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**
After profiling the mobile app I found out that the detectNfts function
triggers a call to the NFTs API in a loop while the cursor/continuation
is defined. This is good when trying to detect all NFTs for a given user
but has two big limitations:
- What if the user has thousands of NFTs and navigates to the NFT view
and then goes back to a different view? These API calls will continue
running on the background endlessly without a reason
- What if we just want to fetch the first page of the NFTs? On mobile
when the user navigates to the NFTs tab we just display 18 NFTs, we just
need 1 single API call to fetch these and no endless loop to retrieve
the rest

This is why I have added firstPageOnly and signal options to
NftDetectionController.detectNfts() method to allow fetching only the
first page of NFTs and aborting detection operations in
[Core](MetaMask/core#7436)

Now I am making use of these new properties on Mobile which will reduce
number of API calls and improve the overall performance of the app for
user with a lot of NFTs

<!--
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: NFTs allow fetching one page and aborting fetch when
navigating away

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-2106 &
https://consensyssoftware.atlassian.net/browse/ASSETS-2105

## **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**
As you can see:
- When we navigate to the NFTs tab we fetch NFTs in a loop until there
is no cursor/continuation
- When we navigate away from the NFTs tab we keep fetching NFTs in a
loop until there is no cursor/continuation


https://github.com/user-attachments/assets/d089b358-8cbf-45bf-a71f-51e9f09ee402


### **After**

As you can see:
- When we navigate to the NFTs tab we make a single API call to the NFTs
API since we do not need more NFTs for that view
- When we navigate to the list of all NFTs we fetch NFTs in a loop until
the user navigates away or the is not cursor/continuation


https://github.com/user-attachments/assets/beb53910-0f2d-42cc-a5f0-a5837f91bd3f


<!-- [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]
> Makes NFT detection abortable with an AbortController and adds a
firstPageOnly option; full view triggers full detection on mount and
aborts on unmount, with tests updated accordingly.
> 
> - **Hooks (`useNftDetection`)**:
> - Add `AbortController` support and `abortDetection()` to cancel
in-progress detection.
> - Extend `detectNfts` to accept `firstPageOnly` (default `true`) and
pass `{ firstPageOnly, signal }` to `NftDetectionController.detectNfts`.
> - Abort previous detection before starting a new one; return updated
API `{ detectNfts, abortDetection, chainIdsToDetectNftsFor }`.
> - **UI (`UI/NftGrid/NftGrid.tsx`)**:
> - Replace focus-based trigger with mount-based `useEffect` for full
view: call `detectNfts(false)` and cleanup with `abortDetection` on
unmount.
>   - Wire `abortDetection` from `useNftDetection`.
> - **Tests**:
> - Update `useNftDetection.test.ts` to cover `firstPageOnly`
default/false, abort-on-reinvoke, and `abortDetection` behavior.
> - Update `NftGrid.test.tsx` to assert `detectNfts(false)` on full view
mount and `abortDetection` on unmount; ensure non-full view does not
call them.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f1e76cd. 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**
* feat: update optin metrics screen changes.
* Jira: https://consensyssoftware.atlassian.net/browse/SL-406
<!--
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: Update optin metrics screen ui changes

## **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**
<img width="319" height="722" alt="Screenshot 2025-12-15 at 3 17 13 PM"
src="https://github.com/user-attachments/assets/c7205498-a61a-458e-96c6-f91db02a5237"
/>

<!-- [screenshots/recordings] -->

### **After**
<img width="324" height="728" alt="Screenshot 2025-12-15 at 1 51 41 PM"
src="https://github.com/user-attachments/assets/e5f4adb0-b0a6-4ab6-b8b2-9b27293ff33f"
/>

<img width="270" height="570" alt="Screenshot 2025-12-15 at 6 20 54 PM"
src="https://github.com/user-attachments/assets/a69225f5-71c6-4460-aab4-1567d1dff499"
/>


<!-- [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]
> Updates the OptinMetrics screen layout (image above title, larger
illustration, right-aligned checkboxes, adjusted paddings) and changes
title copy to “Improve MetaMask.”
> 
> - **UI (OptinMetrics)**
> - **Layout**: Moves illustration above title; increases illustration
height to 180; adjusts container paddings (`paddingTop: 40`, split
action padding to `paddingHorizontal`/`paddingTop`).
> - **Checkbox Rows**: Switches to `justifyContent: space-between`;
places text on left and `Checkbox` on right; removes extra right margin;
maintains disabled styling logic.
> - **Button Bar**: Replaces uniform `padding` with `paddingHorizontal`
and `paddingTop`.
> - **Copy/i18n**
> - Updates `privacy_policy.description_title` from `Help improve
MetaMask` to `Improve MetaMask`.
> - **Tests**
> - Snapshot updates reflecting new layout, paddings, image size, and
title text.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7ec03fd. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Dec 15, 2025
@pull pull Bot added the ⤵️ pull label Dec 15, 2025
@pull pull Bot merged commit 45f5adf into Reality2byte:main Dec 15, 2025
2 of 36 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants