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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions