Skip to content

Response drift: smarkets — winner_count, complete, cashout_enabled, bet_delay, market_type fields not accessed by normalizer #2016

Description

@realfishsam

Exchange

smarkets

Severity

MEDIUM

What Our Normalizer Expects

core/src/exchanges/smarkets/normalizer.ts extracts a fixed set of fields from each market object: id, event_id, name, slug, description, category, categories. No market lifecycle fields (complete, winner_count) or trading-constraint fields (cashout_enabled, bet_delay) are accessed or included in sourceMetadata.

What The Live API Returns

The live GET https://api.smarkets.com/v3/events/?limit=3&state=upcoming response includes several unaccessed fields on every market object:

markets[].winner_count: int         ← how many outcomes can win (1 = binary, N = multi-winner)
markets[].complete: bool            ← whether the market has fully traded / closed
markets[].cashout_enabled: bool     ← whether cashout (early settlement) is available
markets[].bet_delay: int            ← seconds delay between bet placement and acceptance
markets[].market_type.name: str     ← canonical market type name (e.g. "winner")
markets[].market_type.param: str    ← type-specific parameter (e.g. over/under threshold)
markets[].info.reason: str          ← additional market metadata (e.g. suspension reason)

Endpoint tested: GET https://api.smarkets.com/v3/events/?limit=3&state=upcoming

Impact

MEDIUM:

  • winner_count: Without this, PMXT cannot distinguish binary markets from multi-winner markets. Placing orders on a "pick 3 of 5" market using binary-market assumptions produces incorrect probability calculations and incorrect order sizing.
  • complete: Closed/settled markets are indistinguishable from active ones in normalized output — closed markets appear live, misleading consumers.
  • cashout_enabled: Cashout offers are conditionally available. Without this flag, UI cannot show or suppress the cashout option per market.
  • bet_delay: Order execution logic cannot account for the acceptance delay, which affects time-sensitive strategies.
  • market_type.name/market_type.param: Market mechanics (e.g. correct score, handicap, over/under) cannot be surfaced to consumers, preventing type-specific display or routing.

Relationship to Existing Issues

Issue #1366 covers a separate finding: events[].end_date is null for all events. This issue is unrelated and tracks the unaccessed market-level operational fields.

Suggested Fix

Add all seven fields to the Smarkets raw market type definition and include them in SMARKETS_PROMOTED_MARKET_KEYS (or map them explicitly in the normalizer):

// SmarketsRawMarket — add fields
winner_count?: number;
complete?: boolean;
cashout_enabled?: boolean;
bet_delay?: number;
market_type?: { name: string; param?: string };
info?: { reason?: string };

Promote winner_count and complete as typed fields on UnifiedMarket if market-type routing or lifecycle filtering is needed downstream. Include the rest in sourceMetadata at minimum.


Found by automated response shape drift audit

Metadata

Metadata

Assignees

No one assigned

    Labels

    response-driftLive API response shape differs from normalizer expectations

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions