Skip to main content

What it is

User-owned execution is an optional trading mode for applications whose users should trade as themselves instead of attributing activity to a builder account.
Requires polynode-sdk >= 0.13.0, Python polynode >= 0.13.0, or Rust polynode >= 0.16.0 with the trading feature.
Set executionMode: "user_owned" in TypeScript, execution_mode=ExecutionMode.USER_OWNED in Python, or execution_mode: ExecutionMode::UserOwned in Rust. Builder mode remains the default, so existing integrations do not change unless they opt in. In user-owned mode:
  • Orders use the user’s normal CLOB credentials and carry zero builder attribution.
  • Gasless smart-wallet operations use authorization owned by the signing wallet, not a builder credential.
  • Builder credentials, builder authentication headers, and nonzero builder overrides are rejected.
  • Activity does not consume a builder’s relayer allowance.
Normal Polymarket wallet, market, balance, and order rules still apply.

Why use it

Use user-owned execution when a user should be able to trade independently of your platform’s builder allowance and your platform does not need builder credit for that activity. Keep the default builder mode when your platform wants builder attribution or uses its own builder credentials.

Wallet control and custody

Polynode does not receive or store the user’s private key, seed phrase, or wallet signer. The user’s wallet signs the ownership message, orders, and smart-wallet actions. Your application should never ask a user to send you a private key. The returned wallet-owned relayer credential is not a wallet key and cannot sign an order, approve a token, or transfer funds by itself. Treat it as a backend secret because it is tied to that user’s gasless execution account. The SDK keeps the credential in memory unless your application explicitly saves it. Store it only in your own backend secret manager. Do not put it in browser storage, logs, analytics, source control, or client-visible configuration.

Platform integration

Treat one signing wallet as the unit of isolation. A platform serving many users should keep a separate wallet-owned relayer credential for each wallet address and create a separate trader context for the active wallet. Never share one trader instance or relayer credential across two users. For each wallet:
  1. Load that wallet’s credential from your encrypted backend secret store.
  2. If it does not exist, run the two-step browser authorization below and save the returned credential under the same expected wallet address.
  3. Pass the credential to that wallet’s trader configuration and complete onboarding or trading.
  4. Clear the trader context when the request, worker job, or user session ends.
The browser receives only the short-lived message and returns its signature; your Polynode API key and wallet-owned relayer credential remain on the backend. An individual browser-only application may keep the credential in memory for the current page session, but should let it disappear when the page closes rather than writing it to browser storage. Reauthorization reuses the wallet’s existing authorization when available; it does not create builder attribution.

Supported wallets

The first release supports normal EOA signers and EOA-controlled Safe or deposit wallet accounts. The signer must support a standard personal-message signature. Gasless split and merge require an EOA-controlled Safe or deposit wallet. A plain EOA can sign orders, but these gasless position methods fail closed rather than silently routing through a different wallet. Legacy POLY_PROXY accounts and Magic/DID signers are not supported in user-owned mode. Keep those accounts on the default builder path for now.

Browser-wallet authorization

Use the two-step API when the user signs in a browser. Keep the Polynode API key and the complete challenge object on your backend; send only the displayed message to the user’s wallet.
Backend
Browser
The equivalent backend primitives are begin_user_relayer_authorization() and complete_user_relayer_authorization() in Python, and PolyNodeTrader::begin_user_relayer_authorization() and PolyNodeTrader::complete_user_relayer_authorization() in Rust.

TypeScript

For a caller-controlled service wallet or signing callback, the combined flow is one call:
Use await trader.authorizeUserOwnedExecution(userControlledSigner) when you want the combined authorization result without running the rest of onboarding.

Python

Use await trader.authorize_user_owned_execution(user_controlled_signer) when you want the combined authorization result without running full onboarding. The existing synchronous trader.split() and trader.merge() methods remain build-only helpers; use the explicit execute_* methods above for gasless submission.

Rust

Use authorize_user_owned_execution(&signer) when you want the combined result without running full onboarding. Supply a previously saved credential through TraderConfig.user_relayer_credentials on later runs.

CLOB transport

User-owned orders go directly from the SDK to the official Polymarket CLOB by default. There is no automatic fallback between transports, which prevents an ambiguous response from creating a duplicate order. Integrations may explicitly select Polynode’s regional proxy: The proxy changes only the network path. It does not add builder attribution or take wallet custody.

Important limitations

  • User-owned mode does not support Polynode fee escrow. A positive SDK fee configuration fails before signing or submitting an order.
  • Normal CLOB credentials are still required and should be protected as secrets.
  • Market balances, token approvals, minimum sizes, rate limits, and order rules are unchanged.
  • A split must be followed by a merge of the same complete set to restore the original collateral amount.

Integration checklist

  1. Enable user-owned execution only for users who opt in.
  2. Keep the Polynode API key and full challenge object on your backend.
  3. Ask the wallet to sign only the exact message returned by the SDK.
  4. Bind the returned signature and credential to the same expected address.
  5. Keep wallet-owned and CLOB credentials in your backend secret manager.
  6. Do not pass builder credentials, a nonzero builder code, or a positive fee configuration.
  7. Confirm the ready status reports user-owned execution before submitting.
  8. Close the trader on shutdown to clear its active signer and in-memory credential.

Common errors