[pull] main from MetaMask:main#302
Merged
Merged
Conversation
<!-- 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** - Reduce padding in network fee item when fee is included - Fix padding issues of the selected token row in Select Token modal. - Fix issues with some native token images rendered with bigger size in Select Token modal. - Apply the correct navigation title style. <!-- 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: Various UI fixes on swap component. ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/SWAPS-3337 ## **Manual testing steps** ```gherkin Validate that the correct styles are applied and rendered based on the provided screenshots. ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <img width="430" height="51" alt="Screenshot 2025-10-30 at 6 58 44 PM" src="https://github.com/user-attachments/assets/ecdf0f18-dca2-4af3-83bc-d460d1db61c5" /> <img width="430" height="93" alt="Screenshot 2025-10-30 at 6 59 47 PM" src="https://github.com/user-attachments/assets/9f333e80-cee2-414b-9708-5c1ae3735af3" /> <img width="430" height="277" alt="Screenshot 2025-10-30 at 7 02 27 PM" src="https://github.com/user-attachments/assets/fb8c2ab2-55d6-416e-9ef5-a81296defcfa" /> <!-- [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] > Refines Bridge UI typography/padding, standardizes label casing, adjusts native token icon sizes, and adds a toSentenceCase util with tests and e2e updates. > > - **Bridge UI/Styling**: > - `TokenButton`: switch symbol text to `HeadingLG`, use themed size and `fontWeight: 500`. > - Token symbol text in `BridgeView` snapshots updated (`lineHeight` 32, `fontWeight` 500). > - **Token Selectors**: > - `TokenSelectorItem`: fix selected row alignment (`selectedItemWrapperReset`), constrain native token icon to `32x32`, keep badge wrapper alignment. > - Snapshot updates for source/dest selectors reflecting `{}` style, icon sizing, and layout tweaks. > - **Quote Details**: > - Use `toSentenceCase` for labels (`network_fee`, `minimum_received`, `price_impact`, `points`). > - Slippage row: move edit icon before value and change icon color to `Alternative`; tighten spacing in included network fee row (`gap` 2). > - **Tooltip & Navbar**: > - `TooltipModal`: reduce horizontal padding and change title variant to `HeadingSM`. > - `NavbarTitle`: change title variant to `HeadingSM`. > - **Utils/Tests/E2E**: > - Add `toSentenceCase` in `app/util/string` with comprehensive tests. > - Update e2e selectors to use sentence-cased `NETWORK_FEE`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 890fe0e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…2246) ## **Description** This PR refactors Perps selectors and utility functions for better performance and code quality: **Reason for change:** 1. The `selectTradeConfiguration` selector was creating new object references on every call, causing unnecessary re-renders and breaking React dependency tracking in `useMemo`/`useEffect` 2. Manual string matching for EVM account type checking (`account.type.startsWith('eip155:')`) was fragile and not using official MetaMask utilities **Solution:** 1. Converted `selectTradeConfiguration` to use `createSelector` from reselect for memoization, ensuring stable object references 2. Replaced manual string matching with official `isEvmAccountType` utility from `@metamask/keyring-api` **Impact:** - Eliminates unnecessary component re-renders - Better React dependency tracking - More maintainable code using official utilities - Added null safety checks ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: TAT-2025 ## **Manual testing steps** ```gherkin Feature: Perps selector and utility refactoring Scenario: verify no behavioral changes Given the Perps feature is accessible When user accesses any Perps functionality (order placement, watchlist, configuration) Then all functionality works identically to before And no visual changes are observed And no errors appear in console ``` **Automated Testing:** All existing tests pass without modification: - � Selector tests: 19/19 passed - � Account utils tests: 5/5 passed - � Wallet service tests: 24/24 passed ## **Screenshots/Recordings** ### **Before** N/A - Internal refactoring only, no UI changes ### **After** N/A - Internal refactoring only, no UI changes ## **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 (all existing tests pass) - [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. --- ## **Technical Details** ### Files Changed (4 files): 1. **app/components/UI/Perps/controllers/selectors.ts** - Added `createSelector` import from reselect - Converted `selectTradeConfiguration` to memoized selector with 3 input selectors - Returns stable object references: `{ leverage?: number } | undefined` 2. **app/components/UI/Perps/controllers/selectors.test.ts** - No changes needed (tests already compatible) 3. **app/components/UI/Perps/utils/accountUtils.ts** - Added `isEvmAccountType` import from `@metamask/keyring-api` - Replaced `account.type.startsWith('eip155:')` with `isEvmAccountType(account.type)` - Added null safety: `account && isEvmAccountType(account.type)` 4. **app/components/UI/Perps/services/HyperLiquidWalletService.test.ts** - Added mock for `@metamask/keyring-api` to prevent import errors - Mock matches existing test data (`'eip155:1'`) ### Risk Assessment =� **Very Low Risk** - Pure refactoring with zero behavioral changes - All existing tests pass without modification - No API contract changes - Comprehensive test coverage <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Memoizes perps trade config selector and switches EVM account detection to keyring-api utility, with tests updated to mock the new import. > > - **Controllers (`controllers/selectors.ts`)**: > - Refactor `selectTradeConfiguration` to a memoized `createSelector`, returning stable `{ leverage } | undefined` per network/coin. > - **Utils (`utils/accountUtils.ts`)**: > - Replace string prefix check with `isEvmAccountType` for EVM account detection, with null-safety. > - **Tests (`services/HyperLiquidWalletService.test.ts`)**: > - Add mock for `@metamask/keyring-api` (`isEvmAccountType`) to prevent import issues. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit dbd08fe. 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 removes the use of `selectMultichainAccountsState2Enabled` from the BIP-44 intro modal. ## **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: None ## **Manual testing steps** N/A ## **Screenshots/Recordings** N/A ## **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] > Removes the feature-flag dependency from the Multichain Accounts intro modal logic and updates tests to rely only on seen state and version update boundaries. > > - **Hook (`app/components/hooks/useMultichainAccountsIntroModal.ts`)**: > - Remove `selectMultichainAccountsState2Enabled` usage, related condition, and dependency. > - Modal now shows only when `!hasSeenIntroModal` and app updates across the 7.56 → 7.57 boundary. > - Drop `isMultichainAccountsState2Enabled` from returned state and dependencies. > - **Tests (`app/components/hooks/useMultichainAccountsIntroModal.test.ts`)**: > - Remove feature-flag setup/assertions and the "feature disabled" case. > - Update initial state and expectations to cover only seen-state and version-boundary scenarios. > - Keep navigation assertions and version matrix validating boundary logic. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4807ed3. 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** Implement useRampNavigation hook that navigates the user to the appropriate ramp flow. This hook exports a goToRamps method that can be used in every endpoint to navigate to either Aggregator or Deposit accordingly. <!-- 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: https://consensyssoftware.atlassian.net/browse/TRAM-2814?atlOrigin=eyJpIjoiNGUwNjI3YTJkYzQ2NGM5YzkxYzI5YWJkN2ZhZjliZTciLCJwIjoiaiJ9 ## **Manual testing steps** N/A ## **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 `useRampNavigation` to navigate to aggregator (buy/sell) or deposit flows, with early return when Unified V1 is enabled, plus unit tests. > > - **Hooks**: > - Introduces `useRampNavigation` providing `goToRamps` to route based on `RampMode`. > - Routes to `createBuyNavigationDetails` or `createSellNavigationDetails` for `AGGREGATOR` (defaulting to `BUY`), passing optional `intent`. > - Routes to `createDepositNavigationDetails` for `DEPOSIT`, passing params. > - Early-returns (no navigation) when `useRampsUnifiedV1Enabled` is true. > - **Tests**: > - Adds `useRampNavigation.test.ts` covering default and explicit `BUY`/`SELL`, intent/params forwarding, `DEPOSIT` flow, and Unified V1 early-return behavior. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit caddf25. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## **Description** Before this PR, the silent auth function was calling the get opt in status endpoint (under some circumstances) for an individual address. This is fine if it's called in some places, but not so efficient when it's called for an entire account group via an auth trigger (i.e. account group changed). In this new implementation, we now do this in bulk before attempting to start calling silent auth for any account of the account group. We're also adding a new defined exception for when the season state returns a 404. In this case we also clear some of the state in the app. ## **Changelog** CHANGELOG entry: null ## **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] > Prefetches bulk opt-in status for account groups, makes silent-auth skip token-aware, and throws/handles SeasonNotFound by clearing season cache. > > - **RewardsController**: > - Prefetch `getOptInStatus` for sorted accounts before running per-account silent auth. > - Make `shouldSkipSilentAuth` async and require valid session token when `hasOptedIn` is true. > - Await async skip check in `performSilentAuth`. > - On `SeasonNotFoundError` in `getSeasonStatus`, clear `state.seasons` and rethrow. > - **RewardsDataService**: > - Add `SeasonNotFoundError`; throw when 404 message indicates season not found in `getSeasonStatus`. > - **Tests**: > - Update tests to await async `shouldSkipSilentAuth`, validate token checks, and add coverage for `SeasonNotFoundError` handling. > - Adjust mocks to support new call flow (bulk opt-in status, token retrieval). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fdd6b1a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
…22048) <!-- 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** Fix an issue where on Solana blockchain swaps, upon navigating to transaction screen, users where informed that the swap lives in two blockchains, while it should redirect them to Solscan upon clicking "View on Block Explorer". <!-- 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: Fix issue where Solana swaps incorrectly displayed as cross-chain; ensure “View on Block Explorer” redirects to Solscan. ## **Related issues** Fixes: #18136 ## **Manual testing steps** ```gherkin Feature: Same-chain Solana swap transaction details Scenario: user views block explorer for a same-chain Solana swap transaction Given the user has completed a same-chain swap on Solana (SOL to USDC) And the transaction is visible in the activity tab When user navigates to the transaction details And user clicks "View on Block Explorer" button Then the app opens an integrated browser tab with the Solscan transaction URL And the cross-chain bridge modal is NOT displayed ``` ## **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] > Use source tx hash to open the block explorer directly for same-chain swaps, including Solana, and add tests/mocks to cover this behavior. > > - **Bridge Transaction Details**: > - Use `bridgeTxHistoryItem.status.srcChain.txHash` (fallback to `evmTxMeta.hash`) to build explorer URL for swaps via `useMultichainBlockExplorerTxUrl`. > - "View on Block Explorer" now navigates directly to browser for swaps; retains modal for bridges. > - **Tests**: > - Add test ensuring same-chain Solana swap opens browser with URL containing the Solana tx hash. > - Update mocks and imports; rename `mockTx` to `mockEVMTx` and add `mockMultiChainTx`. > - **Mocks/State**: > - Extend `_mocks_/initialState.ts` with a `solana-swap-tx` entry to simulate a Solana same-chain swap. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 3dd3656. 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** Fixes a discrepancy where the funding rate shown in the Perps markets list differed from the asset detail screen. The detail screen used live WebSocket data and `formatFundingRate()`, while the list used static data and manual formatting. ## **Changelog** CHANGELOG entry: Fixed funding rate display inconsistency between Perps markets list and asset detail screen ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1975 ## **Manual testing steps** ```gherkin Feature: Perps funding rate display consistency Scenario: funding rate matches between markets list and detail screen Given user is on the Perps markets list view And user has selected "Funding Rate" as the display metric When user views the funding rate for any market in the list Then the funding rate displayed matches the funding rate shown on the asset detail screen And the funding rate updates in real-time from WebSocket data ``` ## **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/11a1cf39-8077-4707-8498-db74f2391e68 ### **After** https://github.com/user-attachments/assets/d5e10cf2-7bb8-404f-bf3c-286b1fccac47 <!-- [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] > Displays funding rate from live WebSocket data (even when price is unchanged) and formats it via formatFundingRate; adds comprehensive tests. > > - **PerpsMarketRowItem** (`PerpsMarketRowItem.tsx`): > - **Live data merge**: Update `market.fundingRate` from `livePrice.funding` and trigger updates even if `price` is unchanged. > - **Formatting**: Use `formatFundingRate` for `displayMetric="fundingRate"` for consistent 4-decimal percentage output. > - **Tests** (`PerpsMarketRowItem.test.tsx`): > - Add funding rate test suite covering positive/negative/zero, undefined/null, very small/large values, live updates, unchanged values, and `onPress` propagation of updated data. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e6329c6. 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**
Tron accounts controlled by feature flags
<!--
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: chore: Tron accounts controlled by feature flags
## **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 Tron accounts feature-flag gating with provider wrapper, runtime
toggling and wallet alignment; introduces selector/tests; includes Tron
in Metro features; bumps iOS bundle size threshold.
>
> - **Core (multichain account service)**
> - Wrap `TrxAccountProvider` with `AccountProviderWrapper` and
initialize via `isTronAccountsFeatureEnabled`.
> - Align wallets if any of `bitcoin`/`tron` is enabled initially;
subscribe to flag changes to toggle providers and align when enabled.
> - **Feature flags**
> - Add `app/multichain-tron/remote-feature-flag.ts` with
`isTronAccountsFeatureEnabled`.
> - New selector `selectIsTronAccountsEnabled` with unit tests.
> - **Tests**
> - Extend `multichain-account-service-init.test.ts` for Tron flag
scenarios; simplify Bitcoin assertions and reset spies between events.
> - **Build/CI**
> - Include `tron` in Metro main/beta feature sets.
> - Increase iOS JS bundle size threshold to `52`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
acba6f9. 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 several maintainability issues reported by SonarCloud: 🔗 [View related issues on SonarCloud](https://sonarcloud.io/project/issues?id=metamask-mobile&pullRequest=22058&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true) Additionally, it reverts a temporary workaround previously added for Android to prevent a crash occurring when users navigated through the KYC WebView. The root cause of the WebView crash has been resolved in a separate PR, making the temporary fix unnecessary. ## **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: Reverted temporary workaround for KYC WebView crash (issue resolved in upstream fix). ## **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] > Refactors Card features: rewrites asset selection and balance logic, unifies KYC verification navigation to WebView, tightens onboarding routing, improves SDK/logging, and adds extensive tests. > > - **Card Home**: > - Add `enableCardAction` tests covering success/failure/loading paths; mock `Logger.log`. > - Log errors in `enableCardAction` catch. > - **Asset Selection Bottom Sheet**: > - Major refactor with helper utilities (network filtering, token mapping/deduping, CAIP handling, sorting by priority/allowance). > - Integrate balances via `useAssetBalances`; show allowance state text; improve list rendering and Solana footer. > - Preserve existing navigation and priority update, and allow Limited tokens to update priority directly. > - **Balances (`useAssetBalances`)**: > - Extract helpers; improve fiat calculation (market data, Solana rates, proportional fallback), normalization, and asset building. > - Update tests with extensive scenarios (enabled/limited/not-enabled, fallbacks, edge cases). > - **Onboarding/KYC**: > - Verify Identity: always navigate to WebView; simplify tests; add screen view metric. > - OnboardingNavigator: require `firstName` and `countryOfNationality` before address; update tests. > - Types: add `countryOfNationality` to `UserResponse`. > - **SDK**: > - Improve error logging/handling (external wallet details, provision card); simplify network-to-CAIP mapping; minor cleanup. > - **Priority/External Wallet Hooks**: > - Extract `determineAllowanceState`; use nullish coalescing where applicable; add tests for warnings and fetching behaviors. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 94c9b08. 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 aims to fix BTC amount validation in send flow. As we will implement `onAmountInput` validations - this is a temporary fix to handle it in the client code. In near future this validation will be handled in snap repository. ## **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: #22204 ## **Manual testing steps** 1. Go send flow 2. Pick BTC 3. Try sending lower than 0.0001 4. You shouldn't be able to proceed to recipient page ## **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] > Enforces a 0.0001 BTC minimum in send amount validation and adds tests for BTC thresholds. > > - **Validation**: > - Update `useAmountValidation` to use `useSendType` and `bignumber.js` to enforce a Bitcoin minimum amount of `0.0001`. > - Add temporary Bitcoin-specific check returning `strings('send.invalid_value')` when below threshold. > - Update memo dependencies to include `isBitcoinSendType`. > - **Tests**: > - Extend `useAmountValidation.test.ts` to mock `useSendType` and cover BTC amounts below, at, and above the minimum threshold. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ab9acac. 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?
-->
Some small changes:
- Fix eslint warnings
- Remove unnecessary comments
- Refactor state update for predict balance
## **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**
- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Fixes ESLint warnings across hooks/views, refactors `getBalance` cache
update, and streamlines tests/mocks (including unskipping market data
test).
>
> - **PredictController**:
> - Refactor `getBalance` cache update to safely initialize
`state.balances[providerId]` before setting `address` entry.
> - **Hooks**:
> - Add targeted ESLint-disable lines for React hook deps in
`usePredictBalance`, `usePredictPositions`, `usePredictPriceHistory`,
`useUnrealizedPnL`.
> - Views (`PredictBuyPreview`, `PredictSellPreview`): add
ESLint-disable on empty deps effects.
> - **Tests**:
> - Unskip and run `usePredictMarketData` success test.
> - Clean up withdraw tests by removing obsolete eligibility comments;
keep behavior intact.
> - Normalize mock naming (`MockedEngine`, `MockedPredictActivityType`)
and minor mock adjustments in transactions/activity tests.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7125c5f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ay (#22248) ## **Description** This PR improves the user experience of the Perps trading interface by adding skeleton placeholder loading states and fixing the rewards points display to prevent "undefined" from appearing in the UI. ### What is the reason for the change? **Problem 1: No Loading Feedback** - Users experienced no visual feedback during long-running operations (amount optimization, fee calculation) - This created perception of slow/broken UI and risk of double-submission - Blank spaces appeared during data loading **Problem 2: Rewards Display Showing "undefined"** - Rewards points row was displaying even when `estimatedPoints` was `undefined` - "undefined" text was visible in production - Only checked `shouldShowRewardsRow` flag, not the actual data value ### What is the improvement/solution? **Loading States:** - Added `isLoading` prop to `PerpsAmountDisplay` component - Implemented skeleton placeholder (80x20px) during amount optimization - Fee display now shows "--" during calculation instead of blank space **Rewards Fix:** - Added compound condition: `shouldShowRewardsRow && estimatedPoints !== undefined` - Rewards row only appears when data is valid - Eliminates "undefined" text from appearing in UI ## **Changelog** CHANGELOG entry: Added skeleton loading states for amount optimization and fee calculation, fixed rewards points display to prevent undefined values ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2024 ## **Manual testing steps** ```gherkin Feature: Perps Order Loading States Scenario: user enters order amount Given user is on the Perps order view And the order form is empty When user enters an amount and closes the keypad Then a skeleton placeholder should appear during amount optimization And the fee display should show "--" during calculation And no blank spaces should appear Scenario: user views rewards points Given user is on the Perps order view And user has entered a valid order amount When rewards calculation completes successfully Then rewards points row should appear with valid point value When rewards calculation fails or returns undefined Then rewards points row should not appear And "undefined" text should never be visible ``` ## **Screenshots/Recordings** ### **Before** - No loading feedback during optimization (blank display) - Fee calculation showed blank space - Rewards row showed "undefined" when data was unavailable - Users clicking multiple times due to lack of feedback ### **After** - Skeleton placeholder appears during amount optimization (professional loading UX) - Fee display shows "--" during calculation (clear loading state) - Rewards row only appears when points data is valid (no "undefined" text) - Clear visual feedback prevents user confusion ## **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 (UI changes, existing tests cover functionality) - [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. --- ## **Technical Details** ### Files Modified 1. **`PerpsAmountDisplay.tsx`** - Added `isLoading?: boolean` prop to interface - Imported `SkeletonPlaceholder` from 'react-native-skeleton-placeholder' - Implemented conditional skeleton rendering (80x20px, 4px border radius) 2. **`PerpsOrderView.tsx`** - Passed `isLoading={!hasValidAmount || feeResults.isLoadingMetamaskFee}` to PerpsAmountDisplay - Updated fee display to check loading state and show fallback - Fixed rewards display condition to check both flag AND data value ### Risk Level =� **Low Risk** - UI-only changes, no business logic modifications ### Validation - � ESLint validation passed - � TypeScript validation passed - � All changes follow existing patterns in codebase ### Benefits - Clear feedback during loading (no user confusion) - Professional UX (standard loading pattern) - Improved perceived performance - Eliminates "undefined" text in UI - Clean rewards display (only when valid) - Prevents double-submission attempts <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds amount skeleton loading, shows fallback fees while loading/invalid, and hides rewards row unless points are defined. > > - **Perps UI**: > - **Amount**: `PerpsAmountDisplay` gains `isLoading` prop and skeleton placeholder; refactors display value calculation. > - **Fees**: In `PerpsOrderView`, `PerpsFeesDisplay` now shows `PERPS_CONSTANTS.FALLBACK_DATA_DISPLAY` when amount is invalid or `isLoadingMetamaskFee`, otherwise formats fees. > - **Rewards**: Rewards row renders only if `shouldShowRewardsRow` AND `estimatedPoints !== undefined`. > - **Wiring**: `PerpsOrderView` passes `isLoading={isLoadingAccount}` to `PerpsAmountDisplay`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 25ac425. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
# Geoblock Analytics Implementation
## Overview
This PR implements analytics tracking for geoblocking events in Predict,
allowing us to understand when and where users are blocked from
performing actions due to geographic restrictions.
CHANGELOG entry: null
## Changes
### 1. State Structure Refactoring
**Consolidated eligibility and geoblock data into a single nested
structure:**
```typescript
// Before
eligibility: { [key: string]: boolean }
geoBlockData: { [key: string]: { country?: string } }
// After
eligibility: {
[key: string]: {
eligible: boolean;
country?: string;
}
}
```
**Benefits:**
- Simplified state management - one source of truth
- Atomic updates - eligible status and country always in sync
- Easier to consume - no need to access two separate state objects
### 2. Analytics Event Implementation
**Event:** `PREDICT_GEO_BLOCKED_TRIGGERED`
**Properties:**
- `country` - The country code where the user is located (from geoblock
API)
- `attempted_action` - The action the user tried to perform
**Attempted Actions:**
- `deposit` - User tried to add funds
- `predict_action` - User tried to place a prediction
- `cashout` - User tried to cash out a position
- `claim` - User tried to claim winnings
- `withdraw` - User tried to withdraw funds (not currently guarded)
### 3. Integration Points
**Guarded Actions:**
All actions that require eligibility checks use `executeGuardedAction`
from `usePredictActionGuard` hook:
```typescript
executeGuardedAction(
() => {
// Action logic
},
{ attemptedAction: PredictEventValues.ATTEMPTED_ACTION.DEPOSIT }
);
```
**Components Updated:**
- ✅ `PredictBalance.tsx` - Add funds (deposit)
- ✅ `PredictAddFundsSheet.tsx` - Add funds (deposit)
- ✅ `PredictMarketDetails.tsx` - Buy (predict), Claim
- ✅ `PredictPositionsHeader.tsx` - Claim
- ✅ `PredictPositionDetail.tsx` - Cash out
- ✅ `PredictMarketSingle.tsx` - Buy (predict)
- ✅ `PredictMarketOutcome.tsx` - Buy (predict)
- ✅ `PredictMarketMultiple.tsx` - Buy (predict)
### 4. Controller Updates
**`PredictController.ts`:**
- `refreshEligibility()` - Now stores both `eligible` and `country`
together
- `trackGeoBlockedEvent()` - New method to track analytics when user is
blocked
- Updated to use consolidated eligibility state
**`usePredictEligibility.ts` hook:**
- Now returns both `isEligible` and `country`
- Simplifies component consumption
### 5. Testing
**All tests updated and passing:**
- ✅ PredictController tests (1687 tests)
- ✅ usePredictEligibility tests
- ✅ Component tests updated for new hook signature
- ✅ Test suites: 67 passed
## Data Flow
```
User Action Attempt
↓
executeGuardedAction
↓
Check eligibility (from state)
↓
Blocked? → Yes → trackGeoBlockedEvent(country, attemptedAction)
↓ ↓
No Analytics Event Sent
↓
Execute Action
```
## Analytics Dashboard
**To query geoblock events in the analytics dashboard:**
```sql
SELECT
country,
attempted_action,
COUNT(*) as blocked_count,
DATE(timestamp) as date
FROM events
WHERE event_name = 'PREDICT_GEO_BLOCKED_TRIGGERED'
GROUP BY country, attempted_action, DATE(timestamp)
ORDER BY blocked_count DESC
```
**Key Metrics:**
- Most blocked countries
- Most common blocked actions
- Trends over time
- Conversion rates by geography
## Example Event
```json
{
"event": "PREDICT_GEO_BLOCKED_TRIGGERED",
"properties": {
"country": "US",
"attempted_action": "deposit"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
```
## Files Changed
### Core Implementation
- `app/components/UI/Predict/controllers/PredictController.ts`
- `app/components/UI/Predict/hooks/usePredictEligibility.ts`
- `app/components/UI/Predict/hooks/usePredictActionGuard.ts`
- `app/components/UI/Predict/constants/eventNames.ts`
### Components
-
`app/components/UI/Predict/components/PredictBalance/PredictBalance.tsx`
-
`app/components/UI/Predict/components/PredictAddFundsSheet/PredictAddFundsSheet.tsx`
-
`app/components/UI/Predict/views/PredictMarketDetails/PredictMarketDetails.tsx`
-
`app/components/UI/Predict/components/PredictPositionsHeader/PredictPositionsHeader.tsx`
-
`app/components/UI/Predict/components/PredictPositionDetail/PredictPositionDetail.tsx`
-
`app/components/UI/Predict/components/PredictMarketSingle/PredictMarketSingle.tsx`
-
`app/components/UI/Predict/components/PredictMarketOutcome/PredictMarketOutcome.tsx`
-
`app/components/UI/Predict/components/PredictMarketMultiple/PredictMarketMultiple.tsx`
### Tests
- `app/components/UI/Predict/controllers/PredictController.test.ts`
- `app/components/UI/Predict/hooks/usePredictEligibility.test.ts`
-
`app/components/UI/Predict/components/PredictAddFundsSheet/PredictAddFundsSheet.test.tsx`
## Testing Instructions
### Manual Testing
1. **Setup geoblock scenario:**
- Use VPN or modify geoblock API response to return `isEligible: false`
2. **Test each action:**
- Try to deposit funds → Check analytics event sent
- Try to place a prediction → Check analytics event sent
- Try to cash out → Check analytics event sent
- Try to claim winnings → Check analytics event sent
3. **Verify analytics:**
- Open DevTools console
- Look for `📊 [Analytics] PREDICT_GEO_BLOCKED_TRIGGERED` logs
- Verify `country` and `attempted_action` are correct
### Automated Testing
```bash
# Run all Predict tests
yarn jest ./app/components/UI/Predict
# Run specific test suites
yarn jest app/components/UI/Predict/controllers/PredictController.test.ts
yarn jest app/components/UI/Predict/hooks/usePredictEligibility.test.ts
```
## Migration Notes
### State Migration
No migration required. The consolidated state structure is backward
compatible:
- Old state with empty `eligibility` object will work correctly
- `refreshEligibility()` will populate new structure on first call
### API Compatibility
No API changes required. The geoblock API response format remains the
same:
```typescript
interface GeoBlockResponse {
isEligible: boolean;
country?: string;
}
```
## Future Enhancements
1. **Enhanced Metrics:**
- Add `ip` to analytics (currently stored but not tracked)
- Track `region` for more granular insights
2. **User Education:**
- Show country-specific messaging
- Suggest alternative actions for blocked users
3. **Dashboard Integration:**
- Real-time geoblock monitoring
- Alerts for sudden spikes in blocked regions
## Checklist
- [x] State structure refactored and tested
- [x] Analytics event implemented
- [x] All guarded actions updated with `attemptedAction`
- [x] Tests updated and passing (67 suites, 1687 tests)
- [x] Dev logging added for debugging
- [x] Code follows project guidelines
- [x] No breaking changes
## Related Issues
- Tracking user geoblocking for compliance and UX insights
- Understanding geographic distribution of blocked actions
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Add geo-block analytics and migrate eligibility to include country,
wiring attemptedAction tracking across guarded Predict actions.
>
> - **Analytics**:
> - Add `PREDICT_GEO_BLOCKED_TRIGGERED` event and properties `country`
and `attempted_action`.
> - **State/Controller**:
> - Change `PredictController.state.eligibility` to `{ [providerId]: {
eligible: boolean; country?: string } }`.
> - Update `refreshEligibility()` to store country; add
`trackGeoBlockTriggered()`.
> - **Providers**:
> - Update `PredictProvider.isEligible()` to return `{ isEligible,
country }` via `GeoBlockResponse`.
> - Implement in `PolymarketProvider.isEligible()`.
> - **Hooks**:
> - `usePredictEligibility()` returns `{ isEligible, country }` (default
`false` when unset).
> - `usePredictActionGuard()` accepts `{ checkBalance, attemptedAction
}` and tracks geo-blocks when blocked.
> - **UI (guarded actions instrumented with `attemptedAction`)**:
> - `PredictAddFundsSheet`, `PredictBalance` → deposit.
> - `PredictMarketDetails`, `PredictMarketSingle`,
`PredictMarketOutcome`, `PredictMarketMultiple` → predict/buy, claim.
> - `PredictPositionsHeader` → claim; `PredictPositionDetail` → cashout.
> - **MetaMetrics**:
> - Register new event in `MetaMetrics.events`.
> - **Tests**:
> - Update controller, hooks, provider, and component tests for new
eligibility shape, geo-block tracking, and attemptedAction args.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e6d0566. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )