Skip to content

[pull] main from MetaMask:main#320

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

[pull] main from MetaMask:main#320
pull[bot] merged 15 commits into
Reality2byte:mainfrom
MetaMask:main

Conversation

@pull
Copy link
Copy Markdown

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

abretonc7s and others added 15 commits November 12, 2025 17:43
… cp-7.59.0 (#22552)

## **Description**

This PR fixes a critical UX issue where users without HyperLiquid
deposits were blocked from viewing Perps market data, but more
importantly, it implements a comprehensive architectural improvement to
separate read and write operations in the HyperLiquid provider.

### The Problem

Users who had never traded on HyperLiquid before (no on-chain deposits)
encountered "Perps temporarily offline" errors when trying to view the
Perps screen. Investigation revealed that:

1. Builder fee approval requires on-chain deposits to succeed
2. The previous implementation (PR #22242) moved builder fee approval to
`ensureReady()` for performance optimization
3. **Root cause**: `ensureReady()` was being called in 15+ read-only
methods (validation, data fetching, balance checks)
4. This caused read operations to trigger wallet signatures and block
the UI when builder fee approval failed

### The Solution

#### 1. Non-Blocking Builder Fee Approval
- Wrapped builder fee approval in try-catch within `ensureReady()`
- Allows initialization to complete even if builder fee fails
- Builder fee is still checked explicitly before actual trading
operations

#### 2. Race Condition Prevention
- Added pending promise deduplication using Maps
- Prevents multiple concurrent calls from triggering duplicate signature
requests
- Eliminates "DEX abstraction already set" and "Referrer already set"
error spam

#### 3. Architectural Improvement: Separation of Read/Write Operations P

**Removed `ensureReady()` from 15 read-only methods** and replaced with
minimal client initialization:

**High Priority (Called from validation hooks/screen init):**
- `getAccountState()` - Balance and account data
- `getPositions()` - Position data
- `getOpenOrders()` - Open orders
- `getMarketDataWithPrices()` - Market prices
- `calculateFees()` - Fee calculation

**Medium Priority (Historical data):**
- `getOrderFills()`, `getOrders()`, `getFunding()`
- `getUserNonFundingLedgerUpdates()`, `getUserHistory()`,
`getHistoricalPortfolio()`

**Lower Priority (Market discovery):**
- `getMarkets()`, `getAvailableHip3Dexs()`, `getAvailableDexs()`,
`ping()`

### Benefits

#### � Better User Experience
- Users can view Perps data immediately without builder fee approval
- Validation never blocks on initialization steps

#### � Performance Improvements
- Eliminated DEX abstraction network call on every validation
- Read operations are instant (no network overhead)
- Faster screen initialization and validation

#### � Architectural Clarity
- Clear separation: Read operations = view data, Write operations =
trade
- Validation is truly read-only (no side effects)
- Builder fee approval only runs when actually needed (during trading)

#### � Reliability
- No more "already set" error spam
- Race conditions eliminated
- Graceful degradation (view data even if setup incomplete)

### Technical Details

**Before:**
```typescript
async getAccountState() {
  await this.ensureReady(); // Triggers: DEX abstraction, referral, builder fee
  // ... fetch data
}
```

**After:**
```typescript
async getAccountState() {
  // Read-only operation: only need client initialization
  this.ensureClientsInitialized();
  this.clientService.ensureInitialized();
  // ... fetch data
}
```

Write operations (placeOrder, editOrder, etc.) correctly keep
`ensureReady()` to ensure full initialization before trading.

## **Changelog**

CHANGELOG entry: Fixed Perps "temporarily offline" error for new users
and improved performance by optimizing read operations

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2060

## **Manual testing steps**

```gherkin
Feature: Perps data viewing without builder fee approval

  Scenario: New user views Perps market data
    Given user has never traded on HyperLiquid (no deposits)
    And user has not approved builder fee

    When user opens Perps screen
    Then market data and prices load successfully
    And no wallet signature prompts appear
    And no "temporarily offline" errors occur

  Scenario: Existing user places order
    Given user has approved builder fee in the past

    When user opens order form and enters order details
    Then order validation completes without signatures

    When user clicks "Place Order" button
    Then builder fee approval is checked before order placement
    And order executes successfully

  Scenario: Race condition prevention
    Given multiple operations triggered simultaneously (e.g., validation + balance check)

    When all operations call ensureReady() concurrently
    Then only one initialization sequence runs
    And no "already set" errors appear in logs
```

## **Screenshots/Recordings**

### **Before**
- Users without deposits saw "Perps temporarily offline"
- Console showed multiple "DEX abstraction already set" errors
- Validation triggered wallet signature prompts

### **After**
- All users can view Perps data immediately
- No error spam in console
- Validation is instant and read-only
- Builder fee approval only triggers when placing actual orders

## **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]
> Separates read vs write paths in HyperLiquid provider (read ops no
longer block on builder fee), adds promise deduping for init/approvals,
updates close-position slippage for full closes, and refreshes wallet
account on each sign.
> 
> - **HyperLiquid Provider (architecture/perf)**
> - Split initialization: read-only methods now only ensure clients,
skipping `ensureReady()` (e.g., `getPositions`, `getOrders`,
`getOpenOrders`, `getFunding`, `getAccountState`, `getMarkets`,
`getMarketDataWithPrices`, `getAvailable*`, `ping`, `getMaxLeverage`,
`calculateFees` fetch path).
> - Builder fee approval made non-blocking in `ensureReady()`;
explicitly enforced before trading ops (`placeOrder`, `editOrder`,
`cancel*`, `closePosition(s)`, `updatePositionTPSL`).
> - Added promise deduplication for init/approvals
(`ensureReadyPromise`, `pendingBuilderFeeApprovals`) to prevent
concurrent signature/race conditions.
> - `disconnect()` now clears pending promises and resets client init
state.
> - **Close Position UI/Tests**
> - Always pass `slippage` context; for full close set
`slippage.usdAmount` to `undefined` to bypass $10 min; tests updated to
assert this.
> - **Wallet Integration**
> - `HyperLiquidWalletService.signTypedData` re-reads the current
account on each sign to handle account switches.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
445297f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
…ket details due to loading skeletons (#22505)

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

- Super quick one that addresses an issue with the sticky tabs
(outcomes, etc) not working correctly after the introduction of the
loading skeletons

<!--
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: NA

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

<img width="420" alt="image"
src="https://github.com/user-attachments/assets/3f41621f-9230-4a6a-8202-f1a1e489fa7e"
/>

## **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]
> Computes `stickyHeaderIndices` based on loading state and renders tab
bar separately from tab content so sticky tabs work correctly with
loading skeletons.
> 
> - **PredictMarketDetails (`PredictMarketDetails.tsx`)**:
> - Compute `stickyHeaderIndices` via `useMemo`, returning `[]` during
initial loading and `[1]` otherwise; pass to `ScrollView`.
> - Separate rendering of sticky tab bar (`renderCustomTabBar()`) from
tab content, showing the tab bar during loading and only rendering tab
content when `market` is loaded.
> - Minor restructuring around skeleton display to avoid interfering
with sticky behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ef40812. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…22503)

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

- Created new accounts.ts utility module to centralize account tree
management
- Migrated account tree logic from PredictController and hooks to
accounts utility
- Updated usePredictActivity, usePredictBalance, usePredictClaimToasts,
usePredictDeposit, usePredictDepositToasts, usePredictPositions, and
useUnrealizedPnL hooks
- Removed useWithdrawToasts hook (consolidated into deposit toasts)
- Added comprehensive test coverage for new accounts utility
- Updated PredictController and PredictPositionsHeader to use new
utility

<!--
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]
> Extracts `getEvmAccountFromSelectedAccountGroup` and refactors
PredictController, hooks, and UI to use it for address resolution, with
updated toasts/formatting and comprehensive tests.
> 
> - **Core/Controller**:
> - Replace direct `AccountsController.getSelectedAccount()` usage with
`getSigner().address` backed by
`getEvmAccountFromSelectedAccountGroup()` across `getPositions`,
`getActivity`, `getUnrealizedPnL`, `getAccountState`, `getBalance`,
`clearPendingDeposit`.
> - Add accounts utility import and integrate into signer/address
resolution.
> - **Utilities**:
> - Add `utils/accounts.ts` with
`getEvmAccountFromSelectedAccountGroup`.
> - **Hooks/UI**:
> - Update `usePredictBalance`, `usePredictDeposit`,
`usePredictDepositToasts`, `usePredictClaimToasts`,
`usePredictPositions`, `usePredictActivity`, `useUnrealizedPnL`, and
`PredictPositionsHeader` to derive `selectedAddress` via accounts
utility (remove Redux address selector usage).
>   - Deposit toast confirmed amount now formatted via `formatPrice`.
> - **Tests**:
> - Add unit tests for accounts utility and update existing tests to
mock `AccountTreeController` and new address flow across hooks,
controller, and views.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3481cd3. 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**

- Adjust button heights and spacing in PredictKeypad for better UX
- Implement dynamic label formatting in PredictMarketOutcome buttons
  - Use bullet separator (•) when both labels are ≤6 characters
  - Use newline separator when either label exceeds 6 characters
  - Adjust button height dynamically based on label length
- Update insufficient funds message to show available balance
- Improve error message copy for better user understanding
- "Not enough funds. You can use up to {amount}." (was "Insufficient
funds...")
  - "Minimum amount is {amount}" (was "Minimum bet is {amount}")
- Add comprehensive test coverage for button label formatting scenarios

<!--
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]
> Refines Predict keypad/button layout, adds dynamic outcome button
label formatting, and updates Buy Preview errors to show max usable
amount with new copy, plus tests and i18n updates.
> 
> - **Predict UI**:
> - **Outcome buttons (`PredictMarketOutcome`)**: Add dynamic label
formatting (bullet vs newline) with `MAX_LABEL_LENGTH=6`, center text,
and increase button height when labels are long.
> - **Keypad (`PredictKeypad`)**: Tighten spacing and set fixed heights
for quick-amount and "Done" buttons.
> - **Buy Preview (`PredictBuyPreview`)**:
> - Compute `maxBetAmount` and render updated error copy: "Not enough
funds. You can use up to {{amount}}." and "Minimum amount is {{amount}}"
via i18n.
> - **Tests**:
> - Add comprehensive tests for outcome label formatting and update
validation/error expectations across Buy Preview.
> - **i18n (`locales/languages/en.json`)**:
> - Update `prediction_insufficient_funds` and `prediction_minimum_bet`
strings to new copy with amount placeholders.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3f7bbb2. 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**

Updates bitcoin to `1.5.0`, which places accounts info under encrypted
state

<!--
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]
> Update `@metamask/bitcoin-wallet-snap` from `^1.4.5` to `^1.5.0` in
`package.json` and `yarn.lock`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f6e0b97. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…2170)

