Skip to content

[pull] main from MetaMask:main#315

Merged
pull[bot] merged 9 commits into
Reality2byte:mainfrom
MetaMask:main
Nov 11, 2025
Merged

[pull] main from MetaMask:main#315
pull[bot] merged 9 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Nov 11, 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 : )

grvgoel81 and others added 9 commits November 11, 2025 13:07
<!--
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**
* BugFix: #22375
* Jira: https://consensyssoftware.atlassian.net/browse/SL-280
* Shadow overlay issue in import srp via home screen
<!--
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: BugFix:
#22375

## **Related issues**

Fixes: 
* #22375
* Shadow overlay issue in import srp via home screen

## **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="353" height="798" alt="bug"
src="https://github.com/user-attachments/assets/2c4b5b6c-8bbd-4bf7-9e0e-4d898a6c855b"
/>

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


### **After**

https://github.com/user-attachments/assets/b36c5b81-96ca-4bd9-b422-db4cde062bdb
<!-- [screenshots/recordings] -->



https://github.com/user-attachments/assets/be424bbd-3175-4cf6-92d0-a5ec18f11c6d



https://github.com/user-attachments/assets/278508ca-f130-4f65-a472-10f49be445f3



## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Wraps WalletRecovery in SafeAreaView and updates layout/styles,
updating the snapshot accordingly.
> 
> - **UI (WalletRecovery)**
> - Wrap screen with `SafeAreaView` (`edges={{ bottom: 'additive' }}`)
and add `safeArea` style.
> - Adjust layout: reorganize `root` container spacing,
`socialContainer` structure, line break placement, and `srp` section
paddings (`srpTitle`, `srpListContainer`).
> - **Tests**
> - Update snapshot
`app/components/Views/WalletRecovery/__snapshots__/index.test.tsx.snap`
to reflect the new safe area wrapper and layout changes.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e5af869. 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**

This PR adds a feature flag for automatically updating preinstalled
Snaps and enables it. Following onboarding and as long as the user
doesn't opt-out, the Snaps registry will be queried and used to serve
updates for preinstalled Snaps.

## **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: Enable automatic updates of preinstalled Snaps

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Enables auto-updating preinstalled Snaps and adds a saga to update the
Snaps registry after login/onboarding, with tests and a
snaps-controllers bump.
> 
> - **Engine / Snaps Controller**:
> - Add `featureFlags.autoUpdatePreinstalledSnaps: true` in
`snap-controller-init.ts`; update expectations in
`snap-controller-init.test.ts`.
> - **Sagas**:
> - Introduce `handleSnapsRegistry` to call
`SnapController.updateRegistry` on `LOGIN` or when
`SET_COMPLETED_ONBOARDING` indicates completion; register in `rootSaga`.
> - **Tests**:
> - Add tests for `handleSnapsRegistry` covering login, onboarding
completion, and negative cases.
> - **Dependencies**:
>   - Bump `@metamask/snaps-controllers` from `^16.1.0` to `^16.1.1`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
afc3c7f. 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?
-->

There was a `transactions` array reference that was being reused on
every run of the selector, so duplicate items were being added and
breaking the transactions view.

## **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 issue with activity list showing blank spaces

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-1751

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

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


https://github.com/user-attachments/assets/437d7622-a32f-49dd-80ba-616eaa2c65ef


### **After**

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


https://github.com/user-attachments/assets/2a2edf96-7332-4c21-8673-078a1328d4cc


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

- Refactor some text to try to address the cut-off problem
- Add shares quantity to postion item
- Fix formatCents function to show only 1 decimal when necessary

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Switches cents display to compact format and enhances position card
text with share counts; adds formatting utilities and extensive tests
plus minor UI/layout tweaks.
> 
> - **UI/Components**:
>   - `PredictMarketOutcome`:
> - Button prices now use `formatCents` (e.g., `65¢`), adds winner/loser
badge on closed markets, minor layout tweaks.
>   - `PredictPosition`:
> - New subtitle: `"${amount} on {outcome} · {shares} share(s) at
{priceCents}"` using i18n, `formatCents`, `formatPositionSize`,
`formatPrice`.
>     - Supports `onPress` via test ID; renders icon; colorized PnL.
> - `PredictPositionsHeader`/`PredictMarketDetails`: small text/layout
cleanups.
> - **Utils**:
> - Add/overhaul `formatCents`, `formatVolume`,
`formatPositionSize(options)`, `getRecurrence`; keep
`formatPercentage/formatPrice`.
> - **Tests**:
> - Update expectations from `65.00¢` to `65¢`; add coverage for
pluralization, press handlers, and new formatters.
> - **Localization**:
> - Add `predict.position_info_plural/singular`, outcome labels, and
recurrence mapping.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
71f8d32. 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**

This PR enables automatic account upgrades when Smart Transactions (STX)
are turned off.
It removes the UI condition that previously blocked the flow from
initiating and refines the EIP-7702 authorization handling, signature
normalization, and gasless eligibility logic.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Added automatic account upgrade support

## **Related issues**

Fixes: MetaMask/mobile-planning#2332

## **Manual testing steps**

```gherkin
Feature: Automatic account upgrade when Smart Transactions are off

  Scenario: User sends a transaction using USDC as the gas token
    Given the user account has not been upgraded on the test network
      And the account has a sufficient USDC balance

    When the user sends a transaction
      And selects USDC as the gas payment token

    Then the transaction should complete successfully
      And the account should be automatically upgraded after completion

```

## **Screenshots/Recordings**


[mobile-auto-upgrade.webm](https://github.com/user-attachments/assets/f73d9f2e-ed76-432d-9d76-8542b1f6bf70)


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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds nonce-handling to the 7702 delegation publish path and simplifies
gasless eligibility by relying on relay support, plus signature
normalization utilities and tests.
> 
> - **Confirmations (Gasless eligibility)**:
> - Simplify `useIsGaslessSupported`: remove `isAtomicBatchSupported`
checks; now uses relay support and excludes contract deployments.
Updated tests accordingly.
> - **Transaction Controller Init**:
> - Wire `Delegation7702PublishHook` into `hooks.publish` when STX
disabled or `sendBundle` unsupported.
> - Add `getNextNonce` helper using `getNonceLock`/`releaseLock`; pass
to `Delegation7702PublishHook`. Tests verify locking and hex conversion.
> - **Delegation 7702 Publish Hook**:
> - Accept `getNextNonce`; use it to build authorization list (fallback
when tx nonce absent).
> - Normalize authorization signature parts (`r`, `s`, `yParity`) using
new util and `toHex`; improve calldata normalization.
> - Expand tests for gasless/sponsored flows, deployments, relay
responses, and errors.
> - **Utils**:
>   - Add `stripSingleLeadingZero` with tests for hex normalization.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1b24923. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
# Interactive Chart for Predict Markets

## Overview

This PR adds interactive drag-to-view functionality to the Predict
market details chart, allowing users to explore historical price data by
dragging their finger across the chart.

CHANGELOG entry: null


https://github.com/user-attachments/assets/036a225c-d751-4233-8e8a-453c03de7506

## Features

### 1. **Touch Interaction**
- Users can touch and drag on the chart to view values at different
points in time
- Crosshair line follows finger position from top to bottom of chart
- Values update in real-time as user drags

### 2. **Visual Feedback**
- **Crosshair Line**: Solid vertical line (theme-aware) extends from top
to bottom
- **Time Label**: Displayed at top of chart showing timestamp at dragged
position
- **Data Point Indicators**: Colored circles on each line at the active
position
- **Value Labels**: Colored badges showing series name and value at each
data point

### 3. **Smart Label Positioning**
- **Collision Detection**: Labels automatically adjust to prevent
overlap when lines cross
- **Side Switching**: Labels flip from right to left side when user
drags past chart midpoint
- **Character Limit**: Labels truncate to 25 characters to prevent
overflow

### 4. **Dynamic Legend Values**
- Legend above chart updates to show values at dragged position
- Automatically reverts to latest values when user releases touch
- Provides context for historical data exploration

### 5. **Gesture Handling**
- **Directional Detection**: Distinguishes between horizontal drags
(chart interaction) and vertical scrolls (page scrolling)
- **No Scroll Conflicts**: Parent ScrollView continues to work for
vertical scrolling
- Smart gesture capture prevents interference between chart interaction
and page navigation

### 6. **Theme Support**
- All colors use design tokens for automatic light/dark mode support
- Crosshair line: `colors.border.muted` (gray in light mode, white in
dark mode)
- Text: `colors.text.alternative` (gray in light mode, white in dark
mode)
- Labels: `colors.background.default` for text on colored backgrounds

## Technical Implementation

### Components Modified

1. **`PredictDetailsChart.tsx`**
   - Added `PanResponder` for touch gesture handling
   - Implemented collision detection algorithm for label positioning
   - Created tooltip overlay with proper z-index stacking
   - Added directional gesture discrimination

2. **`ChartLegend.tsx`**
   - Added `activeIndex` prop to display dragged position values
   - Updates dynamically during drag interaction
   - Reverts to latest values on release

### Key Technical Decisions

- **Tooltip Rendering**: Uses separate transparent `LineChart` overlay
rendered last for proper z-index
- **Collision Detection**: Sorts labels by Y position and applies
minimum 4px spacing
- **Gesture Direction**: Uses `gestureState.dx` and `gestureState.dy` to
determine horizontal vs vertical movement
- **Label Truncation**: 25-character limit with ellipsis for long
outcome titles

## Testing

### Manual Testing Steps

1. Navigate to any Predict market with price history
2. Touch and drag horizontally on the chart
3. Verify:
   - Crosshair line appears and follows touch
   - Time label shows at top of chart
   - Value labels appear next to data points
   - Legend values update to show dragged position
   - Labels flip to left side when dragging on right half
   - Labels don't overlap when lines cross
4. Release touch and verify:
   - Tooltip disappears
   - Legend reverts to latest values
5. Try vertical scrolling on chart area:
   - Verify page scrolls normally
   - Chart interaction only activates on horizontal drag

### Edge Cases Tested

- ✅ Multiple series with crossing lines (collision detection)
- ✅ Long outcome titles (truncation to 25 chars)
- ✅ Single vs multiple series charts
- ✅ Empty data states
- ✅ Loading states
- ✅ Light and dark modes
- ✅ Gesture conflicts with ScrollView

## Screenshots/Demo

_Add screenshots or screen recording demonstrating the interactive
features_

## Performance Considerations

- Uses `useCallback` for gesture handlers to prevent unnecessary
re-renders
- Tooltip component defined outside render to avoid recreation
- Collision detection runs only during active drag (not on every render)
- Proper cleanup on gesture release

## Accessibility

- Touch targets are appropriate size (chart fills available width)
- Visual feedback is clear and theme-aware
- Falls back to showing latest values when not interacting

## Breaking Changes

None. All changes are additive and backward compatible.

## Dependencies

No new dependencies added. Uses existing:
- `react-native-svg-charts` (already in use)
- `react-native-svg` (already in use)
- React Native `PanResponder` (built-in)

## Future Enhancements

Potential improvements for future PRs:
- Haptic feedback on touch
- Animation transitions for label movements
- Pinch-to-zoom for chart data
- Export chart data feature
- Customizable tooltip appearance

## Commits

- `ba2a015` - feat: add interactive chart with drag-to-view values in
Predict
- `3a40cd1` - refactor: improve chart tooltip styling and positioning
- `93142d5` - feat: add label collision detection to chart tooltip
- `2a6f32b` - feat: update legend values dynamically based on dragged
position
- `a9d37d6` - feat: add character limit to tooltip labels

## Checklist

- [x] Code follows project coding guidelines
- [x] No linting errors
- [x] Changes are backward compatible
- [x] Manual testing completed
- [x] Works in both light and dark themes
- [x] Gesture handling doesn't conflict with ScrollView
- [ ] Unit tests added (if applicable)
- [ ] E2E tests updated (if applicable)
- [ ] Documentation updated (if applicable)

## Related Issues

_Link any related issues or tickets here_


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds touch-driven crosshair/tooltip overlay with dynamic legend
updates to Predict details chart, plus extensive tests and minor
type/mocks updates.
> 
> - **PredictDetailsChart** (`PredictDetailsChart.tsx`):
> - Add interactive drag support via `PanResponder` with
horizontal/vertical gesture discrimination.
> - Implement `ChartTooltip` overlay (crosshair, timestamp, per-series
circles/labels) rendered via transparent `LineChart` layer.
> - Dynamic legend: pass `activeIndex` to `ChartLegend` to show values
at the dragged position; revert when inactive.
> - Data/type updates: `ChartSeries.data` supports optional `label`;
generate formatted `label` for timestamps; collision handling and
side-switching for tooltip labels; theme-aware colors.
> - **ChartLegend** (`components/ChartLegend.tsx`):
> - Accept `activeIndex` to display contextual values; fallback to last
point; formatting via `formatTickValue`.
> - **Tests**:
> - Expand `PredictDetailsChart.test.tsx` to cover interactions,
overlays, label truncation/collisions, theme, multiple series, and axis
labels; adjust `LineChart` mock to hide transparent overlay; add
`Circle`/`Rect` to SVG mocks.
> - Add `ChartLegend.test.tsx` with value formatting, activeIndex
behaviors, edge cases, and multi-series coverage.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
98d1802. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Luis Taniça <matallui@gmail.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**

This pull request adds analytics tracking for button presses in the buy
and deposit settings modals, ensuring that user interactions are logged
with relevant context such as modal location, ramp type, and region. It
also updates tests to cover the new analytics behavior and adjusts the
analytics event type to support both deposit and buy actions.

**Analytics tracking enhancements:**

* Added calls to `useAnalytics` in both `SettingsModal` and
`ConfigurationModal` to track when users press key buttons, logging the
event `RAMPS_BUTTON_CLICKED` with details including location, ramp type,
and region.
[[1]](diffhunk://#diff-e763577f4d665c8606263239492930e87bf3d4e279cbbac587936cf66d7bd4d8R24-R26)
[[2]](diffhunk://#diff-e763577f4d665c8606263239492930e87bf3d4e279cbbac587936cf66d7bd4d8L37-R48)
[[3]](diffhunk://#diff-14b45fbd996660ab55073b32a73ea45aa0488624ceb4efbd267c8a967cda1f4cR37-R40)
[[4]](diffhunk://#diff-14b45fbd996660ab55073b32a73ea45aa0488624ceb4efbd267c8a967cda1f4cR58-R65)
* Updated the analytics event type definition in `analytics.ts` to allow
`ramp_type` to be either `'DEPOSIT'` or `'BUY'`.

**Testing improvements:**

* Added and updated mocks for the analytics hook (`useAnalytics`) and
region selection in test files to verify that analytics events are
triggered with the correct parameters.
[[1]](diffhunk://#diff-c97ef93052f382820dc15a75c6550cfb58cb2e02701b00954bf6627ee973dae5L6-R18)
[[2]](diffhunk://#diff-c97ef93052f382820dc15a75c6550cfb58cb2e02701b00954bf6627ee973dae5R33-R43)
[[3]](diffhunk://#diff-2b29b56f399f76e64d8c1f0562554c20f367f832fcef7a8bbd87d7a31363dcd4R49-R51)
[[4]](diffhunk://#diff-2b29b56f399f76e64d8c1f0562554c20f367f832fcef7a8bbd87d7a31363dcd4R102)
* Added new test cases to ensure that pressing the relevant buttons in
both modals triggers the analytics event as expected.
[[1]](diffhunk://#diff-c97ef93052f382820dc15a75c6550cfb58cb2e02701b00954bf6627ee973dae5R165-R177)
[[2]](diffhunk://#diff-2b29b56f399f76e64d8c1f0562554c20f367f832fcef7a8bbd87d7a31363dcd4R135-R145)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

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

## **Manual testing steps**

```gherkin
Feature: Deposit and Buy switcher

  Scenario: user switches between buy and deposit
    Given user is in Deposit or Buy

    When user opens the settings modal
    And navigates to the other experience
    Then analytic event is tracked
```

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Add analytics tracking for settings modal button presses in
buy/deposit flows (with region) and update event types; tests updated to
cover tracking.
> 
> - **Analytics tracking**:
> - Add `useAnalytics` calls in
`Aggregator/Views/Modals/Settings/SettingsModal.tsx` and
`Deposit/Views/Modals/ConfigurationModal/ConfigurationModal.tsx` to emit
`RAMPS_BUTTON_CLICKED` with `location`, `ramp_type`, and `region` from
SDK-selected region.
> - **Types**:
> - Expand `RampsButtonClicked.ramp_type` in
`Deposit/types/analytics.ts` to support `'DEPOSIT' | 'BUY'`.
> - **Tests**:
> - Mock `useAnalytics` and region in `SettingsModal.test.tsx` and
`ConfigurationModal.test.tsx`.
> - Add assertions that pressing "Use new buy experience" / "More ways
to buy" triggers `RAMPS_BUTTON_CLICKED` with correct params.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bcf0b8b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Description

This PR significantly improves the loading experience across the Predict
feature by implementing skeleton loaders in place of generic loading
indicators. Skeleton loaders provide visual placeholders that mimic the
actual content structure, reducing perceived loading time and creating a
smoother user experience.

CHANGELOG entry: null


https://github.com/user-attachments/assets/992ab739-7dc8-47f3-b7df-9fdddbfe072e

### What Changed

**Market List**
- Created `PredictMarketSkeleton` component to show placeholder cards
during market list loading
- Replaced generic loading spinner with realistic market card skeletons
- Applied to both initial load and pagination footer

**Market Details Page**
- Created `PredictDetailsHeaderSkeleton` for header section (back arrow,
avatar, title)
- Created `PredictDetailsContentSkeleton` for outcome options area
- Created `PredictDetailsButtonsSkeleton` for action buttons (Buy
Yes/No)
- Header renders immediately with skeleton if route params are missing
- Content and buttons show skeletons only during initial market data
fetch
- Chart component handles its own loading state independently

**Home Screen - Positions Tab**
- Added inline skeleton for "Available Balance" value in
`PredictPositionsHeader`
- Added inline skeleton for "Unrealized P&L" value in
`PredictPositionsHeader`
- Removed early return to ensure card always renders during loading
- Hidden arrow icon during balance loading state
- Created `PredictPositionSkeleton` component for individual position
items
- Replaced large `ActivityIndicator` with 4 skeleton position cards in
`PredictPositions`

**Buy/Trade Preview Screen**
- Added smart skeleton loader for "To win" value
- Skeleton only appears when user changes input amount (not during
auto-refresh)
- Uses `previousValueRef` to track actual value changes
- Automatically clears after calculation completes
- Prevents annoying skeleton flashing from background 1s auto-refresh

### Why These Changes

- **Improved Perceived Performance**: Skeleton loaders reduce perceived
loading time by providing visual feedback that content is coming
- **Consistent UX Pattern**: Matches modern mobile app patterns
(Facebook, Instagram, etc.)
- **Better User Feedback**: Shows the structure of content before it
loads, setting expectations
- **Reduced Jarring Transitions**: Smooth visual transition from
skeleton to content vs. spinner to content
- **Context Preservation**: Users can see where content will appear and
what type of content to expect

### Technical Approach

1. **Component Structure**: Each skeleton component mirrors the layout
and dimensions of its real content counterpart
2. **Modular Design**: Split complex skeletons into reusable
sub-components (Header, Content, Buttons)
3. **Conditional Rendering**: Smart logic to show skeletons only during
appropriate loading states
4. **Independent Loading States**: Different sections load independently
(e.g., chart vs. market data)
5. **Smart Debouncing**: Buy preview skeleton uses value change
detection + debouncing to avoid flash

### Design Alignment

All skeleton implementations were created based on Figma SVG designs
provided by the design team, ensuring pixel-perfect alignment with
design specifications.

## Changelog

### Added
- Added skeleton loader component for prediction market cards in feed
- Added skeleton loaders for market details page (header, content,
action buttons)
- Added skeleton loaders for Available Balance and Unrealized P&L on
home screen
- Added skeleton loader component for position items in positions list
- Added smart skeleton loader for "To win" value in buy preview screen

### Changed
- Replaced generic loading spinner with skeleton cards in market list
- Replaced large activity indicator with position card skeletons in
positions list
- Updated positions header to always render main card with inline value
skeletons during loading

## Related Issues

Refs: [Add issue number if applicable]

## Manual Testing Steps

### Market List Skeleton
```gherkin
GIVEN I am on the Predict tab
WHEN the market list is loading for the first time
THEN I should see 4 skeleton market cards with avatar, title, content area, and footer
AND the skeletons should smoothly transition to real market cards once loaded

WHEN I scroll to the bottom of the market list
AND more markets are being fetched
THEN I should see 2 skeleton cards at the bottom
AND they should transition to real market cards once loaded
```

### Market Details Skeleton
```gherkin
GIVEN I tap on a prediction market from the list
WHEN the market details page is loading
AND the title exists in route params
THEN I should see the header with real back arrow, avatar, and title immediately
AND I should see skeleton content for outcome options
AND I should see skeleton buttons at the bottom

WHEN the market data finishes loading
THEN the skeleton content should transition to real outcome options
AND the skeleton buttons should transition to real "Buy Yes" and "Buy No" buttons

GIVEN I tap on a market with no title in route params
WHEN the market details page loads
THEN I should see a skeleton header with functional back arrow
AND the avatar and title should be skeleton placeholders
AND the skeleton header should transition to real content once market data loads
```

### Home Screen Positions Skeleton
```gherkin
GIVEN I am on the Predict home screen
WHEN my balance and unrealized P&L are loading
THEN I should see the main card with skeleton placeholders for both values
AND the arrow icon next to Available Balance should be hidden
AND the skeletons should smoothly transition to real values once loaded

WHEN my positions list is loading
THEN I should see 4 skeleton position cards
AND each should show avatar, title lines, and value placeholders
AND they should transition to real position items once loaded

WHEN I have no positions and no balance data
AND nothing is loading
THEN the positions header card should not render at all
```

### Buy Preview Skeleton
```gherkin
GIVEN I am on the Buy/Trade preview screen
WHEN I type in a new amount value
THEN I should see the "To win" label remain visible
AND the value should show as a skeleton while calculating
AND the skeleton should disappear once calculation completes (max 500ms)

WHEN the preview auto-refreshes every 1 second
THEN the skeleton should NOT flash or appear
AND the "To win" value should update silently in the background

WHEN I clear the input to 0
THEN the skeleton state should reset
AND no skeleton should show for the "To win" value
```

## Screenshots/Recordings

<!-- Add before/after screenshots or screen recordings showing:
- Market list with skeleton loaders during initial load
- Market list with skeleton loaders during pagination
- Market details page with skeleton header/content/buttons
- Home screen positions tab with skeleton values and position cards
- Buy preview screen with "To win" skeleton appearing on input change
-->

## Pre-merge Checklist

- [ ] Manually tested all skeleton loader scenarios
- [ ] All unit tests pass (`yarn jest app/components/UI/Predict`)
- [ ] No new linter errors
- [ ] No TypeScript errors
- [ ] Screenshots/recordings added (UI changes)
- [ ] Follows coding guidelines and design system rules
- [ ] PR template completed
- [ ] Assigned to myself
- [ ] Team label added
- [ ] Branch follows naming convention

## Components Created

### New Files
1. `app/components/UI/Predict/components/PredictMarketSkeleton/`
   - `PredictMarketSkeleton.tsx` - Skeleton for market list cards
   - `PredictMarketSkeleton.test.tsx` - Unit tests
   - `index.ts` - Barrel export

2. `app/components/UI/Predict/components/PredictDetailsHeaderSkeleton/`
- `PredictDetailsHeaderSkeleton.tsx` - Skeleton for details page header
   - `PredictDetailsHeaderSkeleton.test.tsx` - Unit tests
   - `index.ts` - Barrel export

3. `app/components/UI/Predict/components/PredictDetailsContentSkeleton/`
- `PredictDetailsContentSkeleton.tsx` - Skeleton for details page
content
   - `PredictDetailsContentSkeleton.test.tsx` - Unit tests
   - `index.ts` - Barrel export

4. `app/components/UI/Predict/components/PredictDetailsButtonsSkeleton/`
   - `PredictDetailsButtonsSkeleton.tsx` - Skeleton for action buttons
   - `PredictDetailsButtonsSkeleton.test.tsx` - Unit tests
   - `index.ts` - Barrel export

5. `app/components/UI/Predict/components/PredictPositionSkeleton/`
   - `PredictPositionSkeleton.tsx` - Skeleton for position list items
   - `PredictPositionSkeleton.test.tsx` - Unit tests
   - `index.ts` - Barrel export

### Modified Files
1.
`app/components/UI/Predict/components/MarketListContent/MarketListContent.tsx`
   - Integrated `PredictMarketSkeleton` for loading states

2.
`app/components/UI/Predict/views/PredictMarketDetails/PredictMarketDetails.tsx`
   - Integrated header, content, and button skeletons
   - Modified conditional rendering logic

3.
`app/components/UI/Predict/views/PredictMarketDetails/PredictMarketDetails.test.tsx`
   - Updated tests to expect new skeleton components

4.
`app/components/UI/Predict/components/PredictPositionsHeader/PredictPositionsHeader.tsx`
   - Added inline skeletons for balance and P&L values
   - Modified loading state logic

5.
`app/components/UI/Predict/components/PredictPositionsHeader/PredictPositionsHeader.test.tsx`
   - Updated tests for new loading behavior

6.
`app/components/UI/Predict/components/PredictPositions/PredictPositions.tsx`
   - Replaced ActivityIndicator with PredictPositionSkeleton components

7.
`app/components/UI/Predict/components/PredictPositions/PredictPositions.test.tsx`
   - Updated tests to expect skeleton components

8.
`app/components/UI/Predict/views/PredictBuyPreview/PredictBuyPreview.tsx`
   - Added smart skeleton for "To win" value with value-change detection

9. `app/components/UI/Predict/hooks/usePredictOrderPreview.ts`
   - Exposed `isCalculating` state for skeleton logic

## Technical Notes

### Design System Compliance
- All skeletons use `Box` component from
`@metamask/design-system-react-native`
- Styling uses `useTailwind()` hook and `twClassName` prop
- No StyleSheet usage (adheres to workspace rules)
- Uses design system color tokens (`bg-muted`, `bg-section`, etc.)

### Testing Strategy
- Unit tests for all new skeleton components
- Integration tests updated for modified components
- All tests use React Testing Library best practices

### Performance Considerations
- Skeleton components are lightweight (no heavy computations)
- Smart debouncing prevents excessive skeleton re-renders
- Independent loading states prevent unnecessary full-page re-renders

## Review Focus Areas

1. **Visual Accuracy**: Do skeletons match the Figma designs and real
content structure?
2. **Loading Logic**: Are skeletons appearing at the right times and
transitioning smoothly?
3. **User Experience**: Does this feel smoother than the previous
loading indicators?
4. **Test Coverage**: Do tests properly cover loading states and
transitions?
5. **Code Organization**: Are components modular and reusable?


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds dedicated skeleton loaders for market lists, market details,
positions, and buy preview, replacing spinners and refining loading
logic.
> 
> - **Predict UI**:
> - **Market List (`MarketListContent.tsx`)**: Replace generic
loading/footer placeholders with `PredictMarketSkeleton` cards for
initial load and pagination.
> - **Market Details (`PredictMarketDetails.tsx`)**: Add
`PredictDetailsHeaderSkeleton`, `PredictDetailsContentSkeleton`, and
`PredictDetailsButtonsSkeleton`; render skeletons during initial fetch;
keep chart loading independent; refine header rendering when route
params missing.
>   - **Positions**:
> - **Header (`PredictPositionsHeader.tsx`)**: Inline skeletons for
Available Balance and Unrealized P&L; always render card while loading;
disable arrow while loading.
> - **List (`PredictPositions.tsx`)**: Replace `ActivityIndicator` with
4 `PredictPositionSkeleton` rows during initial/refresh loads; gate
`PredictNewButton` when loading.
> - **Buy Preview (`PredictBuyPreview.tsx`)**: Show smart skeleton for
"To win" value only while recalculating due to user input; keep balance
skeleton.
> - **New Components**: `PredictMarketSkeleton`,
`PredictDetailsHeaderSkeleton`, `PredictDetailsContentSkeleton`,
`PredictDetailsButtonsSkeleton`, `PredictPositionSkeleton` (+ index
files).
> - **Misc**: Simplify `selectPredictEnabledFlag` property check; update
tests and snapshots to assert skeletons.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
118502a. 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**

- show polymarket offline screen for feed errors

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: [PRED-280

](https://consensyssoftware.atlassian.net/browse/PRED-280?atlOrigin=eyJpIjoiYzgwMjc5ODhlNDAzNDNiZmJmYWVmOWY4MzYyNjQyMWUiLCJwIjoiaiJ9)
## **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]
> Replaces inline error message with `PredictOffline` in
`MarketListContent`, wiring retry to `refetch`, and updates tests to
validate offline UI and retry behavior.
> 
> - **Predict Feed**
> - **Error UI**: Replace inline error message in
`app/components/UI/Predict/components/MarketListContent/MarketListContent.tsx`
with `PredictOffline` and hook `onRetry` to `handleRefresh`/`refetch`.
> - **Tests**
> - Update `MarketListContent.test.tsx` to mock `PredictOffline` and
assert offline copy and layout via `testID`s.
> - Add retry behavior test invoking `onRetry` (using `act`) to verify
`refetch` is called.
> - Keep existing loading/footer skeleton and empty state tests intact.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
566f524. 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 Nov 11, 2025
@pull pull Bot added the ⤵️ pull label Nov 11, 2025
@pull pull Bot merged commit 325d6ab into Reality2byte:main Nov 11, 2025
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