Skip to content

fix(predict): hide child more-market cards from feed#30154

Merged
caieu merged 2 commits into
mainfrom
PRED-865-filter-out-more-markets-events-from-the-feed
May 15, 2026
Merged

fix(predict): hide child more-market cards from feed#30154
caieu merged 2 commits into
mainfrom
PRED-865-filter-out-more-markets-events-from-the-feed

Conversation

@caieu
Copy link
Copy Markdown
Contributor

@caieu caieu commented May 13, 2026

Description

Filters Polymarket "more market" child events out of Predict feed surfaces without changing raw pagination behavior.

Polymarket marks child/more-market events with parentEventId. This PR maps that API field to PredictMarket.parentMarketId, then filters parented markets from feed and featured carousel render data. Pagination still uses the raw page size before filtering, so infinite scroll can continue even when a page contains hidden child markets.

Changelog

CHANGELOG entry: Fixed child prediction markets appearing as standalone cards in the Predict feed.

Related issues

Fixes: PRED-865

Manual testing steps

Feature: Predict feed more-market filtering

  Scenario: user scrolls the Predict feed
    Given Polymarket returns feed events that include child events with parentEventId

    When user opens the Predict feed
    Then child more-market cards are not rendered as standalone cards

    When user scrolls to the end of the visible feed page
    Then the feed continues loading the next raw page when available

Screenshots/Recordings

N/A. Logic-only feed filtering change covered by unit tests.

Before

N/A

After

N/A

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
  • I've tested with a power user scenario
  • I've instrumented key operations with Sentry traces for production performance metrics

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 which markets are surfaced in the Predict feed/carousel by filtering out events with parentMarketId, which could inadvertently hide valid markets or impact pagination edge-cases despite added tests.

Overview
Filters Polymarket “more-market” child events out of Predict feed surfaces.

This maps Polymarket parentEventId onto PredictMarket.parentMarketId (now nullable) during event parsing, then adds filterStandaloneMarkets and applies it in usePredictMarketData and useFeaturedCarouselData so only standalone markets render. Pagination/hasMore behavior continues to use the raw page size before filtering, with new unit tests covering filtering and offset handling.

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

@metamaskbotv2 metamaskbotv2 Bot added the team-predict Predict team label May 13, 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 INVALID-PR-TEMPLATE PR's body doesn't match template label May 13, 2026
@caieu caieu marked this pull request as ready for review May 13, 2026 22:48
@caieu caieu requested a review from a team as a code owner May 13, 2026 22:48
Copy link
Copy Markdown
Contributor

@MarioAslau MarioAslau left a comment

Choose a reason for hiding this comment

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

Medium severity

1. isStandaloneMarket treats numeric 0 as a child market

// metamask-mobile/app/components/UI/Predict/utils/feed.ts
export function isStandaloneMarket(market: PredictMarket): boolean {
  const { parentMarketId } = market;
  return (
    parentMarketId === undefined ||
    parentMarketId === null ||
    String(parentMarketId).trim() === ''
  );
}

The PredictMarket.parentMarketId type is string | number | null. If a future Polymarket payload ever uses 0 as a sentinel for "no parent" (or if the field defaults to 0 for new rows), String(0).trim() === '0', so the market is treated as a child and silently filtered out. Same applies to NaN (String(NaN) === 'NaN').

The current tests cover string '', null, string parent, and numeric 123, but do not cover the 0 case. Two cheap options:

// Option A: treat any number as a real id (matches the Polymarket convention of positive ids).
if (typeof parentMarketId === 'number') return false;
if (parentMarketId == null) return true;
return parentMarketId.trim() === '';

// Option B: be explicit about which numeric values are "no parent".
if (parentMarketId === undefined || parentMarketId === null) return true;
if (typeof parentMarketId === 'number') return parentMarketId === 0;
return parentMarketId.trim() === '';

Either is unambiguous and dodges the String(0) === '0' quirk. Worth one sentence in the PR confirming which numeric values Polymarket actually emits.

2. E2E fixture schema is out of date

From the bot comment on the PR:

E2E Fixture Validation, Structural changes detected. Missing keys 15, Value mismatches 12 (informational).

This is the parentMarketId field being added to PredictMarket. Run @metamaskbot update-mobile-fixture in a PR comment before merge so the fixture stays in sync with the type.


Low severity

3. Architectural inconsistency: carousel filters in useMemo, feed filters inside the fetch callback

useFeaturedCarouselData applies filterStandaloneMarkets reactively in useMemo. usePredictMarketData applies it once at fetch time and stores filtered data in state. Both work, but if a future change adds another feed filter, the two will need to be touched in different places. Not blocking; just worth noting that a single shared "transform pipeline" helper would be cleaner if more filters land.

4. Polymarket API type widened to allow null without auditing other consumers

// metamask-mobile/app/components/UI/Predict/providers/polymarket/types.ts
-  parentEventId?: string | number;
+  parentEventId?: string | number | null;

PolymarketProvider.ts line 303 reads event.parentEventId ?? event.id (nullish coalescing handles both null and undefined, safe). utils.ts lines 1383 to 1407 use parentEventId for child-event aggregation (!e.parentEventId falsy check, also safe). So the widening looks benign with current consumers, but worth a one-line note in the PR that this was checked, otherwise it reads as a quiet API contract change.

5. refine is now called on filtered data, not raw

// metamask-mobile/app/components/UI/Predict/hooks/usePredictMarketData.tsx
setMarketData(refine ? refine(visibleMarkets) : visibleMarkets);

Current callers (PredictFeed.tsx lines 271 and 527) only ever pass deduplicateSeriesMarkets via refine, and that helper does not depend on seeing children, so this change is safe today. If a future caller passes a refine function that does cross-market analysis (e.g., aggregating parent + children stats), the behavior would silently change. Low because the surface is small and well-known, but a JSDoc note on the refine option in UsePredictMarketDataOptions saying "called on the already-filtered, user-visible markets" would future-proof it.

@caieu caieu requested a review from MarioAslau May 14, 2026 19:25
Map Polymarket parentEventId to PredictMarket parentMarketId and filter
parented markets from feed and carousel render data while preserving raw
pagination behavior.
@caieu caieu force-pushed the PRED-865-filter-out-more-markets-events-from-the-feed branch from af1f56e to 98e31ad Compare May 15, 2026 12:27
@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 10 changed files are within the app/components/UI/Predict/ directory, exclusively affecting the Polymarket/Predictions feature:

  1. New filtering logic (feed.ts): Introduces isStandaloneMarket and filterStandaloneMarkets utilities to exclude child/sub-markets (those with a non-empty parentMarketId) from display.

  2. Type updates (types/index.ts, providers/polymarket/types.ts): Added parentMarketId field to PredictMarket and updated parentEventId to allow null values.

  3. API mapping (providers/polymarket/utils.ts): Maps parentEventId from the Polymarket API response to the new parentMarketId field.

  4. Hook changes (useFeaturedCarouselData.ts, usePredictMarketData.tsx): Both hooks now apply filterStandaloneMarkets to filter out child markets before displaying them in the featured carousel and market list.

Impact: These changes affect which markets are visible in the Predictions UI — child/sub-markets will no longer appear in the featured carousel or market list. This is a behavioral change that needs validation via SmokePredictions tests.

Tag dependencies per descriptions:

  • SmokePredictions → also select SmokeWalletPlatform (Trending section) and SmokeConfirmations (on-chain transactions for opening/closing positions)

No other feature areas (accounts, swaps, network, browser, snaps, etc.) are affected.

Performance Test Selection:
The changes add a filterStandaloneMarkets filter step to both the featured carousel data and the market list data loading paths. While the filter itself is lightweight (O(n) array filter), it changes the number of markets rendered in the Predictions UI, which could affect render times and list performance. The @PerformancePredict tag covers prediction market list loading and balance display, making it relevant to validate that the filtering doesn't introduce performance regressions.

View GitHub Actions results

@caieu caieu enabled auto-merge May 15, 2026 15:42
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 81.94%. Comparing base (6375f80) to head (7c7379a).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
...mponents/UI/Predict/hooks/usePredictMarketData.tsx 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #30154      +/-   ##
==========================================
+ Coverage   81.92%   81.94%   +0.01%     
==========================================
  Files        5442     5442              
  Lines      145329   145325       -4     
  Branches    33217    33217              
==========================================
+ Hits       119064   119085      +21     
+ Misses      18135    18116      -19     
+ Partials     8130     8124       -6     

☔ 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.

@sonarqubecloud
Copy link
Copy Markdown

@caieu caieu added this pull request to the merge queue May 15, 2026
Merged via the queue into main with commit fe0c0ac May 15, 2026
177 of 181 checks passed
@caieu caieu deleted the PRED-865-filter-out-more-markets-events-from-the-feed branch May 15, 2026 17:36
@github-actions github-actions Bot locked and limited conversation to collaborators May 15, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.79.0 Issue or pull request that will be included in release 7.79.0 label May 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template release-7.79.0 Issue or pull request that will be included in release 7.79.0 size-M team-predict Predict team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants