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
Drift
fetchArbitrage's result mapping uses JS||fallback (coerces any falsy value, including an explicitnull) in TypeScript, but Python'sdict.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'sbestBid/bestAskhandling, notfetchArbitrage's result fields.TypeScript SDK
sdks/typescript/pmxt/router.ts:613-621:Python SDK
sdks/python/pmxt/router.py:640-651: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: nullorbuyPrice: null(key present, valuenull) for a given arbitrage entry, TypeScript silently normalizes it to0/"", while Python'sArbitrageOpportunity.spread/.buy_priceremainsNone. Code that does arithmetic onspread/buyPricein Python raisesTypeErrorfor a payload TypeScript would silently compute0for.Found by automated SDK cross-language drift audit