chore(runway): cherry-pick fix: compliance modal appear once on asset page cp-7.74.0#29208
Merged
Merged
Conversation
… page cp-7.74.0 (#29201) <!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **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? --> On the token details (spot assets) page, tapping **Long** or **Short** when a wallet is OFAC-blocked would open the `AccessRestrictedModal` correctly the first time, but pressing either button again would do nothing — the modal could never be reopened without leaving and re-entering the screen. **Root cause:** `TokenDetailsActions` sets a `navigationLockRef` to `true` on every button tap to prevent rapid double-navigation. It is cleared by three paths: screen refocus, navigation state change, or an explicit `resetNavigationLockRef` callback passed in from the parent. When `useComplianceGate`'s `gate()` detects a blocked wallet it shows `AccessRestrictedModal` (rendered at the app root by `AccessRestrictedProvider`) and returns early — no navigation occurs, the screen never blurs, and the external reset was never called. The lock stayed `true` permanently, silently swallowing all subsequent Long/Short presses. **Fix:** Added `.finally(() => resetNavigationLockRef.current?.())` to both `handleLongPress` and `handleShortPress` in `AssetOverviewContent.tsx`. This mirrors what the geo-block path already does inside `closeEligibilityModal`. The call is a safe no-op when `handlePerpsAction` navigates away, since the focus/state listeners also clear the lock in that case. Additionally, `AccessRestrictedModal` was migrated from the legacy internal `BottomSheet` component to the `BottomSheet` exported by `@metamask/design-system-react-native`, which is the single source of truth for bottom sheets in the codebase. The `shouldNavigateBack={false}` prop was also removed — the design-system `BottomSheet` does not expose this prop and the modal is rendered at the app root so no back-navigation is possible regardless. ## **Changelog** CHANGELOG entry: Fixed an issue where the access-restricted compliance modal could not be reopened after being dismissed on the token details page. ## **Related issues** No issue: bug fix for observed regression on the compliance-gated Long/Short buttons on the token details screen. ## **Manual testing steps** ```gherkin Feature: Access-restricted compliance modal on the token details page Background: Given I am logged into MetaMask Mobile And my wallet address is flagged as OFAC-blocked (compliance check returns blocked) And I am on the token details page for a token that has a Perps market (e.g. ETH) Scenario: user can reopen the compliance modal after dismissing it Given I see the Long and Short action buttons When user taps the Long button Then the access-restricted bottom sheet modal appears When user dismisses the modal by tapping the close button Then the modal is dismissed When user taps the Long button again Then the access-restricted bottom sheet modal appears again Scenario: user can open the compliance modal via the Short button after a previous dismissal Given I see the Long and Short action buttons When user taps the Short button Then the access-restricted bottom sheet modal appears When user dismisses the modal by tapping the close button Then the modal is dismissed When user taps the Short button again Then the access-restricted bottom sheet modal appears again ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Low Risk** > Low risk bug fix that only adjusts button press flow and a modal implementation; main risk is unintended double-tap navigation if the lock is cleared too aggressively. > > **Overview** > Fixes an issue where `Long`/`Short` on the token details screen could only open the compliance access-restricted modal once by ensuring the `TokenDetailsActions` navigation lock is always released when `useComplianceGate().gate()` completes (including non-navigating paths). > > Migrates `AccessRestrictedModal` to use the design-system `BottomSheet` component and removes the unsupported `shouldNavigateBack` prop. Adds tests to assert repeated `Long`/`Short` presses re-invoke `gate()` when it resolves without navigating. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 5a47cb7. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
Contributor
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Contributor
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - PR targets a release branch (release/*) All E2E tests pre-selected. |
|
Contributor
|
✅ E2E Fixture Validation — Schema is up to date |
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.



Description
On the token details (spot assets) page, tapping Long or Short
when a wallet is OFAC-blocked would open the
AccessRestrictedModalcorrectly the first time, but pressing either button again would do
nothing — the modal could never be reopened without leaving and
re-entering the screen.
Root cause:
TokenDetailsActionssets anavigationLockReftotrueon every button tap to prevent rapid double-navigation. It iscleared by three paths: screen refocus, navigation state change, or an
explicit
resetNavigationLockRefcallback passed in from the parent.When
useComplianceGate'sgate()detects a blocked wallet it showsAccessRestrictedModal(rendered at the app root byAccessRestrictedProvider) and returns early — no navigation occurs,the screen never blurs, and the external reset was never called. The
lock stayed
truepermanently, silently swallowing all subsequentLong/Short presses.
Fix: Added
.finally(() => resetNavigationLockRef.current?.())toboth
handleLongPressandhandleShortPressinAssetOverviewContent.tsx. This mirrors what the geo-block path alreadydoes inside
closeEligibilityModal. The call is a safe no-op whenhandlePerpsActionnavigates away, since the focus/state listeners alsoclear the lock in that case.
Additionally,
AccessRestrictedModalwas migrated from the legacyinternal
BottomSheetcomponent to theBottomSheetexported by@metamask/design-system-react-native, which is the single source oftruth for bottom sheets in the codebase. The
shouldNavigateBack={false}prop was also removed — the design-systemBottomSheetdoes not expose this prop and the modal is rendered at theapp root so no back-navigation is possible regardless.
Changelog
CHANGELOG entry: Fixed an issue where the access-restricted compliance
modal could not be reopened after being dismissed on the token details
page.
Related issues
No issue: bug fix for observed regression on the compliance-gated
Long/Short buttons on the token details screen.
Manual testing steps
Screenshots/Recordings
Before
N/A
After
N/A
Pre-merge author checklist
Docs and MetaMask Mobile
Coding
Standards.
if applicable
guidelines).
Not required for external contributors.
Performance checks (if applicable)
SRPs
to import wallets with many accounts and tokens
performance metrics
trace()for usage andaddTokenfor an example
For performance guidelines and tooling, see the Performance
Guide.
Pre-merge reviewer checklist
app, test code being changed).
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Note
Low Risk
Low risk bug fix that only adjusts button press flow and a modal
implementation; main risk is unintended double-tap navigation if the
lock is cleared too aggressively.
Overview
Fixes an issue where
Long/Shorton the token details screen couldonly open the compliance access-restricted modal once by ensuring the
TokenDetailsActionsnavigation lock is always released whenuseComplianceGate().gate()completes (including non-navigating paths).Migrates
AccessRestrictedModalto use the design-systemBottomSheetcomponent and removes the unsupportedshouldNavigateBackprop. Adds tests to assert repeated
Long/Shortpresses re-invokegate()when it resolves without navigating.Reviewed by Cursor Bugbot for commit
5a47cb7. Bugbot is set up for automated
code reviews on this repo. Configure
here.