## **Description**

Updates the default button size for BottomSheetHeader close (X) and back
(<) buttons from Medium (MD) to Large (LG) to align with the BottomSheet
standardization specifications.

This change makes all BottomSheets consistent by default without
requiring individual components to explicitly set the button size.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of: https://consensyssoftware.atlassian.net/browse/MDP-343

<img width="450" height="397" alt="Screenshot 2025-11-04 at 4 44 57 PM"
src="https://github.com/user-attachments/assets/08fb3eee-7d14-4e91-af13-694ab8d93802"
/>

## **Manual testing steps**

```gherkin
Feature: BottomSheetHeader button size update

  Scenario: View updated button sizes in Storybook
    Given Storybook is running
    When I navigate to BottomSheetHeader component
    Then I should see the close button (X) is size LG (32x32px)
    And I should see the back button (<) is size LG (32x32px)
```

## **Screenshots/Recordings**

### **Before**

Close and back buttons were size MD (28x28px with 20x20px icons)

<img width="422" height="174" alt="Screenshot 2025-11-04 at 3 45 52 PM"
src="https://github.com/user-attachments/assets/91a44051-2ef6-4b20-94b9-86b395ec92a2"
/>

### **After**

Close and back buttons are now size LG (32x32px with 24x24px icons)

<img width="420" height="168" alt="Screenshot 2025-11-04 at 3 40 07 PM"
src="https://github.com/user-attachments/assets/c8dd306e-fadb-45ff-8d9c-58f57cdf5e24"
/>

