Skip to content

[pull] main from MetaMask:main#435

Merged
pull[bot] merged 7 commits into
Reality2byte:mainfrom
MetaMask:main
Jan 7, 2026
Merged

[pull] main from MetaMask:main#435
pull[bot] merged 7 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Jan 7, 2026

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

Battambang and others added 7 commits January 7, 2026 14:32
<!--
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?
-->

Enhances the gas fee sponsorship user experience by updating the tooltip
logo and content next to "network fee" to align with the other tooltip
logo in the swap quote card.

### Problem
There was a different tooltip logo for gas fees sponsored swaps in the
swap quote card.
The send transaction modal is missing the gas fees sponsored content
network fee tooltip.

### Solution
Implement a UI-level workaround that updates the tooltip logo next to
"network fee" in the swap quote card.
Add the the gas fees sponsored content network fee tooltip for send
transaction.

## **Changelog**

CHANGELOG entry: updated network fee tooltip for gas fees sponsored case

## **Related issues**

Fixes: null

## **Manual testing steps**

1. Go to the swap page.
2. Request a same chain swap quote on a chain eligible of gas fees
sponsored.
3. The quote response for network fees should display the correct
tooltip logo.
4. The send transaction network fee tooltip should display the specific
text for gas fees sponsored case.

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->
<img width="300" height="600" alt="Mobile before"
src="https://github.com/user-attachments/assets/fbb9cdef-f522-4a97-8cbb-b82ef65074d1"
/>



### **After**

<!-- [screenshots/recordings] -->
<img width="300" height="600" alt="Mobile after"
src="https://github.com/user-attachments/assets/7396b2e2-4934-435c-838c-33ae7f2a200f"
/>

<img width="300" height="600" alt="Monad send mob"
src="https://github.com/user-attachments/assets/8b531a43-eec9-4074-843a-543ab2646d59"
/>



## **Pre-merge author checklist**

- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/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-extension/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]
> Standardizes the “network fee” tooltip for sponsored gas cases.
> 
> - Bridge `QuoteDetailsCard`: sets tooltip `iconName` to `Info` for
`network_fee` when gas fees are sponsored.
> - Confirmations `gas-fee-details-row`: updates tooltip content to
`bridge.network_fee_info_content_sponsored`, injecting the native token
symbol (resolved via `selectNetworkConfigurationByChainId` with
`useNetworkInfo` fallback).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
49bf386. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

The getter `Engine.state` was missing the state of some controllers. It
has been updated to include everything, and a unit test has been added
to ensure we don't forget to add state to this again in the future.

There is no known user impact, we don't rely on this state to be present
right now. This was done to let us use this as a replacement for
`Engine.datamodel` later on.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

N/A

