Repository navigation
SDK drift: apiSecret forwards generically for all 17 TypeScript venue classes; Python's api_secret constructor param exists on only 4 of 17 #2158
Description
Drift
TypeScript's base Exchange class accepts apiSecret as a generic ExchangeOptions field and forwards it unconditionally to the sidecar for every venue subclass. Python's base Exchange.__init__ has no api_secret parameter at all, and only 4 of the 17 venue subclasses in _exchanges.py add their own api_secret parameter + override to forward it — the other 13 don't accept it as a keyword argument, so passing one raises TypeError.
Note: the earlier, TS-side version of this gap (Exchange.getCredentials() never forwarding apiSecret at all) was already tracked and fixed — see closed issues #1371 (merged via #1375), #1041, #971, #881. This issue is the current, still-open asymmetry that remains after that fix: TypeScript's forwarding is now generic across all venues, while Python's is restricted to a hand-picked subset.
TypeScript SDK
sdks/typescript/pmxt/client.ts:238 — apiSecret?: string; on base ExchangeOptions.
sdks/typescript/pmxt/client.ts:376 — this.apiSecret = options.apiSecret; in the base Exchange constructor.
sdks/typescript/pmxt/client.ts:483-489 (getCredentials()):
protected getCredentials(): ExchangeCredentials | undefined {
if (!this.apiKey && !this.apiSecret && !this.privateKey) {
return undefined;
}
return {
apiKey: this.apiKey,
apiSecret: this.apiSecret, // forwarded unconditionally for every venue
privateKey: this.privateKey,
funderAddress: this.proxyAddress,
signatureType: this.signatureType,
};
}Every venue class that just takes generic ExchangeOptions (e.g. Kalshi, Smarkets, Hyperliquid, Myriad, SuiBets, Rain, Hunch, Mock, Baozi, Opinion, Metaculus, PolymarketUS, KalshiDemo) therefore accepts new Kalshi({ apiSecret: '...' }).
Python SDK
Base Exchange.__init__ (sdks/python/pmxt/client.py:324-338) has no api_secret parameter, and _get_credentials_dict (client.py:559-575) never references it. Only 4 venue classes in sdks/python/pmxt/_exchanges.py add api_secret themselves: Polymarket (line 16), Limitless (line 82), Probable (line 217), GeminiTitan (line 546) — each with its own self.api_secret = api_secret and if self.api_secret: creds["apiSecret"] = self.api_secret override. The other 13 venue classes (e.g. Kalshi at _exchanges.py:131-168) have no api_secret parameter — pmxt.Kalshi(api_secret="...") raises TypeError: __init__() got an unexpected keyword argument 'api_secret'.
Expected
Python's per-venue constructors should generically accept and forward api_secret, matching TypeScript's uniform ExchangeOptions.apiSecret handling across all 17 venues — or, if apiSecret is intentionally meaningful only for specific venues, TypeScript should narrow getCredentials()/ExchangeOptions to the same venue subset Python uses.
Impact
This follows the same architectural pattern as the already-tracked #1889 (proxy_address/signature_type dropped by 15 of 17 Python venue constructors) and #1926 (api_key/private_key dropped by Baozi/Rain/Hunch/Mock/SuiBets in Python) — for the apiSecret field specifically, which neither of those covers. A user porting code from TypeScript to Python that passes apiSecret to any of the 13 unsupported Python venue classes gets an immediate, hard constructor TypeError, not a silently-ignored field.
Found by automated SDK cross-language drift audit
Activity