Skip to content

feat(predict): bPredict Bottom Sheet Errors PRED-836#29184

Merged
MarioAslau merged 8 commits into
mainfrom
predict/bottom-sheet-errors
Apr 27, 2026
Merged

feat(predict): bPredict Bottom Sheet Errors PRED-836#29184
MarioAslau merged 8 commits into
mainfrom
predict/bottom-sheet-errors

Conversation

@MarioAslau

@MarioAslau MarioAslau commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Description

When the predictBottomSheet feature flag is ON, this PR moves Predict buy-flow
error reporting out of the legacy PredictOrderRetrySheet overlay and the
generic background-failure toast and into inline banners rendered directly inside
the buy BottomSheet. It also auto-reopens the buy sheet with the right banner
when an order fails after backgrounding (e.g. ETH deposit-then-place flow).

When the flag is OFF, behavior is unchanged: the legacy retry sheet still opens
for not-fully-filled errors, and the failure toast still fires for background
failures.

Two banner variants:

  • price_changed (warning) - triggered by PREDICT_BUY_ORDER_NOT_FULLY_FILLED.
    Title: "Price changed". Body: "Couldn't buy at {price}. Try at market price?".
  • order_failed (error) - generic order failure / network / timeout after
    background processing. Title: "Order failed". Body: "Your order couldn't be
    filled. Try again?".

Both variants swap the primary CTA to "Retry"; tapping Retry re-runs
placeOrder with SLIPPAGE_BEST_AVAILABLE (matching the legacy retry-sheet
behaviour). On retry failure inside sheet mode the secondary
PredictOrderRetrySheet no longer stacks on top - the inline banner re-renders
in place.

Design: https://www.figma.com/design/gsBaqApTVELyFTNA70OwKg/Predict?m=dev&node-id=14938-29764

What changed

New component:

  • PredictBuyErrorBanner (app/components/UI/Predict/views/PredictBuyWithAnyToken/components/PredictBuyErrorBanner/) - styled inline banner with price_changed and order_failed variants. Built with Box/Text/Icon from @metamask/design-system-react-native and useTailwind().

Modified:

  • usePredictBuyError - returns a new buyErrorBanner object alongside errorMessage; maps order_not_filled to price_changed (with formatCents of preview?.sharePrice ?? outcomeTokenPrice ?? 0 so the body remains accurate even on auto-reopen when preview is briefly null) and other failures to order_failed. Also exposes clearBuyErrorBanner for sheet-dismiss/amount-change clearing. Accepts an isSheetMode flag (defaults to false) that gates the new behaviour: in sheet mode buyErrorBanner is populated and errorMessage suppresses the active-order error string; in legacy (full-screen) mode buyErrorBanner is always null and the active-order error is surfaced via errorMessage instead, preserving the pre-feature contract.
  • usePredictOrderRetry - accepts isSheetMode. In sheet mode it skips opening the legacy PredictOrderRetrySheet both on the initial becameNotFilled effect AND in the handleRetryWithBestPrice catch block (the second guard prevents the secondary sheet from stacking on retry failure).
  • PredictPreviewSheetContext - tracks provider-mount state and auto-reopens the buy sheet when activeOrder?.error flips on while no buy sheet is mounted, so background failures resurface inside the sheet rather than as a toast.
  • usePredictToastRegistrations - suppresses the order/failed toast when the flag is ON and the preview-sheet provider is mounted; the inline banner replaces it.
  • PredictBuyActionButton - accepts isRetry; swaps the label to "Retry" when an actionable banner is active.
  • PredictBuyWithAnyToken - renders PredictBuyErrorBanner between the fee summary and the action button; blurs the input/closes the keyboard when a banner becomes active in sheet mode so the Retry button is unobstructed; swaps the CTA label/handler when retry is required; passes outcomeTokenPrice and isSheetMode into usePredictBuyError so the banner/error-message gating is centralized in the hook (no leak of banner-driven button state into legacy mode).
  • PredictBuyPreview, Predict.testIds.ts, contexts/index.ts - small wiring updates.
  • locales/languages/en.json - new predict.order.price_changed_title, price_changed_body, and retry keys; tightened order_failed_body copy.

Tests:

  • New: PredictBuyErrorBanner.test.tsx, PredictPreviewSheetContext.test.tsx (auto-reopen), and added cases in usePredictBuyError.test.ts (banner variants, fallbacks, plus a legacy mode (isSheetMode: false) describe block asserting the legacy contract), usePredictOrderRetry.test.ts (sheet-mode effect + catch-block guards), usePredictToastRegistrations.test.tsx (toast suppression), PredictBuyActionButton.test.tsx (isRetry label), PredictBuyWithAnyToken.test.tsx (banner rendering + keyboard blur).
  • All existing tests in the touched files still pass.
  • yarn lint:tsc is clean.

Changelog

CHANGELOG entry: Added inline error banners in the Predict buy bottom sheet for price-changed and order-failed scenarios, replacing the secondary retry sheet and failure toast when the predictBottomSheet flag is enabled.

Related issues