## **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]
> Ensures the `Engine.state` getter exposes a complete engine state and
guards access before initialization.
> 
> - Adds missing `GatorPermissionsController` and `SnapsRegistry` to
`Engine.state` in `Engine.ts`
> - Introduces tests in `Engine.test.ts` to assert:
>   - Accessing `Engine.state` before initialization throws an error
> - `Engine.state` includes all controllers that have non-empty `state`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f488d7a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
… details (#24277)

<!--
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 commit re-enables the test for claiming winnings through market
details, which was previously skipped due to blocking CI. The test is
now active and will run as part of the CI pipeline.

## **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: Claim Prediction Winnings
  As a user with winning prediction positions
  I want to claim my winnings from market details
  So that I can receive my earnings

  Background:
    Given the user is logged into the MetaMask app
    And the user has a winning prediction position
    And the user has a lost prediction position
    And the Predictions feature is enabled

  Scenario: Claim button is not visible on lost positions
    Given the user is on the Predictions tab
    When the user taps on a lost position
    Then the market details page should be visible
    And the Claim button should not be visible

  Scenario: Claim button is visible on winning positions
    Given the user is on the Predictions tab
    When the user taps on a winning position
    Then the market details page should be visible
    And the Claim button should be visible

  Scenario: Successfully claim winnings via market details
    Given the user is on the Predictions tab
    And the user has navigated to a winning position's details
    When the user taps the Claim Winnings button
    And the user confirms the claim transaction
    Then the Claim button should no longer be visible on the details page
    And the user should be returned to the wallet view
    And the Claim button should not be visible on the Predictions tab
    And all resolved positions should be removed from the UI
    And the balance should be updated to "$48.16"
```

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

- [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]
> **Scope**
> - Unskips `claim winnings via market details` E2E in
`e2e/specs/predict/predict-claim-positions.spec.ts` by changing
`it.skip` to `it`.
> 
> **What the test covers**
> - Claims winnings from a winning position’s details page, verifies
claim button visibility rules, applies post-claim mocks, and confirms UI
updates (no claim button, resolved positions removed, balance `$48.16`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0a3b29e. 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?
-->

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adjusts performance expectations and stabilizes balance detection to
reduce flaky runs.
> 
> - Raises/adjusts TimerHelper thresholds across performance specs
(login, swap, perps, predict, send, onboarding), especially higher
Android limits; minor async measure call cleanups
> - Onboarding/account tests now verify `SOL` visibility or use
`checkActiveAccount` instead of `ETH` token checks
> - Adds `WalletMainScreen.checkActiveAccount(name)`
> - Reworks `WalletMainScreen.waitForBalanceToStabilize()`:
> - iOS: skip stability loop; wait once for non-empty, non-$0.00 balance
> - Android: keep polling with improved element re-fetch,
`sameResultTimeout` reduced to 8s
> - Updates `Flows.importSRPFlow` timer thresholds and prediction modal
helpers; uses device-based account selection in perps test
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e968405. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
)

## **Description**

This PR fixes two related issues in the OTP Code screen for the Deposit
flow:

### Issue 1: Missing Localization Key

The `ResendButton` component was referencing a non-existent localization
key `deposit.otp_code.resend_error`, which would display the raw key
string to users instead of the intended error message.

**The correct key** that exists in `en.json` is
`deposit.otp_code.resend_code_error` with the value "Error resending
code."

### Issue 2: Test Not Capturing Error State

The test case "renders resend error snapshot when resend fails" was not
properly testing the error state. It was taking a snapshot immediately
after pressing the resend button, capturing the **cooldown state**
("Resend code in 30 seconds") instead of the **error state** ("Error
resending code.").

This happened because:
1. The test pressed the button but didn't await the async operation
2. The snapshot was taken before the
`mockSendUserOtp.mockRejectedValue()` promise rejection was processed
3. Therefore, the snapshot showed `resendButtonState === 'cooldown'`
instead of `resendButtonState === 'resendError'`

---

## **Detailed Changes**

### Fix 1: Localization Key (OtpCode.tsx)

[View
diff](https://github.com/MetaMask/metamask-mobile/pull/24264/files#diff-e9e9e4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4)

```diff
- text="deposit.otp_code.resend_error"
+ text="deposit.otp_code.resend_code_error"
```

### Fix 2: Test Case (OtpCode.test.tsx)

[View
diff](https://github.com/MetaMask/metamask-mobile/pull/24264/files)

```diff
  it('renders resend error snapshot when resend fails', async () => {
    mockSendUserOtp.mockRejectedValue(new Error('Failed to resend'));
    render(OtpCode);
    const resendButton = screen.getByText('Resend it');
-   fireEvent.press(resendButton);
+
+   await act(async () => {
+     fireEvent.press(resendButton);
+   });
+
+   await waitFor(() => {
+     expect(screen.getByText('Error resending code.')).toBeOnTheScreen();
+   });
+
    expect(screen.toJSON()).toMatchSnapshot();
  });
```

### Fix 3: Updated Snapshot

[View snapshot
diff](https://github.com/MetaMask/metamask-mobile/pull/24264/files)

The snapshot now correctly captures the error state UI:

```diff
-                               Resend code in 30 seconds
+                               Error resending code.
                              </Text>
+                             <TouchableOpacity
+                               onPress={[Function]}
+                             >
+                               <Text ...>
+                                 Contact support
+                               </Text>
+                             </TouchableOpacity>
```

---

## **Changelog**

CHANGELOG entry: Fixes a small localization key bug in the OTP code
screen for Buy (deposit)

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-2950 

## **Manual testing steps**

```gherkin
Feature: OTP Code Resend Error State

  Scenario: user sees error message when OTP resend fails
    Given user is on the OTP Code screen in the Deposit flow
    And the network request to resend OTP will fail

    When user taps "Resend it" button
    Then user sees "Error resending code." text
    And user sees "Contact support" link
```

## **Screenshots/Recordings**



### **Before**

<img width="400" alt="before"
src="https://github.com/user-attachments/assets/582a0942-c62f-4782-a536-1c6029676a34"
/>



### **After**

<img width="400" alt="after"
src="https://github.com/user-attachments/assets/96a47069-39f0-45cf-a573-4aee29bcb051"
/>

## **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]
> Resolves incorrect error messaging and ensures tests validate the
actual resend failure UI state.
> 
> - Update `OtpCode.tsx` to use existing i18n key
`deposit.otp_code.resend_code_error` for the resend failure state
> - Fix `OtpCode.test.tsx` by awaiting the async resend action (`act` +
`waitFor`) and asserting `"Error resending code."` before snapshot
> - Refresh snapshots to display the error message with the "Contact
support" link instead of the cooldown text
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1757cf9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR updates the headers in the receive flow to use the newer
`HeaderCenter` component from `component-library/components-temp`.

**What is the reason for the change?**
The `getAddressListNavbarOptions` function in `Navbar/index.js` was a
one-off navbar utility that duplicated functionality already available
in the `HeaderCenter` component.

**What is the improvement/solution?**
- Replaced `getAddressListNavbarOptions` with
`getHeaderCenterNavbarOptions` in `AddressList.tsx`
- Replaced `BottomSheetHeader` with `HeaderCenter` in
`ShareAddressQR.tsx`
- Removed the now-unused `getAddressListNavbarOptions` function and its
tests from `Navbar/index.js`

This consolidates header patterns and reduces code duplication by
leveraging the reusable `HeaderCenter` component.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
https://consensyssoftware.atlassian.net/browse/MDP-655?atlOrigin=eyJpIjoiNzhiOTE5OWVlN2NkNDIxZDhjMzI3MGJlYTQ4OTU2NDkiLCJwIjoiaiJ9

## **Manual testing steps**

```gherkin
Feature: Receive Flow Headers

  Scenario: user views the address list screen
    Given user is logged in and on the wallet home screen
    When user navigates to the receive flow and opens the address list
    Then the header should display with a back button and centered title
    And tapping the back button should navigate back

  Scenario: user views the share address QR sheet
    Given user is logged in and on the wallet home screen
    When user opens the share address QR bottom sheet
    Then the header should display with the account group and network name
    And tapping the back button should close the sheet
```

## **Screenshots/Recordings**

### **Before**

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

### **After**

https://github.com/user-attachments/assets/a01919a8-a560-4589-b06e-963a0b671668

<!-- [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]
> Modernizes Receive flow headers to use the shared `HeaderCenter`
pattern and removes a bespoke navbar util.
> 
> - AddressList: replaces `getAddressListNavbarOptions` with
`getHeaderCenterNavbarOptions`, sets `header` via
`navigation.setOptions`, and ensures back button uses
`AddressListIds.GO_BACK`
> - ShareAddressQR: swaps `BottomSheetHeader` for `HeaderCenter`, adds
back button `testID` via `ShareAddressQRIds.GO_BACK`
> - Navbar: removes `getAddressListNavbarOptions` and its tests
> - Tests: update AddressList and ShareAddressQR expectations for
`header` and back button testIDs; add `GO_BACK` selector in
`ShareAddressQR.selectors.ts`
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c9a8dae. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…24289)

<!--
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 fix prevents filtering of transactions with the "0x0" hash in the
activity view.

### Reason for change
mUSD conversions were being filtered out and hidden on the activity view
since they all have the 0x0 hash.

<!--
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: prevent filtering of transactions with 0x0 hash in
activity view

## **Related issues**

Fixes: [MUSD-181: MUSD conversions aren't appearing in activity
list](https://consensyssoftware.atlassian.net/browse/MUSD-181)

## **Manual testing steps**

```gherkin
Feature: Transaction history preserves distinct outgoing transactions with placeholder hashes

  Scenario: user views transaction history with multiple outgoing transactions that have a placeholder hash
    Given user has multiple outgoing transactions recorded in activity with a placeholder hash value ("0x0")

    When user opens the activity / transaction history list
    Then each of those outgoing transactions is displayed as a separate entry
```

## **Screenshots/Recordings**

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

### **Before**

<!-- [screenshots/recordings] -->
Single mUSD Conversion shown in activity list despite user performing
multiple conversions
<img width="505" height="1012" alt="image"
src="https://github.com/user-attachments/assets/430583c3-af24-407c-91f2-dbef62b52e93"
/>

### **After**

<!-- [screenshots/recordings] -->
All mUSD Conversions displayed in activity list
<img width="505" height="1012" alt="image"
src="https://github.com/user-attachments/assets/f027d5f8-9153-4c26-8923-741c575f0de7"
/>

## **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]
> Prevents unintended filtering of transactions that use the placeholder
hash `0x0`.
> 
> - Updates `filterDuplicateOutgoingTransactions` to treat `hash ===
'0x0'` as absent so these entries are never deduped
> - Adds a unit test in `utils.test.ts` verifying transactions with
`0x0` hash are preserved
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3969d65. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@pull pull Bot locked and limited conversation to collaborators Jan 7, 2026
@pull pull Bot added the ⤵️ pull label Jan 7, 2026
@pull pull Bot merged commit b94b324 into Reality2byte:main Jan 7, 2026
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.

7 participants