Skip to content

Commit 8566a4e

Browse files
committed
Merge branch 'main' into jl/eip-5792-middleware-3-0-0
2 parents 0fb3dea + dafc42c commit 8566a4e

26 files changed

Lines changed: 903 additions & 58 deletions

app/components/UI/Predict/hooks/useFeaturedCarouselData.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,26 @@ describe('useFeaturedCarouselData', () => {
103103
expect(result.current.error).toBeNull();
104104
});
105105

106+
it('filters child more-market cards', async () => {
107+
const { Wrapper } = createWrapper();
108+
const parentMarket = createMockMarket({ id: 'parent-market' });
109+
const childMarket = createMockMarket({
110+
id: 'child-market',
111+
parentMarketId: 'parent-market',
112+
});
113+
mockGetCarouselMarkets.mockResolvedValue([parentMarket, childMarket]);
114+
115+
const { result } = renderHook(() => useFeaturedCarouselData(), {
116+
wrapper: Wrapper,
117+
});
118+
119+
await waitFor(() => {
120+
expect(result.current.isLoading).toBe(false);
121+
});
122+
123+
expect(result.current.markets).toEqual([parentMarket]);
124+
});
125+
106126
it('returns error when controller throws', async () => {
107127
const { Wrapper } = createWrapper();
108128
mockGetCarouselMarkets.mockRejectedValue(new Error('Network error'));

app/components/UI/Predict/hooks/useFeaturedCarouselData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { predictQueries } from '../queries';
77
import { selectPredictUpDownEnabledFlag } from '../selectors/featureFlags';
88
import type { PredictMarket } from '../types';
99
import { isCryptoUpDown } from '../utils/cryptoUpDown';
10+
import { filterStandaloneMarkets } from '../utils/feed';
1011
import { ensureError } from '../utils/predictErrorHandler';
1112

1213
export interface UseFeaturedCarouselDataResult {
@@ -40,7 +41,7 @@ export const useFeaturedCarouselData = (): UseFeaturedCarouselDataResult => {
4041
}, [query.error]);
4142

4243
const markets = useMemo(() => {
43-
const data = query.data ?? [];
44+
const data = filterStandaloneMarkets(query.data ?? []);
4445
if (upDownEnabled) {
4546
return data;
4647
}

app/components/UI/Predict/hooks/usePredictMarketData.test.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,63 @@ describe('usePredictMarketData', () => {
219219
);
220220
});
221221

222+
it('filters child more-market cards without disabling pagination', async () => {
223+
const rawMarkets = Array.from({ length: 20 }, (_, index) => ({
224+
...mockMarketData[0],
225+
id: `market-${index}`,
226+
slug: `market-${index}`,
227+
parentMarketId: index >= 18 ? 'parent-market' : undefined,
228+
}));
229+
mockGetMarkets.mockResolvedValue(rawMarkets);
230+
231+
const { result } = renderHook(() => usePredictMarketData({ pageSize: 20 }));
232+
233+
await waitFor(() => {
234+
expect(result.current.isFetching).toBe(false);
235+
});
236+
237+
expect(result.current.marketData).toHaveLength(18);
238+
expect(result.current.marketData.map((market) => market.id)).toEqual(
239+
rawMarkets.slice(0, 18).map((market) => market.id),
240+
);
241+
expect(result.current.hasMore).toBe(true);
242+
});
243+
244+
it('uses raw page offsets when loading more after child cards are filtered', async () => {
245+
const firstRawPage = Array.from({ length: 20 }, (_, index) => ({
246+
...mockMarketData[0],
247+
id: `first-page-market-${index}`,
248+
slug: `first-page-market-${index}`,
249+
parentMarketId: index >= 18 ? 'parent-market' : undefined,
250+
}));
251+
const secondRawPage = Array.from({ length: 5 }, (_, index) => ({
252+
...mockMarketData[0],
253+
id: `second-page-market-${index}`,
254+
slug: `second-page-market-${index}`,
255+
}));
256+
257+
mockGetMarkets
258+
.mockResolvedValueOnce(firstRawPage)
259+
.mockResolvedValueOnce(secondRawPage);
260+
261+
const { result } = renderHook(() => usePredictMarketData({ pageSize: 20 }));
262+
263+
await waitFor(() => {
264+
expect(result.current.isFetching).toBe(false);
265+
});
266+
267+
await act(async () => {
268+
await result.current.fetchMore();
269+
});
270+
271+
expect(mockGetMarkets).toHaveBeenNthCalledWith(
272+
2,
273+
expect.objectContaining({ limit: 20, offset: 20 }),
274+
);
275+
expect(result.current.marketData).toHaveLength(23);
276+
expect(result.current.hasMore).toBe(false);
277+
});
278+
222279
it('handle null market data', async () => {
223280
mockGetMarkets.mockResolvedValue(null);
224281

app/components/UI/Predict/hooks/usePredictMarketData.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Logger from '../../../../util/Logger';
1313
import { PREDICT_CONSTANTS } from '../constants/errors';
1414
import { ensureError } from '../utils/predictErrorHandler';
1515
import { PredictCategory, PredictMarket } from '../types';
16+
import { filterStandaloneMarkets } from '../utils/feed';
1617

1718
export interface UsePredictMarketDataOptions {
1819
q?: string;
@@ -147,12 +148,13 @@ export const usePredictMarketData = (
147148

148149
const hasMoreData = markets.length >= pageSize;
149150
setHasMore(hasMoreData);
151+
const visibleMarkets = filterStandaloneMarkets(markets);
150152

151153
if (isLoadMore) {
152154
setMarketData((prevData) => {
153155
// Use a Set to efficiently deduplicate by ID
154156
const existingIds = new Set(prevData.map((event) => event.id));
155-
const newEvents = markets.filter(
157+
const newEvents = visibleMarkets.filter(
156158
(event) => !existingIds.has(event.id),
157159
);
158160
const accumulated = [...prevData, ...newEvents];
@@ -162,7 +164,7 @@ export const usePredictMarketData = (
162164
currentOffsetRef.current += pageSize;
163165
} else {
164166
// Replace data for initial load or refresh
165-
setMarketData(refine ? refine(markets) : markets);
167+
setMarketData(refine ? refine(visibleMarkets) : visibleMarkets);
166168
setCurrentOffset(pageSize);
167169
currentOffsetRef.current = pageSize;
168170
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,10 @@ describe('depositWallet', () => {
269269

270270
it('keeps polling when completion succeeds without a hash', async () => {
271271
mockFetch
272-
.mockResolvedValueOnce(mockResponse({ state: 'STATE_MINED' }))
272+
.mockResolvedValueOnce(mockResponse({ state: 'STATE_CONFIRMED' }))
273273
.mockResolvedValueOnce(
274274
mockResponse({
275-
state: 'STATE_MINED',
275+
state: 'STATE_CONFIRMED',
276276
transactionHash:
277277
'0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
278278
}),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const DEPOSIT_WALLET_DOMAIN_VERSION = '1';
2626
// allowed window to reduce intermittent "deadline too soon" failures.
2727
const DEPOSIT_WALLET_BATCH_DEADLINE_SECONDS = 300;
2828

29-
const RELAYER_SUCCESS_STATES = new Set(['STATE_MINED', 'STATE_CONFIRMED']);
29+
const RELAYER_SUCCESS_STATES = new Set(['STATE_CONFIRMED']);
3030
const RELAYER_FAILURE_STATES = new Set(['STATE_FAILED', 'STATE_INVALID']);
3131

3232
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export interface PolymarketApiEvent {
124124
period?: PredictGamePeriod;
125125
live?: boolean;
126126
ended?: boolean;
127-
parentEventId?: string | number;
127+
parentEventId?: string | number | null;
128128
}
129129

130130
export interface PolymarketApiActivity {

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,4 +746,28 @@ describe('polymarket utils', () => {
746746
}),
747747
).resolves.toBe(false);
748748
});
749+
750+
it('preserves parent market id when parsing Polymarket events', () => {
751+
const event: PolymarketApiEvent = {
752+
id: 'child-event',
753+
slug: 'child-event',
754+
title: 'Child Event',
755+
description: 'Child event description',
756+
icon: '',
757+
closed: false,
758+
series: [],
759+
markets: [],
760+
tags: [],
761+
liquidity: 0,
762+
volume: 0,
763+
parentEventId: 'parent-market',
764+
};
765+
766+
expect(parsePolymarketEvents([event], 'trending')).toEqual([
767+
expect.objectContaining({
768+
id: 'child-event',
769+
parentMarketId: 'parent-market',
770+
}),
771+
]);
772+
});
749773
});

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,9 @@ export const parsePolymarketEvents = (
11121112
volume: event.volume,
11131113
game,
11141114
...(seriesData && { series: seriesData }),
1115+
...(event.parentEventId !== undefined && {
1116+
parentMarketId: event.parentEventId,
1117+
}),
11151118
};
11161119
},
11171120
);

app/components/UI/Predict/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ export type PredictMarket = {
116116
volume: number;
117117
game?: PredictMarketGame;
118118
series?: PredictSeries;
119+
parentMarketId?: string | number | null;
119120
childMarketIds?: string[];
120121
};
121122

0 commit comments

Comments
 (0)