Drift
TypeScript declares escrow as a class field that is always present on every Exchange instance (as undefined until conditionally assigned), so reading exchange.escrow is always safe. Python only ever sets self.escrow inside the hosted-trading-allowlist conditional, with no default assigned anywhere else in __init__ — so for any Python exchange instance that isn't hosted-trading-allowlisted, exchange.escrow raises AttributeError.
TypeScript SDK
sdks/typescript/pmxt/client.ts:343 — public escrow?: Escrow; (always-declared field)
sdks/typescript/pmxt/client.ts:403-405 — conditionally assigned only for hosted-trading-allowlisted venues, but the declared field means exchange.escrow is always a safe read (undefined if unset).
Python SDK
sdks/python/pmxt/client.py:412-413:
if self.pmxt_api_key and self.exchange_name in HOSTED_TRADING_VENUES:
self.escrow = Escrow(self)
No self.escrow = None default exists anywhere else in __init__ (verified via full-file grep).
Expected
Python's Exchange.__init__ should initialize self.escrow = None unconditionally before the conditional assignment, matching TypeScript's always-present-but-possibly-unset field semantics.
Impact
This is a real behavioral trap for anyone porting code like if exchange.escrow: ... from TypeScript docs/examples to Python — a plain local Polymarket() instance without pmxt_api_key, or any non-hosted-trading-allowlisted venue, will hard-crash with AttributeError: 'X' object has no attribute 'escrow' in Python instead of the TypeScript-equivalent safe undefined/falsy check.
Found by automated SDK cross-language drift audit
Drift
TypeScript declares
escrowas a class field that is always present on everyExchangeinstance (asundefineduntil conditionally assigned), so readingexchange.escrowis always safe. Python only ever setsself.escrowinside the hosted-trading-allowlist conditional, with no default assigned anywhere else in__init__— so for any Python exchange instance that isn't hosted-trading-allowlisted,exchange.escrowraisesAttributeError.TypeScript SDK
sdks/typescript/pmxt/client.ts:343—public escrow?: Escrow;(always-declared field)sdks/typescript/pmxt/client.ts:403-405— conditionally assigned only for hosted-trading-allowlisted venues, but the declared field meansexchange.escrowis always a safe read (undefinedif unset).Python SDK
sdks/python/pmxt/client.py:412-413:No
self.escrow = Nonedefault exists anywhere else in__init__(verified via full-file grep).Expected
Python's
Exchange.__init__should initializeself.escrow = Noneunconditionally before the conditional assignment, matching TypeScript's always-present-but-possibly-unset field semantics.Impact
This is a real behavioral trap for anyone porting code like
if exchange.escrow: ...from TypeScript docs/examples to Python — a plain localPolymarket()instance withoutpmxt_api_key, or any non-hosted-trading-allowlisted venue, will hard-crash withAttributeError: 'X' object has no attribute 'escrow'in Python instead of the TypeScript-equivalent safeundefined/falsy check.Found by automated SDK cross-language drift audit