Skip to content

Response drift: suibets — onchainState.status (string) split into status: int + statusLabel: str in live API #2014

Description

@realfishsam

Exchange

suibets

Severity

MEDIUM

What Our Normalizer Expects

core/src/exchanges/suibets/fetcher.ts declares onchainState.status as an optional string, and the normalizer reads raw.status as a string to determine market/offer lifecycle state:

// fetcher.ts — SuibetsRawOffer
onchainState?: {
  makerRemaining?: number;
  totalLiquidity?: number;
  filledAmount?: number;
  status?: string;   // expected: string like "OPEN", "MATCHED", "SETTLED"
};

What The Live API Returns

The live API has restructured the status representation. onchainState.status is no longer present as a string. Instead, status information is provided as two separate top-level fields:

[].status: int           ← integer enum (e.g. 1, 2, 3)
[].statusLabel: str      ← human-readable label (e.g. "active", "matched")
[].onchainState.status   ← ABSENT

Endpoint tested: GET https://www.suibets.com/api/p2p/offers?status=all

Impact

MEDIUM: The normalizer reads raw.status expecting a string, but now receives an integer. Any string comparisons (raw.status === 'OPEN', raw.status === 'SETTLED') always return false, causing status-based routing and filtering to silently misclassify every offer. Settled or matched offers may be treated as active, and vice versa.

Additionally, the human-readable statusLabel is not accessed at all — consumers get neither the correct integer status nor the human-readable label in normalized output.

Suggested Fix

Update the interface and normalizer to use the new fields:

// fetcher.ts — SuibetsRawOffer
status?: number;         // integer enum (add)
statusLabel?: string;    // human-readable label (add)
onchainState?: {
  makerRemaining?: number;
  filledAmount?: number;
  // status: string — removed (now at root level)
};

Map statusLabel as the canonical status string in the normalizer and use status (integer) only for numeric comparisons or when the human-readable label is unavailable.


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