Fixes:
JIRA Ticket: https://consensyssoftware.atlassian.net/browse/PRED-836?atlOrigin=eyJpIjoiZWM0M2E2YjZiOGJmNGMwOWFiZDMwNDBhM2UxMzc0OGUiLCJwIjoiaiJ9

Manual testing steps

Feature: Inline error banners in Predict buy bottom sheet (predictBottomSheet flag ON)

  Background:
    Given the user has the predictBottomSheet feature flag enabled
    And the user is on a Predict market with at least one outcome
    And the user has Predict balance funded enough to place a $1 bet

  Scenario: Price changed banner appears when the order is not fully filled
    Given an injected PREDICT_BUY_ORDER_NOT_FULLY_FILLED error from the provider
    When the user opens the buy sheet, enters $1, and taps Confirm
    Then the buy sheet shows a yellow "Price changed" banner with copy "Couldn't buy at {price}. Try at market price?"
    And the primary CTA label changes to "Retry"
    And no PredictOrderRetrySheet overlay opens
    And no failure toast appears

  Scenario: Order failed banner appears after background failure (ETH path)
    Given an injected order failure occurring after the deposit step settles and the sheet has already closed
    When the user opens the buy sheet, picks ETH, enters $1, and taps Confirm
    Then the buy sheet closes and the deposit/processing toast appears
    And ~3 seconds later the buy sheet reopens automatically with a red "Order failed" banner
    And the keyboard is dismissed and the "Retry" CTA is fully visible
    And no failure toast is shown

  Scenario: Retry stays inline in sheet mode
    Given the buy sheet is showing the "Order failed" banner
    When the user taps "Retry" and the retried order also fails
    Then the action button shows "Placing prediction..." while the retry runs
    And the inline banner re-renders in the same sheet
    And no secondary PredictOrderRetrySheet stacks on top of the buy sheet

  Scenario: Banner clears when the user changes the bet amount
    Given the buy sheet is showing the "Price changed" banner
    When the user changes the bet amount via keypad or quick-amount button
    Then the banner disappears
    And the CTA returns to the normal "Buy {outcome}" label

  Scenario: Banner clears when the user dismisses the sheet
    Given the buy sheet is showing the "Price changed" banner
    When the user swipes the sheet down or taps the close button
    And then reopens the buy sheet for the same market
    Then no error banner is shown
    And the sheet is in a clean state

Feature: Legacy behaviour preserved when predictBottomSheet flag is OFF

  Scenario: Legacy retry sheet still opens for not-fully-filled errors
    Given the predictBottomSheet feature flag is disabled
    And the same PREDICT_BUY_ORDER_NOT_FULLY_FILLED injection as above
    When the user taps Confirm
    Then PredictOrderRetrySheet opens as the secondary overlay
    And no inline banner appears in the buy sheet

  Scenario: Legacy failure toast still appears for background failures
    Given the predictBottomSheet feature flag is disabled
    And an injected background order failure
    When the user taps Confirm and the sheet closes
    Then the failure toast "Failed to place prediction" is shown
    And the buy sheet does not auto-reopen

Screenshots/Recordings

Before

After

Screenshot 2026-04-22 at 15 09 41
errorScreen.mov

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

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.

Note

Medium Risk
Changes Predict buy-order failure UX by auto-reopening the buy bottom sheet and moving errors from toasts/PredictOrderRetrySheet into inline banners with a retry CTA; regressions could hide errors or alter retry behavior. Flag-gated, but touches shared order/preview-sheet and toast-registration paths.

Overview
When predictBottomSheet is enabled, buy-flow failures are now surfaced inside the buy bottom sheet via new inline banners (price_changed and order_failed) and the primary CTA switches to Retry (retries with best-available slippage). This suppresses the legacy PredictOrderRetrySheet overlay in sheet mode and hides the background order failed toast when the sheet provider is mounted to avoid duplicate UI.

The buy preview sheet provider now tracks mount state and can auto-reopen the buy sheet with the last buy params when activeOrder.error appears after the sheet was dismissed, and dismissing the buy sheet clears the active order error. Copy and testIDs were updated, and extensive tests were added/updated to cover banner rendering, retry behavior, toast suppression, and auto-reopen scenarios.

Reviewed by Cursor Bugbot for commit 1cc328d. Bugbot is set up for automated code reviews on this repo. Configure here.

@MarioAslau MarioAslau self-assigned this Apr 22, 2026
@MarioAslau MarioAslau added the team-predict Predict team label Apr 22, 2026
@github-actions

Copy link
Copy Markdown
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.

@metamaskbotv2 metamaskbotv2 Bot added the team-mobile-platform Mobile Platform team label Apr 22, 2026
@MarioAslau MarioAslau marked this pull request as ready for review April 22, 2026 14:24
@MarioAslau MarioAslau requested a review from a team as a code owner April 22, 2026 14:24
@github-actions github-actions Bot added the risk:low AI analysis: low risk label Apr 22, 2026
@MarioAslau MarioAslau requested a review from a team as a code owner April 22, 2026 22:43
@github-actions github-actions Bot added risk:high AI analysis: high risk and removed risk:low AI analysis: low risk labels Apr 22, 2026
Comment thread app/components/UI/Predict/views/PredictBuyWithAnyToken/PredictBuyWithAnyToken.tsx Outdated
cortisiko
cortisiko previously approved these changes Apr 23, 2026
@github-actions

Copy link
Copy Markdown
Contributor

AI PR Analysis

🚫 Merge safe: false | 🟠 Risk: high

Merge decision: AI analysis did not complete — manual review required before merging.

AI analysis did not complete. Manual review recommended.

View run

Comment thread app/components/UI/Predict/views/PredictBuyWithAnyToken/PredictBuyWithAnyToken.tsx Outdated
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.95181% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.25%. Comparing base (64f79bb) to head (6acb967).
⚠️ Report is 90 commits behind head on main.

Files with missing lines Patch % Lines
...PredictBuyWithAnyToken/hooks/usePredictBuyError.ts 78.26% 2 Missing and 3 partials ⚠️
.../PredictBuyWithAnyToken/PredictBuyWithAnyToken.tsx 81.81% 2 Missing and 2 partials ⚠️
...omponents/UI/Predict/hooks/usePredictOrderRetry.ts 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #29184      +/-   ##
==========================================
+ Coverage   82.19%   82.25%   +0.06%     
==========================================
  Files        5069     5127      +58     
  Lines      133674   135748    +2074     
  Branches    29969    30572     +603     
==========================================
+ Hits       109870   111663    +1793     
- Misses      16334    16462     +128     
- Partials     7470     7623     +153     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread app/components/UI/Predict/views/PredictBuyWithAnyToken/PredictBuyWithAnyToken.tsx Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a12ac9d. Configure here.

Comment thread app/components/UI/Predict/contexts/PredictPreviewSheetContext.tsx
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePredictions, SmokeWalletPlatform, SmokeConfirmations
  • Selected Performance tags: @PerformancePredict
  • Risk Level: medium
  • AI Confidence: 90%
click to see 🤖 AI reasoning details

E2E Test Selection:
All changes are contained within the Predictions feature (app/components/UI/Predict/). The PR introduces:

  1. New PredictBuyErrorBanner component: A new inline error banner for sheet mode showing 'price_changed' and 'order_failed' states with warning/error styling.

  2. usePredictBuyError hook extension: Now returns buyErrorBanner data and clearBuyErrorBanner for sheet mode, while maintaining legacy full-screen behavior.

  3. usePredictOrderRetry hook: Added isSheetMode parameter to suppress the overlay retry sheet in favor of the new inline banner.

  4. PredictPreviewSheetContext: Added auto-reopen logic when a background order fails (so user sees inline error banner instead of toast), plus isPredictSheetProviderMounted() utility function.

  5. usePredictToastRegistrations: Suppresses the order-failure toast when bottom sheet is enabled and provider is mounted (to avoid duplicate UI).

  6. PredictBuyActionButton: Added isRetry prop to show "Retry" label when in error state.

  7. PredictBuyPreview: Minor layout fix removing flex-1 from sheet mode wrapper.

  8. New test IDs: PRICE_CHANGED_BANNER and ORDER_FAILED_BANNER added.

  9. Locales: New strings for price_changed_title, price_changed_body, order_failed_body (updated), and retry.

  10. Component view preset: Added activeBuyOrders to default PredictController state.

SmokePredictions: Directly required - the buy flow, error handling, retry mechanism, and order failure UX are all changed. The full position lifecycle (opening positions, error recovery) is affected.

SmokeWalletPlatform: Required per tag description - Predictions is a section inside the Trending tab, so changes to Predictions views (PredictBuyWithAnyToken, PredictBuyPreview, PredictPreviewSheetContext) affect Trending.

SmokeConfirmations: Required per SmokePredictions tag description - opening/closing positions are on-chain transactions requiring confirmations.

Performance Test Selection:
The changes introduce new UI rendering (PredictBuyErrorBanner component), auto-reopen logic in PredictPreviewSheetContext, and modified state management in usePredictBuyError. The @PerformancePredict tag covers prediction market flows including deposit flows and balance display, which could be affected by the new banner rendering, additional useEffect hooks, and the auto-reopen mechanism. The new component adds rendering overhead in the buy flow path.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
12 value mismatches detected (expected — fixture represents an existing user).
View details

@MarioAslau MarioAslau requested a review from cortisiko April 24, 2026 02:35

@christopherferreira9 christopherferreira9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for QA

@MarioAslau MarioAslau added this pull request to the merge queue Apr 27, 2026
Merged via the queue into main with commit 9816769 Apr 27, 2026
110 of 111 checks passed
@MarioAslau MarioAslau deleted the predict/bottom-sheet-errors branch April 27, 2026 14:09
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 27, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.76.0 Issue or pull request that will be included in release 7.76.0 label Apr 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.76.0 Issue or pull request that will be included in release 7.76.0 risk:high AI analysis: high risk size-XL team-mobile-platform Mobile Platform team team-predict Predict team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants