Skip to main content
Hosted trading on PMXT settles through a non-custodial PreFundedEscrow smart contract on Polygon (chainId 137). USDC sits in the escrow under your wallet’s beneficial ownership; PMXT cannot move funds without an EIP-712 signature from your wallet. This page walks through the full lifecycle: approve, deposit, trade, withdraw.
You fund Polygon only. USDC always sits in the Polygon PreFundedEscrow for the currently hosted trading venues (Polymarket, Opinion, and Limitless). For hosted venues that don’t settle on Polygon (Opinion on BSC, Limitless on Base), PMXT operates an internal cross-chain leg that holds outcome tokens on the venue’s chain; you neither fund nor sign anything on that side. Pass any EVM-compatible private key; the same EVM wallet/key can trade the currently hosted venues.

Why escrow at all?

Polymarket’s CLOB exchange expects the submitter to be the operator of the user’s CLOB proxy wallet. That proxy is created by Polymarket’s USDC.e adapter and is non-trivial to operate from a third-party context. PMXT’s PreFundedEscrow solves this by acting as a pre-funded operator: the user deposits USDC once, PMXT routes orders against that balance, and the user can withdraw at any time. The user signs every order with EIP-712 against the Polygon escrow’s domain; the escrow contract can only spend USDC against signed orders, never unilaterally. For Opinion, the same Polygon escrow balance funds a cross-chain settlement leg into a BSC-side VenueEscrow that holds Opinion outcome tokens — you still only deposit on Polygon, and your EIP-712 signature still targets the Polygon escrow domain. The BSC hop is PMXT’s plumbing.

The client.escrow namespace

Hosted exchange clients (Polymarket, Opinion, Limitless) expose an escrow namespace. Every method builds an unsigned transaction. Your wallet — MetaMask, ethers Wallet, viem, web3.py, etc. — is responsible for signing and broadcasting it. PMXT never holds your private key. See the source: sdks/python/pmxt/escrow.py and sdks/typescript/pmxt/escrow.ts.

1. Approve and deposit

Before the first deposit, the escrow contract needs permission to pull USDC from your wallet (a standard ERC-20 approval). Then you deposit. For most users, the dashboard handles both in a single connected-wallet flow. Open pmxt.dev/dashboard, connect the wallet whose address you passed to the SDK, and use the Deposit flow. Your wallet (MetaMask, Rabby, WalletConnect, etc.) prompts you to sign — PMXT never sees your private key.
  1. Go to pmxt.dev/dashboard and connect the matching wallet.
  2. Click Deposit and enter the USDC amount.
  3. Approve the USDC allowance in your wallet (one-time per token).
  4. Confirm the deposit transaction in your wallet.
Approval is one-time per token + spender; the deposit itself is one-time setup before your first trade. If you ever rotate the escrow contract (rare, gated on a PMXT migration announcement), you’ll need to re-approve.
If you’re scripting deposits (CI, treasury automation, custom wallet integrations), client.escrow builds unsigned transactions you sign and broadcast with your own wallet library.Approve
DepositAmounts are in whole USDC (6 decimals); the SDK validates precision and rejects values like 0.0000001.
USDC precision is 6 decimals. The SDK rejects 0.0000001 with ValidationError. Pre-round before passing the value in.

2. Confirm the deposit

After the deposit transaction confirms on-chain, the balance shows up in escrow. fetch_balance is the canonical check.
On-chain confirmation usually takes 2–5 seconds on Polygon. If fetch_balance still reads zero 30 seconds after broadcast, check the tx on Polygonscan — a failed deposit (e.g. due to missing approval) will not update escrow state.

3. Trade

With escrow funded, you can trade. create_order and submit_order debit the escrow balance; cancel_order releases the reservation. No additional escrow calls are needed during normal trading — the balance just gets spent.

4. Withdraw

Withdrawals are a two-step timelock. You first request a withdrawal; after a contract-enforced delay (~1 hour in production), you claim it. You can also cancel a pending request. The timelock is a security feature — it gives you a window to detect and abort an unauthorized withdrawal even if the operator key were compromised. Because the escrow is non-custodial, every withdrawal step requires a signature from your wallet. The dashboard handles the full request → wait → claim journey as one user flow.
  1. Open pmxt.dev/dashboard and connect your wallet.
  2. Click Withdraw, enter the USDC amount, and confirm the request transaction in your wallet.
  3. Wait for the timelock to elapse (~1 hour in production). The dashboard shows a countdown for each pending request.
  4. Come back, click Claim on the matured request, and confirm the claim transaction in your wallet. Funds move from escrow to your wallet.
If you change your mind during the timelock window, the dashboard exposes a Cancel action on the pending request — the funds stay in escrow as free balance.
For scripted withdrawals, client.escrow.withdraw_tx builds unsigned request / claim / cancel transactions you sign and broadcast with your own wallet library.Request
Inspect pending withdrawals
ClaimOnce claimable_at has passed, claim the funds — they move from escrow to your wallet.
claim does not take an amount. It claims all matured requests at once. The escrow tracks individual request maturities; only matured ones settle.
CancelIf you change your mind during the timelock window, cancel a pending request and the funds remain in escrow as free balance.

Errors you might hit

  • MissingWalletAddressclient.escrow.* requires wallet_address on the exchange constructor. Pass it explicitly.
  • ValidationError: amount precision exceeds 6 decimals — round before passing.
  • InsufficientEscrowBalance (during a trade) — deposit more before retrying, or wait for matured withdrawals to clear pending positions.
  • HostedTradingError (5xx) — transient server error; retry with backoff. See Hosted errors.

Source references