Skip to content

SDK drift: Escrow.withdrawals validates wallet address vs. include in opposite order #2353

Description

@realfishsam

Drift

Escrow.withdrawals/withdrawals validates its two inputs (address and include) in opposite order across the two SDKs. TypeScript resolves/validates the wallet address first, then checks include is non-empty. Python checks include first, then resolves the wallet address. This is the same class of bug already filed as #1892 for depositTx/deposit_tx, but that issue is scoped to a different method (deposit_tx) — no existing issue covers withdrawals.

TypeScript SDK

sdks/typescript/pmxt/escrow.ts:197-204:

async withdrawals(
    opts: { include?: string; address?: string } = {},
): Promise<unknown> {
    const address = resolveWalletAddress(this.client, opts.address);   // validated FIRST
    const include = (opts.include ?? "pending,events").trim();
    if (!include) {
        throw new ValidationError("include must not be empty", "include");
    }

Python SDK

sdks/python/pmxt/escrow.py:170-180:

def withdrawals(
    self,
    include: str = "pending,events",
    address: str | None = None,
) -> dict[str, Any]:
    include_value = include.strip()
    if not include_value:                                             # validated FIRST
        raise ValidationError("include must not be empty", field="include")

    wallet_address = quote(self._wallet_address(address), safe="")     # validated SECOND

Expected

Both languages should validate the same field first (either always wallet-address-then-include, or always include-then-wallet-address), matching whatever order the analogous depositTx/deposit_tx methods settle on when #1892 is resolved.

Impact

Calling withdrawals(include="") with no wallet address configured and no address override raises a wallet-address error in TypeScript but a "include must not be empty" ValidationError in Python — callers relying on catching a specific error type/field for one bad input get a different error depending on SDK language when both inputs happen to be invalid simultaneously.


Found by automated SDK cross-language drift audit

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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