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
Exchange
suibets
Severity
MEDIUM
What Our Normalizer Expects
core/src/exchanges/suibets/fetcher.tsdeclaresonchainState.statusas an optional string, and the normalizer readsraw.statusas a string to determine market/offer lifecycle state:What The Live API Returns
The live API has restructured the status representation.
onchainState.statusis no longer present as a string. Instead, status information is provided as two separate top-level fields:Endpoint tested:
GET https://www.suibets.com/api/p2p/offers?status=allImpact
MEDIUM: The normalizer reads
raw.statusexpecting a string, but now receives an integer. Any string comparisons (raw.status === 'OPEN',raw.status === 'SETTLED') always returnfalse, 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
statusLabelis 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:
Map
statusLabelas the canonical status string in the normalizer and usestatus(integer) only for numeric comparisons or when the human-readable label is unavailable.Found by automated response shape drift audit