Skip to content

SDK drift: fetchArbitrage/fetch_arbitrage numeric/venue field defaulting coerces an explicit null in TypeScript but preserves it as None in Python #1535

Description

@realfishsam

Drift

fetchArbitrage's result mapping uses JS || fallback (coerces any falsy value, including an explicit null) in TypeScript, but Python's dict.get(key, default) only substitutes the default when the key is absent. This is distinct from already-filed #1500, which is scoped specifically to _parse_match_result's bestBid/bestAsk handling, not fetchArbitrage's result fields.

TypeScript SDK

sdks/typescript/pmxt/router.ts:613-621:

return (data as any[]).map((r) => ({
    marketA: convertMarket(r.marketA || {}),
    marketB: convertMarket(r.marketB || {}),
    spread: r.spread || 0,
    buyVenue: r.buyVenue || '',
    sellVenue: r.sellVenue || '',
    buyPrice: r.buyPrice || 0,
    sellPrice: r.sellPrice || 0,
    relation: r.relation,
    confidence: r.confidence,
}));

Python SDK

sdks/python/pmxt/router.py:640-651:

return [
    ArbitrageOpportunity(
        market_a=_parse_market(r.get("marketA", {})),
        market_b=_parse_market(r.get("marketB", {})),
        spread=r.get("spread", 0.0),
        buy_venue=r.get("buyVenue", ""),
        sell_venue=r.get("sellVenue", ""),
        buy_price=r.get("buyPrice", 0.0),
        sell_price=r.get("sellPrice", 0.0),
        relation=r.get("relation"),
        confidence=r.get("confidence"),
    )
    for r in raw
]

Expected

Both SDKs should apply the same fallback rule for these fields — either both coerce any falsy value (including explicit null) to the default, or both only substitute the default when the key is absent.

Impact

If the server sends spread: null or buyPrice: null (key present, value null) for a given arbitrage entry, TypeScript silently normalizes it to 0/"", while Python's ArbitrageOpportunity.spread/.buy_price remains None. Code that does arithmetic on spread/buyPrice in Python raises TypeError for a payload TypeScript would silently compute 0 for.


Found by automated SDK cross-language drift audit

Metadata

Metadata

Assignees

No one assigned

    Labels

    sdk-driftCross-language SDK consistency findings (TypeScript vs Python)

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions