@@ -89,7 +89,9 @@ import {
8989 fetchCarouselFromPolymarketApi ,
9090 getBalance ,
9191 getL2Headers ,
92+ fetchChildEventsFromGammaApi ,
9293 getMarketDetailsFromGammaApi ,
94+ mergeChildEventsIntoParent ,
9395 getPolymarketEndpoints ,
9496 getRawBalance ,
9597 parsePolymarketActivity ,
@@ -100,6 +102,7 @@ import {
100102import { PredictFeatureFlags } from '../../types/flags' ;
101103import {
102104 extractNeededTeamsFromEvents ,
105+ getEventLeague ,
103106 isLiveSportsEvent ,
104107} from '../../utils/gameParser' ;
105108import { GameCache } from './GameCache' ;
@@ -184,10 +187,6 @@ export class PolymarketProvider implements PredictProvider {
184187 return this . #getFeatureFlags( ) . extendedSportsMarketsLeagues ;
185188 }
186189
187- #hasExtendedMarketsForLeague( league : string ) : boolean {
188- return this . #getExtendedSportsMarketsLeagues( ) . includes ( league ) ;
189- }
190-
191190 #createTeamLookup(
192191 enabled : boolean ,
193192 ) :
@@ -223,6 +222,47 @@ export class PolymarketProvider implements PredictProvider {
223222 ) ;
224223 }
225224
225+ /**
226+ * Extended sports positions can point to child events like player props or
227+ * halftime markets, but the details view should resolve back to the parent
228+ * game and merge the child markets into that game when the league supports it.
229+ */
230+ async #resolveSportMarketFromPolymarket( {
231+ event,
232+ extendedSportsMarketsLeagues,
233+ } : {
234+ event : PolymarketApiEvent ;
235+ extendedSportsMarketsLeagues : string [ ] ;
236+ } ) : Promise < {
237+ resolvedEvent : PolymarketApiEvent ;
238+ childMarketIds ?: string [ ] ;
239+ } > {
240+ const eventLeague = getEventLeague ( event , extendedSportsMarketsLeagues ) ;
241+ if ( ! eventLeague || ! extendedSportsMarketsLeagues . includes ( eventLeague ) ) {
242+ return { resolvedEvent : event } ;
243+ }
244+
245+ const resolvedEventId = event . parentEventId ?? event . id ;
246+
247+ try {
248+ const allEvents = await fetchChildEventsFromGammaApi ( {
249+ parentEventId : resolvedEventId ,
250+ } ) ;
251+ return {
252+ resolvedEvent : mergeChildEventsIntoParent ( allEvents ) ,
253+ childMarketIds : allEvents . map (
254+ ( resolvedChildEvent ) => resolvedChildEvent . id ,
255+ ) ,
256+ } ;
257+ } catch ( childFetchError ) {
258+ DevLogger . log (
259+ 'Failed to fetch child events, using resolved event only:' ,
260+ childFetchError ,
261+ ) ;
262+ return { resolvedEvent : event } ;
263+ }
264+ }
265+
226266 /**
227267 * Generate standard error context for Logger.error calls with searchable tags and context.
228268 * Enables Sentry dashboard filtering by feature and provider.
@@ -543,19 +583,36 @@ export class PolymarketProvider implements PredictProvider {
543583
544584 const supportedLeagues = this . #getSupportedLeagues( ) ;
545585 const liveSportsEnabled = supportedLeagues . length > 0 ;
586+ const extendedSportsMarketsLeagues =
587+ this . #getExtendedSportsMarketsLeagues( ) ;
546588 const isSportsEvent =
547- liveSportsEnabled && isLiveSportsEvent ( event , supportedLeagues ) ;
589+ liveSportsEnabled &&
590+ isLiveSportsEvent (
591+ event ,
592+ supportedLeagues ,
593+ extendedSportsMarketsLeagues ,
594+ ) ;
548595
596+ let mergedEvent = event ;
597+ let childMarketIds : string [ ] | undefined ;
549598 if ( isSportsEvent ) {
550- await this . #ensureTeamsLoadedForEvents( [ event ] , supportedLeagues ) ;
599+ const resolvedSportMarket =
600+ await this . #resolveSportMarketFromPolymarket( {
601+ event,
602+ extendedSportsMarketsLeagues,
603+ } ) ;
604+ mergedEvent = resolvedSportMarket . resolvedEvent ;
605+ childMarketIds = resolvedSportMarket . childMarketIds ;
606+
607+ await this . #ensureTeamsLoadedForEvents( [ mergedEvent ] , supportedLeagues ) ;
551608 }
552609
553610 const teamLookup = this . #createTeamLookup( isSportsEvent ) ;
554611
555- const [ parsedMarket ] = parsePolymarketEvents ( [ event ] , {
612+ const [ parsedMarket ] = parsePolymarketEvents ( [ mergedEvent ] , {
556613 category : PolymarketProvider . FALLBACK_CATEGORY ,
557614 teamLookup,
558- extendedSportsMarketsLeagues : this . #getExtendedSportsMarketsLeagues ( ) ,
615+ extendedSportsMarketsLeagues,
559616 } ) ;
560617
561618 if ( ! parsedMarket ) {
@@ -566,6 +623,10 @@ export class PolymarketProvider implements PredictProvider {
566623 ? GameCache . getInstance ( ) . overlayOnMarket ( parsedMarket )
567624 : parsedMarket ;
568625
626+ if ( childMarketIds ) {
627+ result . childMarketIds = childMarketIds ;
628+ }
629+
569630 return result ;
570631 } catch ( error ) {
571632 DevLogger . log ( 'Error getting market details via Polymarket API:' , error ) ;
0 commit comments