Skip to content

Commit 35588df

Browse files
authored
fix(preidct): prioritize sport market type sorting over price sorting in feed (#28602)
<!-- 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? --> Sport cards on the Predict feed and carousel were displaying the wrong market type (e.g. spreads or totals) instead of moneyline. This happened because `sortMarkets()` checked the `sortBy` parameter **before** `isSportEvent()`. Since both `getMarkets()` and `getCarouselMarkets()` always pass `sortMarketsBy: 'price'`, the `sortSportMarkets()` branch — which enforces moneyline → spreads → totals ordering — was never reached. The sport card components (`PredictMarketSportCard`, `FeaturedCarouselSportCard`) all use `market.outcomes[0]` to select the displayed market, so whichever market had the highest price would show up instead of the moneyline market. **Fix**: Move the `isSportEvent()` check above the `sortBy` check in `sortMarkets()` so sport events always use sport-type-based ordering regardless of the `sortBy` parameter. Non-sport events are unaffected and continue to respect `sortBy` as before. ## **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: [PRED-814](https://consensyssoftware.atlassian.net/browse/PRED-814) ## **Manual testing steps** ```gherkin Feature: Sport card moneyline market display Scenario: sport cards on the feed show the moneyline market Given the user is on the Predict tab And the feed contains sport events with multiple market types (moneyline, spreads, totals) When the user views a sport card on the feed Then the card displays the moneyline market outcomes (team names with win probabilities) And the card does not display spread or total market outcomes Scenario: sport cards on the featured carousel show the moneyline market Given the user is on the Predict home screen And the featured carousel contains sport events When the user views a sport card in the carousel Then the card displays the moneyline market outcomes And the card does not display spread or total market outcomes Scenario: non-sport markets remain sorted by price Given the user is on the Predict tab And the feed contains non-sport prediction markets When the user views the market cards Then markets are sorted by price in descending order as before ``` ## **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/e93b1754-ba6d-4005-a17e-110b2173f1cf ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/d5fcf806-5eae-44e3-af43-57218d81063a ## **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. <!-- Generated with the help of the pr-description AI skill --> [PRED-814]: https://consensyssoftware.atlassian.net/browse/PRED-814?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: small, well-tested change to market ordering logic that only affects how sport events choose their primary market in the feed/carousel. > > **Overview** > Fixes sport event market ordering so `sortMarkets()` always applies `sortSportMarkets()` (moneyline → spreads → totals) *before* any `sortBy`/`event.sortBy` price-based sorting. > > Updates unit tests to reflect the new precedence, adding coverage that sport events ignore both passed-in and event-level `sortBy`, while non-sport events continue to respect price sorting. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7f885c7. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 0c26cf4 commit 35588df

File tree

2 files changed

+79
-10
lines changed

2 files changed

+79
-10
lines changed

app/components/UI/Predict/providers/polymarket/utils.test.ts

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,12 +1970,41 @@ describe('polymarket utils', () => {
19701970
expect(result.map((m) => m.conditionId)).toEqual(['first', 'second']);
19711971
});
19721972

1973-
it('prioritizes sortBy parameter over sport event sorting', () => {
1973+
it('prioritizes sport event sorting over sortBy parameter', () => {
19741974
const markets = [
1975-
createMarket('totals-low-price', '["0.3", "0.7"]', 100, 100, 'totals'),
1975+
createMarket('totals-high-price', '["0.9", "0.1"]', 100, 100, 'totals'),
19761976
createMarket(
1977-
'moneyline-high-price',
1977+
'moneyline-low-price',
1978+
'["0.3", "0.7"]',
1979+
100,
1980+
100,
1981+
'moneyline',
1982+
),
1983+
];
1984+
const sportTags = [{ id: '1', label: 'Sports', slug: 'sports' }];
1985+
const event = createEvent(sportTags, markets);
1986+
1987+
const result = sortMarkets(event, 'price');
1988+
1989+
expect(result.map((m) => m.conditionId)).toEqual([
1990+
'moneyline-low-price',
1991+
'totals-high-price',
1992+
]);
1993+
});
1994+
1995+
it('places moneyline first for sport events even when moneyline has lower price', () => {
1996+
const markets = [
1997+
createMarket(
1998+
'spreads-high-price',
19781999
'["0.9", "0.1"]',
2000+
200,
2001+
200,
2002+
'spreads',
2003+
),
2004+
createMarket('totals-mid-price', '["0.7", "0.3"]', 150, 150, 'totals'),
2005+
createMarket(
2006+
'moneyline-low-price',
2007+
'["0.3", "0.7"]',
19792008
100,
19802009
100,
19812010
'moneyline',
@@ -1986,10 +2015,50 @@ describe('polymarket utils', () => {
19862015

19872016
const result = sortMarkets(event, 'price');
19882017

1989-
// Price sorting overrides sport sorting
2018+
// Moneyline first despite having the lowest price
2019+
expect(result.map((m) => m.conditionId)).toEqual([
2020+
'moneyline-low-price',
2021+
'spreads-high-price',
2022+
'totals-mid-price',
2023+
]);
2024+
});
2025+
2026+
it('uses sortBy parameter for non-sport events when sortBy is provided', () => {
2027+
const markets = [
2028+
createMarket('low-price', '["0.2", "0.8"]', 100, 100),
2029+
createMarket('high-price', '["0.8", "0.2"]', 100, 100),
2030+
];
2031+
const event = createEvent([], markets);
2032+
2033+
const result = sortMarkets(event, 'price');
2034+
2035+
// Non-sport events still respect sortBy
2036+
expect(result.map((m) => m.conditionId)).toEqual([
2037+
'high-price',
2038+
'low-price',
2039+
]);
2040+
});
2041+
2042+
it('ignores event.sortBy for sport events', () => {
2043+
const markets = [
2044+
createMarket('totals-high-price', '["0.9", "0.1"]', 100, 100, 'totals'),
2045+
createMarket(
2046+
'moneyline-low-price',
2047+
'["0.2", "0.8"]',
2048+
100,
2049+
100,
2050+
'moneyline',
2051+
),
2052+
];
2053+
const sportTags = [{ id: '1', label: 'Sports', slug: 'sports' }];
2054+
const event = createEvent(sportTags, markets, 'price');
2055+
2056+
const result = sortMarkets(event);
2057+
2058+
// Sport sorting wins over event.sortBy
19902059
expect(result.map((m) => m.conditionId)).toEqual([
1991-
'moneyline-high-price',
1992-
'totals-low-price',
2060+
'moneyline-low-price',
2061+
'totals-high-price',
19932062
]);
19942063
});
19952064
});

app/components/UI/Predict/providers/polymarket/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,10 @@ export const sortMarkets = (
670670
const markets = Array.isArray(event.markets) ? event.markets : [];
671671
const eventSortBy = event.sortBy;
672672

673+
if (isSportEvent(event)) {
674+
return sortSportMarkets(markets);
675+
}
676+
673677
if (sortBy) {
674678
return sortMarketsByField(markets, sortBy);
675679
}
@@ -678,10 +682,6 @@ export const sortMarkets = (
678682
return sortMarketsByField(markets, eventSortBy);
679683
}
680684

681-
if (isSportEvent(event)) {
682-
return sortSportMarkets(markets);
683-
}
684-
685685
return markets;
686686
};
687687

0 commit comments

Comments
 (0)