## **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]
> Sets `BottomSheetHeader` back/close `ButtonIcon` size to LG by default
and updates affected consumers and snapshots.
> 
> - **Component Library**:
> - `BottomSheets/BottomSheetHeader`: Back and close `ButtonIcon` now
default to `size=LG`.
> - **App UI**:
> - Remove redundant `size` overrides for `BottomSheetHeader` close/back
buttons in Bridge selectors and related screens to rely on new default.
> - **Tests/Snapshots**:
> - Update snapshots across BottomSheet-based modals/views to reflect
`32x32` buttons with `24x24` icons (was `28x28` with `20x20`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
737d5bb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Use Relay strategy for Predict deposits.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
[#5945](MetaMask/MetaMask-planning#5945)

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [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]
> Wires Transaction Pay to Relay using delegation (with 7702 auth), adds
exact batch caveat support, treats Predict deposits as Polygon USDC.e
receives, and ignores skipIfBalance tokens in insufficient balance
alerts.
> 
> - **Payments/Engine**:
> - **Transaction Pay init**: Pass `getDelegationTransaction` and always
use `Relay` strategy; add init messenger for delegation and 7702
signing; hook up in `CONTROLLER_MESSENGERS`.
> - **Messengers**: Extend Transaction Controller init messenger (incl.
`addTransactionBatch`); add Transaction Pay init messenger.
> - **Delegation**:
> - **New caveat**: Add `exactExecutionBatch` builder and register in
caveat builder; validation of inputs; unit tests.
> - **Utils**: Build delegation transactions (encode redeem delegations,
EIP-7702 authorization list, batch/single execution modes); tests and
snapshots.
> - **UI**:
> - **TransactionDetailsSummary**: Treat `predictDeposit` as bridge
receive to `Polygon` with `POLYGON_USDCE`; remove special-case title and
use default; update tests.
> - **Alerts**:
> - **Insufficient Pay Token**: Exclude tokens with `skipIfBalance` from
total; test added.
> - **Deps**:
>   - Bump `@metamask/transaction-pay-controller` to `^5.0.0`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ec1b6af. 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**

- Change pendingDeposits state from boolean flags to batch ID strings
- Update selector to return undefined instead of false for cleared
deposits
- Add batch ID tracking to deposit toasts for better transaction
matching
- Update hook to convert batch ID to boolean for backward compatibility
- Delete deposit entries instead of setting to false when clearing
- Add 'pending' state before batch ID is assigned
- Clear deposit state on errors in depositWithConfirmation
- Fix all related tests to expect batch ID strings and undefined values

<!--
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]
> Switch pending deposit tracking from booleans to batch IDs, update
toasts/selectors to use batch IDs, and adjust controller logic and tests
accordingly.
> 
> - **PredictController**:
> - Change `state.pendingDeposits` to map addresses to batch ID `string`
(was `boolean`).
> - On deposit: clear previous entry, set to `'pending'`, then replace
with real `batchId`; validate chain ID; clear pending on errors/user
cancel.
> - `clearPendingDeposit` now deletes address entry instead of setting
`false`.
> - **Hooks**:
> - `usePredictDeposit`: selector now returns batch ID; exposes
`isDepositPending` via `!!batchId`.
> - `usePredictDepositToasts`: reads batch ID and passes
`transactionBatchId` (ignores `'pending'`).
> - `usePredictToasts`: accepts optional `transactionBatchId` and
matches by `batchId` when provided, otherwise falls back to nested type;
handles clear on status changes.
> - **Selectors**:
> - `selectPredictPendingDepositByAddress` returns `string | undefined`
(was `boolean | false`).
> - **Tests**:
> - Update deposit tests to expect batch IDs and `undefined` after
clear; add cases for preserving state on different `batchId` and
replacing old batch on new deposit.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4c554f3. 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?
-->

This PR addresses two issues related to the Card feature and onboarding
experience:
- Delegation refresh issue: After completing a successful delegation,
some data were not properly updated when navigating back to the CardHome
screen. This fix ensures all relevant data refresh correctly to reflect
the latest state.
- KYC WebView permissions: Removed a property that was preventing the
KYC WebView during onboarding from requesting camera and microphone
access, restoring the expected behavior for KYC verification.

## **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: Data not refreshing properly on CardHome after
successful delegation
CHANGELOG entry: KYC WebView not requesting camera and microphone access
during onboarding

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a post-delegation delay and cache clear to refresh Card data,
consolidates loading/navigation handling, removes token priority update,
and re-enables KYC camera/mic prompts.
> 
> - **Card — Spending Limit
(`app/components/UI/Card/Views/SpendingLimit/SpendingLimit.tsx`)**:
> - Aggregate loading state via `isProcessing` + `isDelegationLoading`
(`isLoading`); block back/cancel while loading; update button
`disabled`/`loading` states.
> - On confirm: validate SDK (error toast if missing), submit
delegation, wait 3s,
`dispatch(clearCacheData('card-external-wallet-details'))`, show success
toast, then navigate back.
> - Remove token priority update flow and related utilities; simplify
logic.
> - **Tests (`SpendingLimit.test.tsx`)**:
> - Remove token-priority mocks/tests; adjust expectations to await 3s
delay, cache clear, success toast, and navigation.
>   - Add/modify loading and navigation blocking/cancel behavior tests.
> - **Onboarding — KYC WebView
(`app/components/UI/Card/components/Onboarding/KYCWebview.tsx`)**:
> - Remove `mediaCapturePermissionGrantType` to allow camera/microphone
permission prompts.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4e1ae30. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…9.0 (#22521)

## **Description**

Bumping multichain accounts deps (and other related peers).

The main major change is for the `multichain-account-service` that will
now report errors to sentry when anything goes wrong for automatic
account creations.

The other change (that was already covered here) is the
`MultichainAccountService.init` which is now `async`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

N/A

## **Manual testing steps**

N/A

## **Screenshots/Recordings**

### **Before**

### **After**

## **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]
> Upgrades multichain account service and related controllers to latest
majors and allows `ErrorReportingService:captureException` in the
service messenger.
> 
> - **Engine/Messenger**:
> - Permit `ErrorReportingService:captureException` in
`getMultichainAccountServiceMessenger`.
> - **Dependencies**:
>   - Bump `@metamask/multichain-account-service` to `^3.0.0`.
>   - Bump `@metamask/account-tree-controller` to `^3.0.0`.
>   - Bump `@metamask/assets-controllers` to `^88.0.0`.
>   - Bump `@metamask/earn-controller` to `^10.0.0`.
>   - Update corresponding peer deps in `yarn.lock`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
05c9641. 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**

- Bunch of minor visual tweaks from the earlier bug bash

<!--
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: NA

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

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

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Tightens recurrence visibility and tweaks icon size and divider color
across Predict UI.
> 
> - **Predict UI tweaks**:
> - Show recurrence only when `market.recurrence !== Recurrence.NONE` in
`PredictMarketMultiple`.
> - Reduce empty-state illustration to `72x72` in
`PredictPositionEmpty`.
> - Change divider to `bg-default` in `PredictPositionsHeader` before
unrealized PnL section.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
89e36d8. 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?
-->

trigger `Release PR Approval` action on PR approval that target
`release/` branches

## **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]
> Adds a `pull_request_review` (submitted) trigger to the `Release PR
Approval` GitHub Actions workflow.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0580a5f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: sethkfman <10342624+sethkfman@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**

This PR adds local geoblocking functionality for Germany (DE) and
Romania (RO) to the Predict feature.

**What is the reason for the change?**
The Predict feature needs to comply with regional regulations by
restricting access for users in specific countries. While the provider
(Polymarket) performs its own eligibility checks, we need an additional
layer of local geoblocking to ensure compliance.

**What is the improvement/solution?**

- Created a new constants file (`geoblock.ts`) that defines the list of
geo-blocked countries
- Added a private method `isLocallyGeoblocked()` to check if a user's
country is in the blocked list
- Modified the `refreshEligibility()` method to apply local geoblocking
after the provider's eligibility check
- When a provider returns `isEligible: true` but the country is in our
blocked list, we override it to `isEligible: false`
- The user's country code is preserved in the state for tracking and
analytics purposes

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict geoblocking for DE and RO

  Scenario: user from Germany is blocked from using Predict
    Given app is running with Predict feature enabled
    And user's location is detected as Germany (DE)

    When user attempts to access Predict feature
    Then user sees geoblocking message indicating feature is not available in their region

  Scenario: user from Romania is blocked from using Predict
    Given app is running with Predict feature enabled
    And user's location is detected as Romania (RO)

    When user attempts to access Predict feature
    Then user sees geoblocking message indicating feature is not available in their region

  Scenario: user from United States can access Predict
    Given app is running with Predict feature enabled
    And user's location is detected as United States (US)

    When user attempts to access Predict feature
    Then user successfully accesses the Predict feature

  Scenario: provider blocks user but local check passes
    Given app is running with Predict feature enabled
    And provider's eligibility check returns ineligible

    When user attempts to access Predict feature
    Then user sees geoblocking message regardless of local geoblocking status
```

## **Screenshots/Recordings**

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

### **Before**

<!-- No geoblocking - users from DE and RO could access Predict if
provider allowed -->

### **After**

<!-- Users from DE and RO are blocked even if provider allows access -->

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

---

## **Test Coverage**

This PR includes comprehensive unit and integration tests:

### Unit Tests (7 tests)

- `isLocallyGeoblocked()` method with DE, RO, and non-blocked countries
- Edge cases: empty string, lowercase, extra spaces, partial matches

### Integration Tests (7 tests)

- `refreshEligibility()` with local geoblocking logic
- Provider eligible + locally blocked countries (DE, RO)
- Provider eligible + allowed countries (US)
- Provider ineligible scenarios
- Edge cases: undefined, null, empty string countries

### Constants Tests (4 tests)

- Validation of GEO_BLOCKED_COUNTRIES array structure and contents

**Total: 18 new tests, all passing ✅**

### Files Changed

- `app/components/UI/Predict/constants/geoblock.ts` (new file)
- `app/components/UI/Predict/controllers/PredictController.ts`
(modified)
- `app/components/UI/Predict/controllers/PredictController.test.ts`
(tests added)
- `app/components/UI/Predict/constants/geoblock.test.ts` (new test file)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces a local geo-block list (DE, RO) and updates
PredictController to override provider eligibility based on it, with
comprehensive unit tests.
> 
> - **PredictController (`controllers/PredictController.ts`)**:
> - Add `GEO_BLOCKED_COUNTRIES` import and private
`isLocallyGeoblocked()`.
> - Update `refreshEligibility()` to override provider `isEligible` to
false when country is locally blocked; preserve `country` in state.
> - **Constants (`constants/geoblock.ts`)**:
>   - New `GEO_BLOCKED_COUNTRIES` list with `DE` and `RO`.
> - **Tests**:
>   - New `constants/geoblock.test.ts` validating structure and entries.
> - Expanded `PredictController.test.ts` covering local geoblocking
flows (DE/RO block, allowed countries, undefined/null/empty), and
`isLocallyGeoblocked` edge cases.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
84cfbae. 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 adds a new cursor rule to enforce consistent feature flag usage
across the codebase. The rule prevents developers from creating new
feature flag selectors using `createSelector` and instead requires them
to use the `useFeatureFlag` hook.

**Reason for change:**
- The codebase has multiple patterns for accessing feature flags
(selectors vs hooks), leading to inconsistency
- New feature flag selectors are being created in various locations,
making it harder to maintain and migrate to a unified approach
- The `useFeatureFlag` hook provides a cleaner, more React-friendly API
for accessing feature flags in components

**Improvement/solution:**
- Added `.cursor/rules/feature-flag-guidelines.mdc` that automatically
applies to all files
- The rule explicitly forbids creating new `createSelector` instances
for feature flags
- The rule enforces using the `useFeatureFlag` hook from
`app/components/hooks/FeatureFlags/useFeatureFlag.ts`
- Provides clear examples of forbidden patterns and required patterns
- Includes migration guidance for existing code

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

Feature: Feature flag guidelines enforcement

  Scenario: developer attempts to create a new feature flag selector
Given a developer is working on a new feature that requires a feature
flag
When they try to create a new selector using createSelector for the
feature flag
Then the cursor rule should warn/prevent this pattern and suggest using
useFeatureFlag hook instead

  Scenario: developer uses useFeatureFlag hook correctly
    Given a developer needs to access a feature flag in a component
When they use the useFeatureFlag hook with a FeatureFlagNames enum value
Then the cursor rule should not flag any issues and the code should work
as expected## **Screenshots/Recordings**

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

### **Before**

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

N/A - This is a development tooling change that doesn't affect the UI.

### **After**

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

N/A - This is a development tooling change that doesn't affect the UI.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).

- [x] I've completed the PR template to the best of my ability

- [x] I've included tests if applicable (N/A - cursor rule file, no
tests needed)

- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable (N/A - markdown documentation file)

- [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 a Cursor rule that mandates using the `useFeatureFlag` hook and
forbids creating new `createSelector`-based feature flag selectors.
> 
> - **Tooling/Rules**:
>   - Add `/.cursor/rules/feature-flag-guidelines.mdc`:
> - Enforces using `useFeatureFlag` and forbids new `createSelector`
feature flag selectors.
> - Includes usage steps, migration guidance, enforcement criteria, and
a single exception for `selectRemoteFeatureFlags`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
50faa30. 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**
In this PR: 
- I enabled EAS updates for internal users. That's is all envs except
for production and dev. However, with check automatically set to false,
the users will not receive updates.
- Fix Rive Animation issues on Android and iOS based on the PRs below
iOS: rive-app/rive-react-native#344
Android:  rive-app/rive-react-native#389
 



Builds:
https://app.bitrise.io/app/be69d4368ee7e86d/pipelines/fd79ecf5-0141-4a3f-91ab-cd9681648fe4
## **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:Enabled EAS updates for preview channel

## **Related issues**

Fixes:Rive animation with EAS updates introduced

## **Manual testing steps**

```gherkin
Feature: my feature name

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

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

## **Screenshots/Recordings**

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

### **Before**

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

### **After**

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

## **Pre-merge author checklist**

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

## **Pre-merge reviewer checklist**

- [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]
> Enables EAS updates on the preview channel (no auto-check), surfaces
OTA details in App Information, and patches Rive to load file:// assets
on iOS/Android.
> 
> - **OTA Updates**:
> - Enable EAS Updates for `preview` channel with `runtimeVersion`,
`updateUrl`, and `checkAutomatically: NEVER` via
`scripts/update-expo-channel.js` (updates Android `meta-data` and iOS
`Expo.plist`).
>   - Add `UPDATE_URL` export in `app/constants/ota.ts`.
> - **Settings UI**:
> - App Information view now displays `Expo Project ID`, `Update ID`,
`channel`, `runtimeVersion`, `OTA Update URL`, `Check Automatically`,
and status when revealed.
>   - Tests added to verify OTA info visibility and values.
> - `expo-updates` mock extended with `url`, `checkAutomatically`, and
resolved async methods.
> - **Rive Animation (patch)**:
> - Android: replace Volley-only path with `ResourceLoader` factory
supporting `file://` (direct FS) and HTTP (Volley).
> - iOS: split URL asset loading into file vs remote handlers; relax URL
validation to allow file URLs.
>   - Apply Yarn patch to `rive-react-native@9.3.4` in `package.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7b1d329. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
@pull pull Bot locked and limited conversation to collaborators Nov 12, 2025
@pull pull Bot added the ⤵️ pull label Nov 12, 2025
@pull pull Bot merged commit a4afa90 into Reality2byte:main Nov 12, 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.