Skip to content

Python SDK _get_credentials_dict does not forward walletAddress — Limitless delegated signing broken #935

@realfishsam

Description

@realfishsam

Gap

The core ExchangeCredentials interface includes walletAddress?: string — used by LimitlessExchange for delegated signing (looking up a profile ID from a wallet address). The Python SDK's _get_credentials_dict method, which serializes credentials into the sidecar request body, does not include walletAddress in the dict it builds. Even if a caller somehow passes wallet_address during construction (it is not a constructor parameter on the base Exchange), it would be silently dropped before reaching the sidecar.

Core

core/src/BaseExchange.ts:371-392

export interface ExchangeCredentials {
    apiKey?: string;
    apiSecret?: string;
    passphrase?: string;
    apiToken?: string;
    privateKey?: string;
    signatureType?: number | string;
    funderAddress?: string;
    walletAddress?: string;   // ← used by Limitless for delegated signing
    baseUrl?: string;
}

core/src/exchanges/limitless/index.ts:104,115walletAddress is read from credentials.walletAddress and used to look up the signing profile for delegated orders.

Python SDK

sdks/python/pmxt/client.py:490-506

def _get_credentials_dict(self) -> Optional[Dict[str, Any]]:
    """Build credentials dictionary for API requests."""
    if not self.api_key and not self.private_key and not self.api_token:
        return None

    creds = {}
    if self.api_key:
        creds["apiKey"] = self.api_key
    if self.private_key:
        creds["privateKey"] = self.private_key
    if self.api_token:
        creds["apiToken"] = self.api_token
    if self.proxy_address:
        creds["funderAddress"] = self.proxy_address
    if self.signature_type is not None:
        creds["signatureType"] = self.signature_type
    return creds if creds else None

walletAddress is never set in this dict. The base Exchange.__init__ also has no wallet_address parameter, so there is no way to supply the value at all.

TypeScript SDK

The TypeScript SDK's getCredentials() method in client.ts similarly builds a credentials object from the constructor options. walletAddress is not part of ExchangeOptions in the TypeScript SDK either, so neither SDK forwards this credential.

Note: Issue #853 tracks the per-exchange OpinionExchangeOptions.walletAddress gap. This issue tracks the lower-level, cross-cutting failure: even if a future fix adds walletAddress to the exchange constructor, the Python credential serialization layer would still silently drop it.

Evidence

grep -n "walletAddress\|wallet_address" sdks/python/pmxt/client.py → zero results.
grep -n "walletAddress" core/src/BaseExchange.ts → line 388.
grep -n "walletAddress" core/src/exchanges/limitless/index.ts → lines 104, 115 confirming the field is consumed by exchange logic.

Impact

Limitless delegated signing workflows cannot pass the walletAddress credential through the Python SDK, even if the caller knows the wallet address. The credential is absent from the serialized dict sent to the sidecar, so the sidecar-side LimitlessExchange sees credentials.walletAddress === undefined and falls through to the default signing path. Delegated signing fails silently — no error, just wrong behavior (orders placed on the caller's own profile instead of the delegated profile).


Found by automated Core-to-SDK surface coverage audit

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    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