Skip to content

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

@realfishsam

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:238apiSecret?: string; on base ExchangeOptions.
sdks/typescript/pmxt/client.ts:376this.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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions