Skip to content

Response drift: suibets — isOnchain field absent from live API, on-chain routing broken #2015

Description

@realfishsam

Exchange

suibets

Severity

MEDIUM

What Our Normalizer Expects

core/src/exchanges/suibets/normalizer.ts reads raw.isOnchain to determine whether an offer is backed by an on-chain contract, and conditionally surfaces raw.onchainOfferId:

// normalizer.ts
isOnchain: raw.isOnchain,
onchainOfferId: raw.onchainOfferId,

SuibetsRawOffer (fetcher.ts) declares both as optional fields:

isOnchain?: boolean;
onchainOfferId?: string;

What The Live API Returns

The live GET https://www.suibets.com/api/p2p/offers response does not include isOnchain:

[].isOnchain   ← ABSENT (field no longer in response)

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

Note: onchainOfferId and onchainState sub-object are still present for on-chain offers.

Impact

MEDIUM: raw.isOnchain is always undefined (falsy) for every offer, regardless of whether the offer is actually on-chain. Any downstream logic that gates behavior on isOnchain === true silently treats all offers as off-chain:

  • On-chain routing and settlement paths are never triggered
  • UI elements that distinguish on-chain vs off-chain offers (e.g. chain explorer links) are suppressed for all offers including those with on-chain contracts
  • The presence of onchainState or a non-null onchainOfferId can serve as a proxy, but is not used

Suggested Fix

Replace the isOnchain field access with a derived check based on the still-present onchainState or onchainOfferId:

// normalizer.ts — derive isOnchain from surviving fields
isOnchain: raw.onchainOfferId != null || raw.onchainState != null,
onchainOfferId: raw.onchainOfferId,

Also remove isOnchain?: boolean from SuibetsRawOffer to reflect the actual API response shape.


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