Update Polymarket docs - 2026-05-12
Updated 6 files that changed on docs.polymarket.com: - docs/api-reference/markets/get-clob-market-info.md - docs/builders/fees.md - docs/concepts/pusd.md - docs/resources/contracts.md - docs/trading/deposit-wallets.md - docs/v2-migration.md
This commit is contained in:
@@ -1,183 +1 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Get CLOB market info
|
||||
|
||||
> Returns all CLOB-level parameters for a market in a single call —
|
||||
tokens, tick size, base fees, rewards, RFQ status, and fee details.
|
||||
|
||||
|
||||
|
||||
|
||||
## OpenAPI
|
||||
|
||||
````yaml /api-spec/clob-openapi.yaml get /clob-markets/{condition_id}
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Polymarket CLOB API
|
||||
description: Polymarket CLOB API Reference
|
||||
license:
|
||||
name: MIT
|
||||
identifier: MIT
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: https://clob.polymarket.com
|
||||
description: Production CLOB API
|
||||
- url: https://clob-staging.polymarket.com
|
||||
description: Staging CLOB API
|
||||
security: []
|
||||
tags:
|
||||
- name: Trade
|
||||
description: Trade endpoints
|
||||
- name: Markets
|
||||
description: Market data endpoints
|
||||
- name: Account
|
||||
description: Account and authentication endpoints
|
||||
- name: Notifications
|
||||
description: User notification endpoints
|
||||
- name: Rewards
|
||||
description: Rewards and earnings endpoints
|
||||
- name: Rebates
|
||||
description: Maker rebate endpoints
|
||||
paths:
|
||||
/clob-markets/{condition_id}:
|
||||
get:
|
||||
tags:
|
||||
- Markets
|
||||
summary: Get CLOB market info
|
||||
description: |
|
||||
Returns all CLOB-level parameters for a market in a single call —
|
||||
tokens, tick size, base fees, rewards, RFQ status, and fee details.
|
||||
operationId: getClobMarketInfo
|
||||
parameters:
|
||||
- name: condition_id
|
||||
in: path
|
||||
required: true
|
||||
description: The condition ID of the market
|
||||
schema:
|
||||
type: string
|
||||
example: '0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af'
|
||||
responses:
|
||||
'200':
|
||||
description: Successfully retrieved CLOB market info
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ClobMarketDetails'
|
||||
'400':
|
||||
description: Bad request - Invalid condition ID
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
components:
|
||||
schemas:
|
||||
ClobMarketDetails:
|
||||
type: object
|
||||
description: >-
|
||||
CLOB-level parameters for a market — tokens, tick size, base fees,
|
||||
rewards, RFQ status, and fee details.
|
||||
properties:
|
||||
gst:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: >-
|
||||
Game start time (used for sports markets), ISO 8601 timestamp or
|
||||
null
|
||||
r:
|
||||
$ref: '#/components/schemas/ClobRewards'
|
||||
t:
|
||||
type: array
|
||||
description: Tokens for this market
|
||||
items:
|
||||
$ref: '#/components/schemas/ClobToken'
|
||||
mos:
|
||||
type: number
|
||||
format: float
|
||||
description: Minimum order size
|
||||
example: 5
|
||||
mts:
|
||||
type: number
|
||||
format: float
|
||||
description: Minimum tick size (price increment)
|
||||
example: 0.01
|
||||
mbf:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Maker base fee in basis points
|
||||
example: 0
|
||||
tbf:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Taker base fee in basis points
|
||||
example: 0
|
||||
rfqe:
|
||||
type: boolean
|
||||
description: Whether RFQ (Request for Quote) is enabled for this market
|
||||
itode:
|
||||
type: boolean
|
||||
description: Whether taker order delay is enabled
|
||||
ibce:
|
||||
type: boolean
|
||||
description: Whether Blockaid check is enabled
|
||||
fd:
|
||||
$ref: '#/components/schemas/FeeDetails'
|
||||
oas:
|
||||
type: integer
|
||||
description: Minimum order age in seconds
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required:
|
||||
- error
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
description: Error message
|
||||
ClobRewards:
|
||||
type: object
|
||||
description: Rewards configuration for a market.
|
||||
additionalProperties: true
|
||||
ClobToken:
|
||||
type: object
|
||||
description: A token in a CLOB market with its ID and outcome label.
|
||||
properties:
|
||||
t:
|
||||
type: string
|
||||
description: The token ID
|
||||
example: >-
|
||||
71321045679252212594626385532706912750332728571942532289631379312455583992563
|
||||
o:
|
||||
type: string
|
||||
description: Outcome label for the token (e.g. "Yes", "No")
|
||||
example: 'Yes'
|
||||
FeeDetails:
|
||||
type: object
|
||||
description: Fee curve parameters for a market.
|
||||
properties:
|
||||
r:
|
||||
type: number
|
||||
format: float
|
||||
nullable: true
|
||||
description: Fee rate
|
||||
example: 0.02
|
||||
e:
|
||||
type: number
|
||||
format: float
|
||||
nullable: true
|
||||
description: Fee curve exponent
|
||||
example: 2
|
||||
to:
|
||||
type: boolean
|
||||
nullable: true
|
||||
description: Whether fees apply to takers only
|
||||
example: true
|
||||
|
||||
````
|
||||
null
|
||||
+1
-264
@@ -1,264 +1 @@
|
||||
# Builder Fees
|
||||
|
||||
> How builders earn fees on orders routed through their applications, and how to integrate.
|
||||
|
||||
CLOB V2 introduces a fee layer that lets builders earn a fee on every order routed through their application. When a builder attaches their unique **builder code** to an order and that order matches, a **builder fee** is collected alongside any platform fee.
|
||||
|
||||
Builder fees are flat percentages of trade notional, configured by each builder within enforced limits. They're additive — they stack on top of platform fees, never replace them.
|
||||
|
||||
<Note>
|
||||
New to the Builder Program? Start with [Builder Program](/builders/overview). This page covers the fee layer specifically.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## How it works
|
||||
|
||||
<Frame>
|
||||
<img src="https://mintcdn.com/polymarket-292d1b1b/lWwKl4XdsXxYugaA/images/core-concepts/builder-fee.png?fit=max&auto=format&n=lWwKl4XdsXxYugaA&q=85&s=9287dc95f24f07bcb9f33c4d7d6ed0f2" alt="" className="dark:hidden" width="2068" height="952" data-path="images/core-concepts/builder-fee.png" />
|
||||
|
||||
<img src="https://mintcdn.com/polymarket-292d1b1b/lWwKl4XdsXxYugaA/images/dark/core-concepts/builder-fee.png?fit=max&auto=format&n=lWwKl4XdsXxYugaA&q=85&s=31b5e9be53b16738ad9f2b833b1eb02a" alt="" className="hidden dark:block" width="2068" height="952" data-path="images/dark/core-concepts/builder-fee.png" />
|
||||
</Frame>
|
||||
|
||||
Builder fees and platform fees are independent. What the user pays depends on the market config and whether a builder code is attached:
|
||||
|
||||
| Market | Builder code attached | User pays |
|
||||
| -------------------- | --------------------- | -------------------------- |
|
||||
| No platform fee | No | Nothing |
|
||||
| No platform fee | Yes | Builder fee only |
|
||||
| Platform fee enabled | No | Platform fee only |
|
||||
| Platform fee enabled | Yes | Platform fee + builder fee |
|
||||
|
||||
Builder fees never replace platform fees — they're always additive.
|
||||
|
||||
<Warning>
|
||||
Polymarket reserves the right to revoke your ability to charge a builder fee in its sole discretion, for any reason or no reason, including but not limited to instances where fees are determined to have been collected through fraudulent, deceptive, misleading, automated, self-referred, or other non-bona fide trading activity.
|
||||
</Warning>
|
||||
|
||||
***
|
||||
|
||||
## Registration
|
||||
|
||||
Register for a builder code through your Polymarket account.
|
||||
|
||||
<Steps>
|
||||
<Step title="Create a builder profile">
|
||||
Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) and set up your builder profile.
|
||||
</Step>
|
||||
|
||||
<Step title="Set your fee rates">
|
||||
Configure two rates on your profile:
|
||||
|
||||
* `builder_taker_fee_bps` — charged on taker orders routed through your app
|
||||
* `builder_maker_fee_bps` — charged on maker orders routed through your app
|
||||
</Step>
|
||||
|
||||
<Step title="Copy your builder code">
|
||||
Your profile is assigned a `bytes32` builder code. Attach it to every order you submit.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Fee rate limits
|
||||
|
||||
| Parameter | Default | Maximum |
|
||||
| -------------- | ---------- | ------------- |
|
||||
| Taker fee rate | 0 bps (0%) | 100 bps (1%) |
|
||||
| Maker fee rate | 0 bps (0%) | 50 bps (0.5%) |
|
||||
| Granularity | — | 1 bp (0.01%) |
|
||||
|
||||
### Rate change policy
|
||||
|
||||
Fee rate changes are gated so users can see them coming:
|
||||
|
||||
* **Cooldown.** One rate change per 7 days.
|
||||
* **Advance notice.** Changes take effect 3 days after being scheduled.
|
||||
* **One pending change at a time.** You can't queue multiple changes — wait for the current one to take effect (or cancel it) before scheduling another.
|
||||
|
||||
***
|
||||
|
||||
## SDK integration
|
||||
|
||||
The V2 SDK handles builder codes natively — no separate signing library, no extra headers.
|
||||
|
||||
### Install
|
||||
|
||||
<CodeGroup>
|
||||
```bash TypeScript theme={null}
|
||||
npm install @polymarket/clob-client-v2 viem
|
||||
```
|
||||
|
||||
```bash Python theme={null}
|
||||
pip install py-clob-client-v2
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
Coming from the old `@polymarket/builder-signing-sdk` + HMAC header flow? That's gone in V2 — see [Migrating to CLOB V2](/v2-migration#builder-program) for the full upgrade path.
|
||||
</Note>
|
||||
|
||||
### Attach your builder code
|
||||
|
||||
Pass `builderCode` on every order your application submits. This is how trades are attributed to your profile.
|
||||
|
||||
**Limit order:**
|
||||
|
||||
```typescript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "0x123...",
|
||||
price: 0.55,
|
||||
size: 100,
|
||||
side: Side.BUY,
|
||||
expiration: 1714000000,
|
||||
builderCode: process.env.POLY_BUILDER_CODE,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.GTC,
|
||||
);
|
||||
```
|
||||
|
||||
**Market order:**
|
||||
|
||||
```typescript theme={null}
|
||||
const response = await client.createAndPostMarketOrder(
|
||||
{
|
||||
tokenID: "0x123...",
|
||||
side: Side.BUY,
|
||||
amount: 500,
|
||||
price: 0.5, // worst-price limit (slippage protection)
|
||||
userUSDCBalance: 1000, // optional — enables fee-aware fill calculations
|
||||
builderCode: process.env.POLY_BUILDER_CODE,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.FOK,
|
||||
);
|
||||
```
|
||||
|
||||
If `builderCode` is omitted, no builder fee is charged.
|
||||
|
||||
<Tip>
|
||||
You can also pass `builderConfig: { builderCode }` once at client construction and every order inherits it. See [Migrating to CLOB V2](/v2-migration#builder-program) for both patterns.
|
||||
</Tip>
|
||||
|
||||
### Query fee parameters
|
||||
|
||||
`getClobMarketInfo()` returns both platform and builder fee parameters for a market:
|
||||
|
||||
```typescript theme={null}
|
||||
const info = await client.getClobMarketInfo(conditionID);
|
||||
|
||||
// Platform fee
|
||||
// info.fd.r — fee rate
|
||||
// info.fd.e — fee exponent
|
||||
// info.fd.to — taker-only flag
|
||||
|
||||
// Builder fee
|
||||
// info.mbf — builder maker fee rate
|
||||
// info.tbf — builder taker fee rate
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Fee calculation
|
||||
|
||||
### Platform fees
|
||||
|
||||
Platform fees use a dynamic per-market formula:
|
||||
|
||||
```
|
||||
platform_fee = C × feeRate × p × (1 - p)
|
||||
```
|
||||
|
||||
Where `C` is the trade size, `p` is the order price, and `feeRate` is a per-market parameter. Platform fees are currently taker-only and are not configurable by builders.
|
||||
|
||||
### Builder fees
|
||||
|
||||
Builder fees are a flat percentage of notional:
|
||||
|
||||
```
|
||||
builder_fee = notional × builder_fee_rate_bps / 10000
|
||||
```
|
||||
|
||||
**Example.** A 1,000 pUSD taker buy routed through a builder charging 100 bps (1%) taker fee:
|
||||
|
||||
```
|
||||
builder_fee = 1000 × 100 / 10000 = 10 pUSD
|
||||
```
|
||||
|
||||
The maker and taker sides of a single trade can have different builder codes and different rates. If Builder A (0.3% maker) posts the resting order and Builder B (0.8% taker) submits the matching order, each earns their respective fee from their respective side.
|
||||
|
||||
### Balance checks
|
||||
|
||||
The CLOB's balance checker accounts for all applicable fees (platform + builder) when validating an order. Users must have enough pUSD to cover the trade plus the maximum possible fees.
|
||||
|
||||
For market buy orders, pass `userUSDCBalance` and the SDK computes fee-adjusted fill amounts automatically.
|
||||
|
||||
***
|
||||
|
||||
## Onchain attribution
|
||||
|
||||
Builder attribution is part of the signed V2 order struct — not an offchain label. The `builder` field appears in every `OrderFilled` event emitted by the CTF Exchange V2 contract.
|
||||
|
||||
### V2 order struct
|
||||
|
||||
```
|
||||
salt, maker, signer, tokenId, makerAmount, takerAmount,
|
||||
side, signatureType, timestamp, metadata, builder
|
||||
```
|
||||
|
||||
The `builder` field is a `bytes32` matching your registered builder code.
|
||||
|
||||
### EIP-712 domain
|
||||
|
||||
The Exchange domain version is `"2"` in V2 (up from `"1"`). If you construct EIP-712 typed data manually rather than via the SDK, update your domain separator — see [For API users](/v2-migration#for-api-users) in the migration guide.
|
||||
|
||||
***
|
||||
|
||||
## Fee processing and payouts
|
||||
|
||||
When a user places an order with your `builderCode` attached:
|
||||
|
||||
1. The CLOB validates the order and the builder code.
|
||||
2. At match time, the Fees Service computes the platform and builder fees for each side.
|
||||
3. The trade settles onchain via `CTFExchangeV2.matchOrders()`, emitting `OrderFilled` events.
|
||||
4. The Builders Service indexes those events, joins onchain attribution with your builder profile, and accrues your earned fees.
|
||||
|
||||
Collected builder fees are distributed to the wallet associated with your builder profile.
|
||||
|
||||
***
|
||||
|
||||
## Program policies
|
||||
|
||||
### Disabled codes
|
||||
|
||||
Polymarket may disable a builder code at any time — for violations of the Builder Program terms, abusive fee practices, or platform integrity concerns. Orders carrying a disabled code will be rejected by the CLOB.
|
||||
|
||||
### Public visibility
|
||||
|
||||
Builder profiles and fee rates are publicly queryable. This is intentional — it lets users and third parties see what a builder charges before using their app.
|
||||
|
||||
### Existing builders
|
||||
|
||||
Builders with V1 integrations have builder code entities provisioned automatically. No action is required beyond upgrading to the V2 SDK and attaching your builder code to orders. See [Migrating to CLOB V2](/v2-migration) for the full upgrade path.
|
||||
|
||||
***
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Builder Program" icon="hammer" href="/builders/overview">
|
||||
Overview of the Builder Program and benefits
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Methods" icon="code" href="/trading/clients/builder">
|
||||
SDK methods for querying your builder trades and orders
|
||||
</Card>
|
||||
|
||||
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
|
||||
Details on attaching builder codes to orders
|
||||
</Card>
|
||||
|
||||
<Card title="Migration Guide" icon="arrow-right" href="/v2-migration">
|
||||
Full V2 migration guide
|
||||
</Card>
|
||||
</CardGroup>
|
||||
null
|
||||
+1
-162
@@ -1,162 +1 @@
|
||||
# Polymarket USD
|
||||
|
||||
> pUSD — the collateral token used for all trading on Polymarket
|
||||
|
||||
**pUSD** (Polymarket USD) is the collateral token used for all trading on Polymarket. It's a standard ERC-20 token on Polygon, backed by USDC. The smart contract — which enables the withdrawal functionality — enforces the backing. No algorithmic peg, no fractional reserve.
|
||||
|
||||
<Note>
|
||||
**Day to day, nothing changes.** You load funds, see a balance, trade, and
|
||||
withdraw. pUSD is the technical settlement layer underneath the same
|
||||
experience you're used to.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Why pUSD
|
||||
|
||||
The protocol settles all trading activity in native USDC, providing a more capital efficient, scalable, and institutionally aligned settlement standard as the platform continues to grow.
|
||||
|
||||
pUSD is a standard ERC-20 wrapper that represents a USDC claim. Wrapping and unwrapping are enforced onchain by the `CollateralOnramp` and `CollateralOfframp` contracts.
|
||||
|
||||
***
|
||||
|
||||
## Key facts
|
||||
|
||||
| | |
|
||||
| -------------- | ----------------------- |
|
||||
| Token standard | ERC-20 |
|
||||
| Network | Polygon mainnet |
|
||||
| Decimals | 6 |
|
||||
| Backing | USDC (enforced onchain) |
|
||||
| Transferable | Yes — standard ERC-20 |
|
||||
|
||||
pUSD is designed to function within Polymarket. There are no current plans to list it on external exchanges.
|
||||
|
||||
See the [Contracts](/resources/contracts) page for all collateral-related contract addresses.
|
||||
|
||||
***
|
||||
|
||||
## Wrapping — USDC.e → pUSD
|
||||
|
||||
Use the **CollateralOnramp** to wrap USDC.e into pUSD.
|
||||
|
||||
```solidity theme={null}
|
||||
function wrap(address _asset, address _to, uint256 _amount) external
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
* `_asset` — address of the asset being wrapped. Must be USDC.e.
|
||||
* `_to` — recipient of the minted pUSD. Does not have to be `msg.sender`.
|
||||
* `_amount` — amount to wrap, in USDC.e base units (6 decimals).
|
||||
|
||||
**Requirements**
|
||||
|
||||
* The caller must first approve the **CollateralOnramp** contract (not the pUSD token) to spend USDC.e.
|
||||
* Reverts with `OnlyUnpaused()` if the admin has paused USDC.e.
|
||||
|
||||
### Example
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import {
|
||||
createWalletClient,
|
||||
createPublicClient,
|
||||
http,
|
||||
parseAbi,
|
||||
parseUnits,
|
||||
} from "viem";
|
||||
import { polygon } from "viem/chains";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
|
||||
const walletClient = createWalletClient({ account, chain: polygon, transport: http() });
|
||||
const publicClient = createPublicClient({ chain: polygon, transport: http() });
|
||||
|
||||
const ONRAMP = "0x93070a847efEf7F70739046A929D47a521F5B8ee" as const;
|
||||
const USDCE = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" as const; // USDC.e on Polygon
|
||||
|
||||
const amount = parseUnits("100", 6); // 100 USDC.e
|
||||
|
||||
// 1. Approve the Onramp to spend your USDC.e
|
||||
const approveHash = await walletClient.writeContract({
|
||||
address: USDCE,
|
||||
abi: parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]),
|
||||
functionName: "approve",
|
||||
args: [ONRAMP, amount],
|
||||
});
|
||||
await publicClient.waitForTransactionReceipt({ hash: approveHash });
|
||||
|
||||
// 2. Wrap USDC.e → pUSD
|
||||
const wrapHash = await walletClient.writeContract({
|
||||
address: ONRAMP,
|
||||
abi: parseAbi(["function wrap(address _asset, address _to, uint256 _amount)"]),
|
||||
functionName: "wrap",
|
||||
args: [USDCE, account.address, amount],
|
||||
});
|
||||
await publicClient.waitForTransactionReceipt({ hash: wrapHash });
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from web3 import Web3
|
||||
|
||||
ONRAMP = "0x93070a847efEf7F70739046A929D47a521F5B8ee"
|
||||
USDCE = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
|
||||
|
||||
amount = 100 * 10**6 # 100 USDC.e
|
||||
|
||||
# 1. Approve the Onramp to spend your USDC.e
|
||||
usdce = w3.eth.contract(address=USDCE, abi=[{
|
||||
"name": "approve", "type": "function",
|
||||
"inputs": [{"name": "spender", "type": "address"},
|
||||
{"name": "amount", "type": "uint256"}],
|
||||
"outputs": [{"type": "bool"}],
|
||||
}])
|
||||
usdce.functions.approve(ONRAMP, amount).transact({"from": address})
|
||||
|
||||
# 2. Wrap USDC.e → pUSD
|
||||
onramp = w3.eth.contract(address=ONRAMP, abi=[{
|
||||
"name": "wrap", "type": "function",
|
||||
"inputs": [{"name": "_asset", "type": "address"},
|
||||
{"name": "_to", "type": "address"},
|
||||
{"name": "_amount", "type": "uint256"}],
|
||||
"outputs": [],
|
||||
}])
|
||||
onramp.functions.wrap(USDCE, address, amount).transact({"from": address})
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Unwrapping — pUSD → USDC.e
|
||||
|
||||
Use the **CollateralOfframp** to unwrap pUSD back into USDC.e.
|
||||
|
||||
```solidity theme={null}
|
||||
function unwrap(address _asset, address _to, uint256 _amount) external
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
|
||||
* `_asset` — asset you want to receive. Must be USDC.e.
|
||||
* `_to` — recipient of the underlying asset.
|
||||
* `_amount` — amount of pUSD to unwrap (6 decimals).
|
||||
|
||||
**Requirements**
|
||||
|
||||
* The caller must first approve the **CollateralOfframp** contract to spend their pUSD.
|
||||
* Same pause gate as the Onramp.
|
||||
|
||||
***
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Contracts" icon="file-contract" href="/resources/contracts">
|
||||
All Polymarket contract addresses and audits
|
||||
</Card>
|
||||
|
||||
<Card title="Bridge" icon="arrow-right-arrow-left" href="/trading/bridge/deposit">
|
||||
Deposit from other chains — auto-wraps to pUSD
|
||||
</Card>
|
||||
</CardGroup>
|
||||
null
|
||||
@@ -1,79 +1 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Contracts
|
||||
|
||||
> All Polymarket smart contract addresses, audits, and security resources
|
||||
|
||||
All Polymarket contracts are deployed on **Polygon mainnet** (Chain ID: 137). This is the single source of truth for all contract addresses used across the platform.
|
||||
|
||||
***
|
||||
|
||||
## Core Trading Contracts
|
||||
|
||||
| Contract | Address |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| CTF Exchange | [`0xE111180000d2663C0091e4f400237545B87B996B`](https://polygonscan.com/address/0xE111180000d2663C0091e4f400237545B87B996B) |
|
||||
| Neg Risk CTF Exchange | [`0xe2222d279d744050d28e00520010520000310F59`](https://polygonscan.com/address/0xe2222d279d744050d28e00520010520000310F59) |
|
||||
| Neg Risk Adapter | [`0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296`](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296) |
|
||||
| Conditional Tokens (CTF) | [`0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) |
|
||||
|
||||
***
|
||||
|
||||
## Collateral Contracts
|
||||
|
||||
| Contract | Address |
|
||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| pUSD — CollateralToken (proxy) | [`0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`](https://polygonscan.com/address/0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB) |
|
||||
| pUSD — CollateralToken (impl) | [`0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f`](https://polygonscan.com/address/0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f) |
|
||||
| CollateralOnramp | [`0x93070a847efEf7F70739046A929D47a521F5B8ee`](https://polygonscan.com/address/0x93070a847efEf7F70739046A929D47a521F5B8ee) |
|
||||
| CollateralOfframp | [`0x2957922Eb93258b93368531d39fAcCA3B4dC5854`](https://polygonscan.com/address/0x2957922Eb93258b93368531d39fAcCA3B4dC5854) |
|
||||
| PermissionedRamp | [`0xebC2459Ec962869ca4c0bd1E06368272732BCb08`](https://polygonscan.com/address/0xebC2459Ec962869ca4c0bd1E06368272732BCb08) |
|
||||
| CtfCollateralAdapter | [`0xADa100874d00e3331D00F2007a9c336a65009718`](https://polygonscan.com/address/0xADa100874d00e3331D00F2007a9c336a65009718) |
|
||||
| NegRiskCtfCollateralAdapter | [`0xAdA200001000ef00D07553cEE7006808F895c6F1`](https://polygonscan.com/address/0xAdA200001000ef00D07553cEE7006808F895c6F1) |
|
||||
|
||||
***
|
||||
|
||||
## Wallet Factory Contracts
|
||||
|
||||
| Contract | Address |
|
||||
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Gnosis Safe Factory | [`0xaacfeea03eb1561c4e67d661e40682bd20e3541b`](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) |
|
||||
| Polymarket Proxy Factory | [`0xaB45c5A4B0c941a2F231C04C3f49182e1A254052`](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) |
|
||||
|
||||
***
|
||||
|
||||
## Resolution Contracts
|
||||
|
||||
| Contract | Address |
|
||||
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| UMA Adapter | [`0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74`](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) |
|
||||
| UMA Optimistic Oracle | [`0xCB1822859cEF82Cd2Eb4E6276C7916e692995130`](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
### Audits
|
||||
|
||||
CTF Exchange V2 has been audited by two independent firms:
|
||||
|
||||
| Auditor | Report |
|
||||
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Quantstamp | [CTF Exchange V2 — Quantstamp — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Quantstamp%20-%20March%202026.pdf) |
|
||||
| Cantina | [CTF Exchange V2 — Cantina — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Cantina%20-%20March%202026.pdf) |
|
||||
|
||||
### Bug Bounty
|
||||
|
||||
Security vulnerabilities can be reported through the [Cantina bug bounty program](https://cantina.xyz/bounties/ff945ca2-2a6e-4b83-b1b6-7a0cd3b94bea).
|
||||
|
||||
***
|
||||
|
||||
## Source Code
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="CTF Exchange V2" icon="github" href="https://github.com/Polymarket/ctf-exchange-v2">
|
||||
Order matching and settlement contracts
|
||||
</Card>
|
||||
</CardGroup>
|
||||
null
|
||||
@@ -1,509 +1 @@
|
||||
# Deposit Wallets
|
||||
|
||||
> Create deposit wallets, execute wallet actions, and place POLY_1271 orders
|
||||
|
||||
Deposit wallets are the wallet path for **new API users**. Existing Safe and
|
||||
Proxy users are unaffected and can continue using their current wallet setup.
|
||||
|
||||
For newly-created polymarket.com accounts using the deposit wallet flow, a
|
||||
deposit wallet is automatically deployed for you.
|
||||
|
||||
<Info>
|
||||
This guide is for developers integrating directly with the APIs or SDKs. It
|
||||
does not change existing user balances, existing proxy wallets, or existing
|
||||
Safes.
|
||||
</Info>
|
||||
|
||||
## Where Deposit Wallets Fit
|
||||
|
||||
| Area | Existing Safe/Proxy users | New API user deposit wallet flow |
|
||||
| -------------------- | ----------------------------------- | ------------------------------------------------ |
|
||||
| Wallet type | Existing proxy wallet or Safe | Deposit wallet |
|
||||
| Wallet deployment | Existing relayer Safe/proxy flow | Relayer `WALLET-CREATE` |
|
||||
| Deployment signature | Existing Safe/proxy deployment flow | No user signature in the `WALLET-CREATE` payload |
|
||||
| Wallet calls | Safe/proxy relayer transactions | Relayer `WALLET` batches |
|
||||
| Order signature type | `0`, `1`, or `2` | `3`, also called `POLY_1271` |
|
||||
| Order maker | EOA, proxy, or Safe | Deposit wallet address |
|
||||
| Order signer field | EOA for existing types | Deposit wallet address |
|
||||
| Signing key | User EOA or session signer | Deposit wallet owner or approved session signer |
|
||||
|
||||
## Mental Model
|
||||
|
||||
A deposit wallet is a per-user ERC-1967 proxy deployed by a deposit wallet
|
||||
factory. The wallet holds pUSD and conditional tokens on-chain.
|
||||
|
||||
The owner or session signer signs two different kinds of payloads:
|
||||
|
||||
1. A **deposit wallet Batch** for on-chain wallet calls. This is submitted to the
|
||||
relayer as a `WALLET` transaction.
|
||||
2. A **CLOB order** with `signatureType = 3`. The CLOB validates this through
|
||||
ERC-1271 on the deposit wallet.
|
||||
|
||||
These signatures are not interchangeable. A `WALLET` batch uses a normal
|
||||
65-byte EIP-712 signature over the `DepositWallet` `Batch` type. A CLOB order
|
||||
uses an ERC-7739-wrapped `POLY_1271` signature and is longer than a normal ECDSA
|
||||
signature.
|
||||
|
||||
## Integration Flow
|
||||
|
||||
<Steps>
|
||||
<Step title="Create or identify the owner signer">
|
||||
Use the EOA or session signer that will own the deposit wallet. This signer is
|
||||
also the key that signs deposit wallet batches and CLOB order payloads unless
|
||||
your session signer flow delegates signing elsewhere.
|
||||
</Step>
|
||||
|
||||
<Step title="Deploy the deposit wallet">
|
||||
Submit a relayer `WALLET-CREATE` request. The body only needs the transaction
|
||||
type, owner address, and deposit wallet factory address.
|
||||
|
||||
The deposit wallet address is deterministic. TypeScript relayer users can call
|
||||
`deriveDepositWalletAddress()`, and Python relayer users can call
|
||||
`get_expected_deposit_wallet()`. Other integrations should store the address
|
||||
returned by onboarding or derive it with the deterministic formula below.
|
||||
</Step>
|
||||
|
||||
<Step title="Fund the deposit wallet">
|
||||
Transfer pUSD to the deposit wallet address. pUSD held by the EOA does not count
|
||||
as CLOB buying power for deposit wallet orders.
|
||||
</Step>
|
||||
|
||||
<Step title="Approve trading contracts from the wallet">
|
||||
Approvals must be made **from the deposit wallet**, not from the owner EOA. Build
|
||||
ERC-20 or ERC-1155 approval calldata and submit it through a relayer `WALLET`
|
||||
batch.
|
||||
</Step>
|
||||
|
||||
<Step title="Sync CLOB balances">
|
||||
After funding or changing allowances, call the CLOB balance allowance update
|
||||
endpoint through the SDK or API. The request must use `signature_type = 3`.
|
||||
</Step>
|
||||
|
||||
<Step title="Place orders with POLY_1271">
|
||||
Initialize the CLOB client with the deposit wallet as the funder and
|
||||
`POLY_1271` as the signature type. Orders must have both `maker` and `signer`
|
||||
set to the deposit wallet address.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## SDK Users
|
||||
|
||||
Use a relayer client or the raw relayer API for wallet deployment and wallet
|
||||
batches. Use the CLOB client for order signing, posting, cancelling, balances,
|
||||
and account data.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Use the TypeScript clients with deposit wallet support:
|
||||
[@polymarket/builder-relayer-client](https://www.npmjs.com/package/@polymarket/builder-relayer-client)
|
||||
and
|
||||
[@polymarket/clob-client-v2](https://www.npmjs.com/package/@polymarket/clob-client-v2).
|
||||
|
||||
```bash theme={null}
|
||||
npm install @polymarket/builder-relayer-client @polymarket/clob-client-v2 @polymarket/builder-signing-sdk viem
|
||||
```
|
||||
|
||||
### Deploy the Wallet
|
||||
|
||||
```typescript theme={null}
|
||||
import {
|
||||
BuilderApiKeyCreds,
|
||||
BuilderConfig,
|
||||
} from "@polymarket/builder-signing-sdk";
|
||||
import { RelayClient } from "@polymarket/builder-relayer-client";
|
||||
import { createWalletClient, Hex, http } from "viem";
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
import { polygon } from "viem/chains";
|
||||
|
||||
const relayerUrl = process.env.RELAYER_URL!;
|
||||
const chainId = Number(process.env.CHAIN_ID ?? 137);
|
||||
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
|
||||
const walletClient = createWalletClient({
|
||||
account,
|
||||
chain: polygon,
|
||||
transport: http(process.env.RPC_URL),
|
||||
});
|
||||
|
||||
const builderCreds: BuilderApiKeyCreds = {
|
||||
key: process.env.BUILDER_API_KEY!,
|
||||
secret: process.env.BUILDER_SECRET!,
|
||||
passphrase: process.env.BUILDER_PASS_PHRASE!,
|
||||
};
|
||||
|
||||
const builderConfig = new BuilderConfig({
|
||||
localBuilderCreds: builderCreds,
|
||||
});
|
||||
|
||||
const relayer = new RelayClient(
|
||||
relayerUrl,
|
||||
chainId,
|
||||
walletClient,
|
||||
builderConfig,
|
||||
);
|
||||
|
||||
const depositWalletAddress = await relayer.deriveDepositWalletAddress();
|
||||
const response = await relayer.deployDepositWallet();
|
||||
const confirmed = await response.wait();
|
||||
```
|
||||
|
||||
`deployDepositWallet()` submits a `WALLET-CREATE` transaction. It does not add a
|
||||
user signature to the deployment body.
|
||||
|
||||
### Execute a Wallet Batch
|
||||
|
||||
```typescript theme={null}
|
||||
import type { DepositWalletCall } from "@polymarket/builder-relayer-client";
|
||||
|
||||
const calls: DepositWalletCall[] = [
|
||||
{
|
||||
target: process.env.PUSD_ADDRESS!,
|
||||
value: "0",
|
||||
data: approveCalldata,
|
||||
},
|
||||
];
|
||||
|
||||
const deadline = Math.floor(Date.now() / 1000 + 600).toString();
|
||||
const response = await relayer.executeDepositWalletBatch(
|
||||
calls,
|
||||
depositWalletAddress,
|
||||
deadline,
|
||||
);
|
||||
const confirmed = await response.wait();
|
||||
```
|
||||
|
||||
The TypeScript relayer client fetches the current `WALLET` nonce before signing
|
||||
and submitting the batch. The SDK signs the batch with this EIP-712 domain before
|
||||
submitting it to the relayer:
|
||||
|
||||
```typescript theme={null}
|
||||
{
|
||||
name: "DepositWallet",
|
||||
version: "1",
|
||||
chainId,
|
||||
verifyingContract: depositWalletAddress,
|
||||
}
|
||||
```
|
||||
|
||||
### Trade From the Deposit Wallet
|
||||
|
||||
```typescript theme={null}
|
||||
import {
|
||||
AssetType,
|
||||
ClobClient,
|
||||
OrderType,
|
||||
Side,
|
||||
SignatureTypeV2,
|
||||
} from "@polymarket/clob-client-v2";
|
||||
|
||||
const creds = {
|
||||
key: process.env.CLOB_API_KEY!,
|
||||
secret: process.env.CLOB_SECRET!,
|
||||
passphrase: process.env.CLOB_PASS_PHRASE!,
|
||||
};
|
||||
|
||||
const clob = new ClobClient({
|
||||
host: process.env.CLOB_API_URL!,
|
||||
chain: chainId,
|
||||
signer: walletClient,
|
||||
creds,
|
||||
signatureType: SignatureTypeV2.POLY_1271,
|
||||
funderAddress: depositWalletAddress,
|
||||
});
|
||||
|
||||
await clob.updateBalanceAllowance({ asset_type: AssetType.COLLATERAL });
|
||||
|
||||
const order = await clob.createAndPostOrder(
|
||||
{
|
||||
tokenID: process.env.TOKEN_ID!,
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.GTC,
|
||||
);
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Use the Python builder relayer client with deposit wallet support:
|
||||
[py-builder-relayer-client](https://pypi.org/project/py-builder-relayer-client/).
|
||||
|
||||
```bash theme={null}
|
||||
pip install py-builder-relayer-client
|
||||
```
|
||||
|
||||
### Deploy the Wallet
|
||||
|
||||
```python theme={null}
|
||||
import os
|
||||
|
||||
from py_builder_relayer_client.client import RelayClient
|
||||
from py_builder_signing_sdk.config import BuilderApiKeyCreds, BuilderConfig
|
||||
|
||||
builder_config = BuilderConfig(
|
||||
local_builder_creds=BuilderApiKeyCreds(
|
||||
key=os.environ["BUILDER_API_KEY"],
|
||||
secret=os.environ["BUILDER_SECRET"],
|
||||
passphrase=os.environ["BUILDER_PASS_PHRASE"],
|
||||
)
|
||||
)
|
||||
|
||||
relayer = RelayClient(
|
||||
os.environ["RELAYER_URL"],
|
||||
int(os.environ.get("CHAIN_ID", "137")),
|
||||
os.environ["PRIVATE_KEY"],
|
||||
builder_config,
|
||||
)
|
||||
|
||||
deposit_wallet = relayer.get_expected_deposit_wallet()
|
||||
response = relayer.deploy_deposit_wallet()
|
||||
confirmed = response.wait()
|
||||
```
|
||||
|
||||
`get_expected_deposit_wallet()` derives the deterministic wallet address from
|
||||
the signer and the chain's deposit wallet configuration.
|
||||
|
||||
### Execute a Wallet Batch
|
||||
|
||||
```python theme={null}
|
||||
import time
|
||||
|
||||
from py_builder_relayer_client.models import DepositWalletCall, TransactionType
|
||||
|
||||
nonce_payload = relayer.get_nonce(
|
||||
relayer.signer.address(),
|
||||
TransactionType.WALLET.value,
|
||||
)
|
||||
wallet_nonce = str(nonce_payload["nonce"])
|
||||
|
||||
call = DepositWalletCall(
|
||||
target=os.environ["PUSD_ADDRESS"],
|
||||
value="0",
|
||||
data=approve_calldata,
|
||||
)
|
||||
|
||||
response = relayer.execute_deposit_wallet_batch(
|
||||
calls=[call],
|
||||
wallet_address=deposit_wallet,
|
||||
nonce=wallet_nonce,
|
||||
deadline=str(int(time.time()) + 600),
|
||||
)
|
||||
confirmed = response.wait()
|
||||
```
|
||||
|
||||
The Python relayer client mirrors the TypeScript wire format for `WALLET-CREATE`
|
||||
and `WALLET` requests, while keeping builder API key auth in the Python client.
|
||||
|
||||
### Trade From the Deposit Wallet
|
||||
|
||||
Use the Python CLOB client with deposit wallet order support:
|
||||
[py-clob-client-v2](https://pypi.org/project/py-clob-client-v2/).
|
||||
|
||||
```bash theme={null}
|
||||
pip install py-clob-client-v2
|
||||
```
|
||||
|
||||
```python theme={null}
|
||||
import os
|
||||
|
||||
from py_clob_client_v2 import (
|
||||
ApiCreds,
|
||||
AssetType,
|
||||
BalanceAllowanceParams,
|
||||
ClobClient,
|
||||
OrderArgs,
|
||||
OrderType,
|
||||
PartialCreateOrderOptions,
|
||||
Side,
|
||||
SignatureTypeV2,
|
||||
)
|
||||
|
||||
creds = ApiCreds(
|
||||
api_key=os.environ["CLOB_API_KEY"],
|
||||
api_secret=os.environ["CLOB_SECRET"],
|
||||
api_passphrase=os.environ["CLOB_PASS_PHRASE"],
|
||||
)
|
||||
|
||||
clob = ClobClient(
|
||||
host=os.environ["CLOB_API_URL"],
|
||||
chain_id=int(os.environ.get("CHAIN_ID", "137")),
|
||||
key=os.environ["PRIVATE_KEY"],
|
||||
creds=creds,
|
||||
signature_type=SignatureTypeV2.POLY_1271,
|
||||
funder=deposit_wallet,
|
||||
)
|
||||
|
||||
clob.update_balance_allowance(
|
||||
BalanceAllowanceParams(
|
||||
asset_type=AssetType.COLLATERAL,
|
||||
signature_type=SignatureTypeV2.POLY_1271,
|
||||
)
|
||||
)
|
||||
|
||||
response = clob.create_and_post_order(
|
||||
order_args=OrderArgs(
|
||||
token_id=os.environ["TOKEN_ID"],
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=Side.BUY,
|
||||
),
|
||||
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
|
||||
order_type=OrderType.GTC,
|
||||
)
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Rust">
|
||||
### Deploy the Wallet and Execute Wallet Batches
|
||||
|
||||
The Rust SDK supports the CLOB order path for deposit wallets. It does not
|
||||
include a builder relayer client. Use the TypeScript or Python relayer client
|
||||
above, or the raw API flow below, to submit `WALLET-CREATE` and `WALLET`
|
||||
transactions.
|
||||
|
||||
Use the Rust CLOB client with deposit wallet support:
|
||||
[polymarket_client_sdk_v2](https://crates.io/crates/polymarket_client_sdk_v2).
|
||||
|
||||
```bash theme={null}
|
||||
cargo add polymarket_client_sdk_v2 --features clob
|
||||
```
|
||||
|
||||
Once the deposit wallet is deployed, funded, and approved, pass the deposit
|
||||
wallet address as the Rust CLOB client funder.
|
||||
|
||||
### Trade From the Deposit Wallet
|
||||
|
||||
```rust theme={null}
|
||||
use std::str::FromStr as _;
|
||||
|
||||
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer as _};
|
||||
use polymarket_client_sdk_v2::clob::types::request::UpdateBalanceAllowanceRequest;
|
||||
use polymarket_client_sdk_v2::clob::types::{AssetType, OrderType, Side, SignatureType};
|
||||
use polymarket_client_sdk_v2::clob::{Client, Config};
|
||||
use polymarket_client_sdk_v2::types::{Address, Decimal, U256};
|
||||
use polymarket_client_sdk_v2::{POLYGON, PRIVATE_KEY_VAR};
|
||||
|
||||
let host = std::env::var("CLOB_API_URL")?;
|
||||
let token_id = U256::from_str(&std::env::var("TOKEN_ID")?)?;
|
||||
let deposit_wallet = Address::from_str(&std::env::var("DEPOSIT_WALLET")?)?;
|
||||
let signer =
|
||||
LocalSigner::from_str(&std::env::var(PRIVATE_KEY_VAR)?)?.with_chain_id(Some(POLYGON));
|
||||
|
||||
let client = Client::new(&host, Config::default())?
|
||||
.authentication_builder(&signer)
|
||||
.funder(deposit_wallet)
|
||||
.signature_type(SignatureType::Poly1271)
|
||||
.authenticate()
|
||||
.await?;
|
||||
|
||||
client
|
||||
.update_balance_allowance(
|
||||
UpdateBalanceAllowanceRequest::builder()
|
||||
.asset_type(AssetType::Collateral)
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let _response = client
|
||||
.limit_order()
|
||||
.token_id(token_id)
|
||||
.side(Side::Buy)
|
||||
.price(Decimal::from_str("0.50")?)
|
||||
.size(Decimal::from_str("10")?)
|
||||
.order_type(OrderType::GTC)
|
||||
.build_sign_and_post(&signer)
|
||||
.await?;
|
||||
```
|
||||
|
||||
The Rust client sets `signatureType = 3` and builds the wrapped ERC-1271 order
|
||||
signature when `SignatureType::Poly1271` and a deposit wallet funder are
|
||||
configured.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Raw API Integration
|
||||
|
||||
### Deposit Wallet Factory
|
||||
|
||||
The factory is configured per chain. Use the relayer's `GET /config` endpoint to
|
||||
retrieve the current factory address.
|
||||
|
||||
```json
|
||||
{
|
||||
"deposit_wallet_factory": "0x..."
|
||||
}
|
||||
```
|
||||
|
||||
### Deriving the Deposit Wallet Address
|
||||
|
||||
The wallet address is deterministic. Use the salt `0x0000000000000000000000000000000000000000000000000000000000000000`.
|
||||
|
||||
```
|
||||
depositWallet = factory.computeAddress(salt, initCode)
|
||||
```
|
||||
|
||||
Where `initCode` is the ERC-1967 proxy initialization code. Use the relayer client's
|
||||
`deriveDepositWalletAddress()` method or `get_expected_deposit_wallet()` helper.
|
||||
|
||||
### WALLET-CREATE
|
||||
|
||||
```json
|
||||
{
|
||||
"transactionType": "WALLET-CREATE",
|
||||
"owner": "0x...",
|
||||
"factory": "0x..."
|
||||
}
|
||||
```
|
||||
|
||||
No user signature is required. The relayer signs and submits the transaction.
|
||||
|
||||
### WALLET
|
||||
|
||||
```json
|
||||
{
|
||||
"transactionType": "WALLET",
|
||||
"calls": [
|
||||
{
|
||||
"target": "0x...",
|
||||
"value": "0",
|
||||
"data": "0x..."
|
||||
}
|
||||
],
|
||||
"nonce": "123",
|
||||
"deadline": "1714000000"
|
||||
}
|
||||
```
|
||||
|
||||
The batch is signed with a standard EIP-712 `DepositWallet.Batch` domain:
|
||||
|
||||
```typescript theme={null}
|
||||
{
|
||||
name: "DepositWallet",
|
||||
version: "1",
|
||||
chainId,
|
||||
verifyingContract: depositWalletAddress,
|
||||
}
|
||||
```
|
||||
|
||||
The relayer signs and submits on your behalf.
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Builder Program" icon="hammer" href="/builders/overview">
|
||||
Overview of the Builder Program and benefits
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Fees" icon="dollar" href="/builders/fees">
|
||||
How builder fees work and how to set rates
|
||||
</Card>
|
||||
|
||||
<Card title="pUSD" icon="coin" href="/concepts/pusd">
|
||||
The collateral token powering Polymarket trading
|
||||
</Card>
|
||||
|
||||
<Card title="Migration Guide" icon="arrow-right" href="/v2-migration">
|
||||
Full V2 migration guide
|
||||
</Card>
|
||||
</CardGroup>
|
||||
null
|
||||
+1
-634
@@ -1,634 +1 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Migrating to CLOB V2
|
||||
|
||||
> A complete guide to upgrading your integration to Polymarket's CLOB V2 — new contracts, new backend, new collateral token, and a simpler builder program.
|
||||
|
||||
Polymarket has shipped a coordinated upgrade of its entire trading infrastructure: **new Exchange contracts**, a **rewritten CLOB backend**, and a **new collateral token** (Polymarket USD, or pUSD). This guide walks you through everything you need to migrate from CLOB V1 to CLOB V2.
|
||||
|
||||
<Warning>
|
||||
**CLOB V2 is live as of April 28, 2026.** Legacy V1 SDKs and V1-signed orders are no longer supported on production. Upgrade to the V2 SDK or update your raw order signing before submitting orders to `https://clob.polymarket.com`.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
**Production URL:** CLOB V2 now runs at `https://clob.polymarket.com`. The pre-cutover `https://clob-v2.polymarket.com` testing host is no longer the integration target for production clients.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## TL;DR
|
||||
|
||||
| What | Before (V1) | After (V2) |
|
||||
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
||||
| SDK package | `@polymarket/clob-client` / `py-clob-client` | `@polymarket/clob-client-v2` / `py-clob-client-v2` |
|
||||
| Constructor | Positional args | Options object, `chainId` → `chain` |
|
||||
| Order fields | `nonce`, `feeRateBps`, `taker` | `timestamp` (ms), `metadata`, `builder` |
|
||||
| Fees | Embedded in the signed order | Operator-set at match time |
|
||||
| Collateral | USDC.e | **pUSD** (standard ERC-20, backed by USDC) |
|
||||
| Builder auth | `POLY_BUILDER_*` HMAC headers + [`builder-signing-sdk`](https://github.com/Polymarket/builder-signing-sdk) | A single `builderCode` field on the order |
|
||||
| EIP-712 domain version | `"1"` | `"2"` (exchange only — API auth unchanged) |
|
||||
| Exchange `verifyingContract` (raw API signers) | V1 addresses | V2 addresses — see [Contracts](/resources/contracts) |
|
||||
| Raw API order signing | V1 Order type | Updated Order type — [see API users section](#for-api-users) |
|
||||
|
||||
**If you're on the latest SDK,** most of this is handled automatically. If you're signing orders manually, update the EIP-712 domain, order fields, and contract addresses described below.
|
||||
|
||||
***
|
||||
|
||||
## Before you start
|
||||
|
||||
<Steps>
|
||||
<Step title="Read this guide end-to-end">
|
||||
Even if a section doesn't look relevant, skim it. V2 touches more surface area than any previous release.
|
||||
</Step>
|
||||
|
||||
<Step title="Pin the latest SDK">
|
||||
Install the V2 SDK: [`@polymarket/clob-client-v2`](https://www.npmjs.com/package/@polymarket/clob-client-v2) (TypeScript) or [`py-clob-client-v2`](https://pypi.org/project/py-clob-client-v2/) (Python). Don't keep using the old `clob-client` / `py-clob-client` packages — those only work against V1 and no longer function against production.
|
||||
</Step>
|
||||
|
||||
<Step title="Test with a funded wallet">
|
||||
Use a small funded wallet to test market discovery, order signing, posting, cancellation, and settlement behavior end-to-end on production.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Warning>
|
||||
**Open orders from before the CLOB V2 cutover were wiped.** If you had resting V1-era orders, they did not migrate and must be re-created with V2 order signing.
|
||||
</Warning>
|
||||
|
||||
***
|
||||
|
||||
## What's changing
|
||||
|
||||
### 1. New Exchange contracts
|
||||
|
||||
The onchain exchange has been rewritten from the ground up.
|
||||
|
||||
* Solidity upgraded from **0.8.15 → 0.8.30**, with Solady replacing OpenZeppelin for gas savings.
|
||||
* Order struct simplified: `nonce`, `feeRateBps`, and `taker` removed; `timestamp`, `metadata`, `builder` added.
|
||||
* EIP-712 exchange domain version bumped from `"1"` to `"2"`.
|
||||
* Fees collected onchain at match time (no longer embedded in the signed order).
|
||||
* Onchain cancel replaced with operator-controlled `pauseUser` / `unpauseUser`.
|
||||
* Batched mint/merge operations for gas efficiency.
|
||||
|
||||
See [Contracts](/resources/contracts) for V2 addresses.
|
||||
|
||||
### 2. Rewritten CLOB backend
|
||||
|
||||
The order manager, ledger, executor, balance checker, and tracker are all new services. From an integrator's perspective:
|
||||
|
||||
* **Nonce system removed.** Order uniqueness now comes from `timestamp` (milliseconds). You no longer track nonces.
|
||||
* **New fee model.** Platform fees are dynamic per market and queryable via `getClobMarketInfo()`.
|
||||
* **Builder codes** enable integrator attribution and revenue sharing, replacing the old HMAC-header flow.
|
||||
|
||||
### 3. New collateral token
|
||||
|
||||
Polymarket is migrating from **USDC.e** to **pUSD** (Polymarket USD), a standard ERC-20 on Polygon backed by USDC. Backing is enforced onchain by the smart contract.
|
||||
|
||||
* For users trading on polymarket.com, the frontend handles wrapping automatically with a one-time approval.
|
||||
* Power users and API-only traders wrap their USDC.e into pUSD via the Collateral Onramp contract's `wrap()` function.
|
||||
|
||||
***
|
||||
|
||||
## For API users
|
||||
|
||||
If you sign and post orders directly (without the SDK), here's what changes in the wire protocol. SDK users can skip this section — the client handles it.
|
||||
|
||||
### EIP-712 domain
|
||||
|
||||
The Exchange domain version bumps to `"2"` and the `verifyingContract` moves to the V2 Exchange.
|
||||
|
||||
```ts theme={null}
|
||||
{
|
||||
name: "Polymarket CTF Exchange",
|
||||
version: "1", // [!code --]
|
||||
version: "2", // [!code ++]
|
||||
chainId: 137,
|
||||
verifyingContract: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", // [!code --]
|
||||
verifyingContract: "0xE111180000d2663C0091e4f400237545B87B996B", // [!code ++]
|
||||
}
|
||||
```
|
||||
|
||||
For Neg Risk markets, the `verifyingContract` is different:
|
||||
|
||||
```ts theme={null}
|
||||
{
|
||||
verifyingContract: "0xC5d563A36AE78145C45a50134d48A1215220f80a", // [!code --]
|
||||
verifyingContract: "0xe2222d279d744050d28e00520010520000310F59", // [!code ++]
|
||||
}
|
||||
```
|
||||
|
||||
See [Contracts](/resources/contracts) for the canonical V2 addresses.
|
||||
|
||||
<Note>
|
||||
**Only the Exchange domain changes.** The `ClobAuthDomain` used for L1 API authentication stays at version `"1"` — L1/L2 auth is identical in V2.
|
||||
</Note>
|
||||
|
||||
### EIP-712 Order type
|
||||
|
||||
The signed struct drops `taker`, `expiration`, `nonce`, and `feeRateBps`, and adds `timestamp`, `metadata`, and `builder`.
|
||||
|
||||
```ts theme={null}
|
||||
Order(
|
||||
uint256 salt,
|
||||
address maker,
|
||||
address signer,
|
||||
address taker, // [!code --]
|
||||
uint256 tokenId,
|
||||
uint256 makerAmount,
|
||||
uint256 takerAmount,
|
||||
uint256 expiration, // [!code --]
|
||||
uint256 nonce, // [!code --]
|
||||
uint256 feeRateBps, // [!code --]
|
||||
uint8 side,
|
||||
uint8 signatureType // [!code --]
|
||||
uint8 signatureType, // [!code ++]
|
||||
uint256 timestamp, // [!code ++]
|
||||
bytes32 metadata, // [!code ++]
|
||||
bytes32 builder // [!code ++]
|
||||
)
|
||||
```
|
||||
|
||||
### Order value to sign
|
||||
|
||||
```ts theme={null}
|
||||
{
|
||||
salt: "12345",
|
||||
maker: "0x...",
|
||||
signer: "0x...",
|
||||
taker: "0x0000000000000000000000000000000000000000", // [!code --]
|
||||
tokenId: "102936...",
|
||||
makerAmount: "1000000",
|
||||
takerAmount: "2000000",
|
||||
expiration: "0", // [!code --]
|
||||
nonce: "0", // [!code --]
|
||||
feeRateBps: "0", // [!code --]
|
||||
side: 0,
|
||||
signatureType: 1 // [!code --]
|
||||
signatureType: 1, // [!code ++]
|
||||
timestamp: "1713398400000", // [!code ++]
|
||||
metadata: "0x0000000000000000000000000000000000000000000000000000000000000000", // [!code ++]
|
||||
builder: "0x0000000000000000000000000000000000000000000000000000000000000000" // [!code ++]
|
||||
}
|
||||
```
|
||||
|
||||
* **`timestamp`** — order creation time in milliseconds. Replaces `nonce` for per-address uniqueness (not an expiration).
|
||||
* **`metadata`** — bytes32.
|
||||
* **`builder`** — bytes32. Zero unless you're attaching a builder code.
|
||||
|
||||
`side` is encoded as `uint8` in the signing payload (`0` = BUY, `1` = SELL), even though the wire body uses the string `"BUY"` / `"SELL"`. No change from V1.
|
||||
|
||||
### POST /order body
|
||||
|
||||
`expiration` is still present in the `POST /order` wire body for GTD/order-expiry handling, but it is **not** part of the V2 EIP-712 signed struct.
|
||||
|
||||
```ts theme={null}
|
||||
{
|
||||
"order": {
|
||||
"salt": "12345",
|
||||
"maker": "0x...",
|
||||
"signer": "0x...",
|
||||
"taker": "0x0000000000000000000000000000000000000000", // [!code --]
|
||||
"tokenId": "102936...",
|
||||
"makerAmount": "1000000",
|
||||
"takerAmount": "2000000",
|
||||
"expiration": "0",
|
||||
"nonce": "0", // [!code --]
|
||||
"feeRateBps": "0", // [!code --]
|
||||
"side": "BUY",
|
||||
"signatureType": 1,
|
||||
"timestamp": "1713398400000", // [!code ++]
|
||||
"metadata": "0x0000000000000000000000000000000000000000000000000000000000000000", // [!code ++]
|
||||
"builder": "0x0000000000000000000000000000000000000000000000000000000000000000", // [!code ++]
|
||||
"signature": "0x..."
|
||||
},
|
||||
"owner": "<api-key>",
|
||||
"orderType": "GTC"
|
||||
}
|
||||
```
|
||||
|
||||
### Request headers
|
||||
|
||||
The API auth headers are unchanged. Builder attribution moves into the signed `builder` field on the order, so the `POLY_BUILDER_*` HMAC headers are gone.
|
||||
|
||||
```yaml theme={null}
|
||||
POLY_ADDRESS: 0x...
|
||||
POLY_SIGNATURE: 0x...
|
||||
POLY_TIMESTAMP: 1713398400
|
||||
POLY_API_KEY: ...
|
||||
POLY_PASSPHRASE: ...
|
||||
POLY_BUILDER_API_KEY: ... # [!code --]
|
||||
POLY_BUILDER_SECRET: ... # [!code --]
|
||||
POLY_BUILDER_PASSPHRASE: ... # [!code --]
|
||||
POLY_BUILDER_SIGNATURE: 0x... # [!code --]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## SDK Migration
|
||||
|
||||
### Install
|
||||
|
||||
CLOB V2 ships under new package names. Install them directly — don't keep using the old `clob-client` / `py-clob-client` packages.
|
||||
|
||||
<CodeGroup>
|
||||
```bash TypeScript theme={null}
|
||||
npm install @polymarket/clob-client-v2 viem
|
||||
```
|
||||
|
||||
```bash Python theme={null}
|
||||
pip install py-clob-client-v2
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Warning>
|
||||
The legacy `@polymarket/clob-client` and `py-clob-client` packages only work against V1 and no longer work against production CLOB V2.
|
||||
</Warning>
|
||||
|
||||
<Note>
|
||||
**What's next.** We're planning a unified SDK that folds Gamma, Data, and CLOB into a single package. Future releases will converge there — for now, `clob-client-v2` / `py-clob-client-v2` are the V2 CLOB clients.
|
||||
</Note>
|
||||
|
||||
### Constructor: positional args → options object
|
||||
|
||||
The single most visible change. `chainId` is renamed to `chain`. `tickSizeTtlMs` is no longer configurable.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Before (V1) theme={null}
|
||||
const client = new ClobClient(
|
||||
host,
|
||||
chainId,
|
||||
signer,
|
||||
creds,
|
||||
signatureType,
|
||||
funderAddress,
|
||||
useServerTime,
|
||||
builderConfig,
|
||||
getSigner,
|
||||
retryOnError,
|
||||
tickSizeTtlMs, // ← removed in V2
|
||||
throwOnError,
|
||||
);
|
||||
```
|
||||
|
||||
```typescript After (V2) theme={null}
|
||||
const client = new ClobClient({
|
||||
host,
|
||||
chain: chainId, // ← renamed from chainId
|
||||
signer,
|
||||
creds,
|
||||
signatureType,
|
||||
funderAddress,
|
||||
useServerTime,
|
||||
builderConfig, // shape changed — see Builder Program below
|
||||
getSigner,
|
||||
retryOnError,
|
||||
throwOnError,
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
The only mental shift: wrap args in `{}` and rename `chainId` → `chain`. Everything else is the same.
|
||||
</Tip>
|
||||
|
||||
### Order creation
|
||||
|
||||
Three fields are no longer user-settable: `feeRateBps`, `nonce`, `taker`. One new optional field: `builderCode`.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Before (V1) theme={null}
|
||||
const order: UserOrder = {
|
||||
tokenID: "0x123...",
|
||||
price: 0.55,
|
||||
size: 100,
|
||||
side: Side.BUY,
|
||||
feeRateBps: 100, // ← removed
|
||||
nonce: 12345, // ← removed
|
||||
taker: "0xabc...", // ← removed
|
||||
expiration: 1714000000,
|
||||
};
|
||||
```
|
||||
|
||||
```typescript After (V2) theme={null}
|
||||
const order: UserOrderV2 = {
|
||||
tokenID: "0x123...",
|
||||
price: 0.55,
|
||||
size: 100,
|
||||
side: Side.BUY,
|
||||
expiration: 1714000000,
|
||||
builderCode: "0x...", // optional — your builder code
|
||||
};
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
**Market orders** follow the same pattern and add an optional `userUSDCBalance` field so the SDK can calculate fee-adjusted fill amounts:
|
||||
|
||||
```typescript theme={null}
|
||||
const marketOrder: UserMarketOrderV2 = {
|
||||
tokenID: "0x123...",
|
||||
amount: 500,
|
||||
side: Side.BUY,
|
||||
orderType: OrderType.FOK,
|
||||
userUSDCBalance: 1000, // optional — enables fee-aware calculations
|
||||
builderCode: "0x...", // optional
|
||||
};
|
||||
```
|
||||
|
||||
## Fee model
|
||||
|
||||
Fees are now **determined by the protocol at match time**, not embedded in your signed order.
|
||||
|
||||
* **Platform fees** are dynamic per market: `fee = C × feeRate × p × (1 - p)`
|
||||
* **Makers are never charged fees** — only takers pay.
|
||||
* You no longer set `feeRateBps` on orders. The SDK handles fee calculation automatically.
|
||||
|
||||
### Querying fee parameters
|
||||
|
||||
V2 introduces `getClobMarketInfo()`, which returns all CLOB-level market parameters in one call:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const info = await client.getClobMarketInfo(conditionID);
|
||||
// info.mts — minimum tick size
|
||||
// info.mos — minimum order size
|
||||
// info.fd — fee details { r: rate, e: exponent, to: takerOnly }
|
||||
// info.t — tokens [{ t: tokenID, o: outcome }, ...]
|
||||
// info.rfqe — is RFQ enabled
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
info = client.get_clob_market_info(condition_id)
|
||||
# info["mts"] — minimum tick size
|
||||
# info["mos"] — minimum order size
|
||||
# info["fd"] — fee details { "r", "e", "to" }
|
||||
# info["t"] — tokens list
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
If you were calculating fees manually in your integration, you can now rely on the SDK. Pass `userUSDCBalance` on market buy orders to get accurate fill amounts after fees.
|
||||
|
||||
***
|
||||
|
||||
## Builder Program
|
||||
|
||||
V2 replaces the old builder authentication flow (HMAC headers + separate signing SDK) with a native **builder code** attached directly to each order.
|
||||
|
||||
### What's gone
|
||||
|
||||
* `@polymarket/builder-signing-sdk` — **no longer needed**
|
||||
* `POLY_BUILDER_API_KEY`, `POLY_BUILDER_SECRET`, `POLY_BUILDER_PASSPHRASE`, `POLY_BUILDER_SIGNATURE` headers
|
||||
* Remote vs. local signing distinction
|
||||
|
||||
### What's new
|
||||
|
||||
* A single `builderCode` (bytes32) from your [Builder Profile](https://polymarket.com/settings?tab=builder)
|
||||
* Attach it per-order via the `builderCode` field, **or** pass it once at construction so every order inherits it
|
||||
|
||||
<Note>
|
||||
`BuilderConfig` still exists, but its shape changed. In V1 it wrapped HMAC credentials from `@polymarket/builder-signing-sdk`. In V2 it's just `{ builderCode: string }`.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
**Your builder API key isn't retired.** The HMAC-based builder API key is still used to authenticate with the [Relayer](/trading/gasless) for gasless transactions. Only the order-signing flow moves to the `builderCode` field — your relayer integration keeps the same credentials.
|
||||
</Note>
|
||||
|
||||
<CodeGroup>
|
||||
```typescript Before (V1) theme={null}
|
||||
import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk";
|
||||
|
||||
const builderConfig = new BuilderConfig({
|
||||
localBuilderCreds: new BuilderApiKeyCreds({
|
||||
key: process.env.POLY_BUILDER_API_KEY,
|
||||
secret: process.env.POLY_BUILDER_SECRET,
|
||||
passphrase: process.env.POLY_BUILDER_PASSPHRASE,
|
||||
}),
|
||||
});
|
||||
|
||||
const client = new ClobClient(
|
||||
host,
|
||||
chainId,
|
||||
signer,
|
||||
creds,
|
||||
signatureType,
|
||||
funderAddress,
|
||||
undefined,
|
||||
false,
|
||||
builderConfig,
|
||||
);
|
||||
```
|
||||
|
||||
```typescript After (V2) — per-order builder code theme={null}
|
||||
const client = new ClobClient({
|
||||
host,
|
||||
chain: chainId,
|
||||
signer,
|
||||
creds,
|
||||
signatureType,
|
||||
funderAddress,
|
||||
});
|
||||
|
||||
await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "0x...",
|
||||
price: 0.55,
|
||||
size: 100,
|
||||
side: Side.BUY,
|
||||
builderCode: process.env.POLY_BUILDER_CODE,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
```
|
||||
|
||||
```typescript After (V2) — pass once at construction theme={null}
|
||||
const client = new ClobClient({
|
||||
host,
|
||||
chain: chainId,
|
||||
signer,
|
||||
creds,
|
||||
signatureType,
|
||||
funderAddress,
|
||||
builderConfig: { builderCode: process.env.POLY_BUILDER_CODE },
|
||||
});
|
||||
|
||||
// Every order posted by this client now carries your builder code.
|
||||
await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "0x...",
|
||||
price: 0.55,
|
||||
size: 100,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Collateral token: USDC.e → pUSD
|
||||
|
||||
Polymarket USD (pUSD) replaces USDC.e as the collateral token. pUSD is a standard ERC-20 on Polygon backed by USDC, with backing enforced onchain by the smart contract. The permissionless Collateral Onramp accepts USDC.e.
|
||||
|
||||
* **For users on polymarket.com:** the UI handles wrapping automatically.
|
||||
* **For API-only traders:** wrap USDC.e into pUSD via the Collateral Onramp's `wrap()` function. See the [pUSD page](/concepts/pusd) for full examples and [Contracts](/resources/contracts) for addresses.
|
||||
|
||||
***
|
||||
|
||||
## Test markets
|
||||
|
||||
The markets below were used for pre-cutover testing on `clob-v2.polymarket.com` and are retained for migration reference. For live testing, resolve current active markets into token IDs and metadata with [`gamma-api.polymarket.com/markets?condition_ids=<id>`](https://gamma-api.polymarket.com/markets), then submit small orders to production CLOB V2 at `https://clob.polymarket.com`.
|
||||
|
||||
### Markets with fees enabled
|
||||
|
||||
Use these to verify fee handling end-to-end.
|
||||
|
||||
* `0xaf5e903876ad42de97e1cf02c2ef8484df69bcfc5541b96a400116557d1e504e`
|
||||
* `0xe9955a31d76ea97457410f61c9b9f2d27ac6fbd8302ed1849d93133884f4fb3b`
|
||||
* `0x8e6a263fc5f4dd9433b4ccbc9bb9e0d89f4de8a91d3a82d6b437fe73fd847ea5`
|
||||
* `0xc7d462e462d8d369aee17c9e3ea8f113166cf9a342a6434a0b2a0f7588dc1bbf`
|
||||
* `0x0440d08e4f534afa8ad9f616a239a19ebf7f2476bd802b1d54180435fa83463f`
|
||||
* `0xd048b3e9ccad82c57a4eec953e75794aeb5e6d0e08bdb79b9e01b24e0049f16d`
|
||||
* `0x88310713845c54e36f29791a1c2dc172b9819b645ba82d5f87560805cd2bb788`
|
||||
* `0xffcab88076a28795281bb07a082c7003a4ff5671420086cb16ec09dfbf9aea68`
|
||||
* `0x64a5bcfb0c76a75081c8be49c895a976d506fce8d21aa9d73f1099e502f2fa4e`
|
||||
* `0x8babe4f4d0eff732d660fa02929a581cb8478ed2a1696c158290b2794d3d7ac0`
|
||||
|
||||
### Additional markets with liquidity
|
||||
|
||||
* `0xcf8a237df51a51511c4f96bb4390480ad72b898ca8ec7e9a3c16c47c8e5e468a`
|
||||
* `0x242d251e7e804f79e1f237896b0f5e73caea72375dcb84e5a60d1cd0d2f80ef5`
|
||||
* `0x9c47ba9e666983bd8d82bfab790509153bf7756c43913f6ef269e33c8955939c`
|
||||
* `0x221aaa62fed17db56fbc7983f88110a9c34861c3262154ee3315425378e3ae12`
|
||||
* `0x625d0091f4c647e5497bd9b03f8526bd486d6c339380b8046e4dd5b3373046b7`
|
||||
* `0xc9b9f89ac915385c8d77edb73872c49e5bf76e510b74b9609e74e7f8d0339df2`
|
||||
* `0xde9f827cb2d568db7801439693645a941a38fe6feaeb08b86087ad367d991704`
|
||||
* `0xfd029ab3d6d27b6e1f3480dce858c97fb12e5bebd6fb50be7520102c56ba8ce1`
|
||||
* `0x894a61a2baa777adf1d03a263a4b2d8faa7e1ebc7bf6694a37701fae8add01d9`
|
||||
* `0xcd57f3ad3bbbdaa96aacabd35f50c2d6e30f777e4a33876a4ab2dcd9f0b8c170`
|
||||
* `0xc4b07998e8f9bf6b95f079d6dc0529f3c6f59698d4e168817ad5f99304de6c57`
|
||||
* `0xe4f4b614a6c2b4ecd8eb700d19c0e6533d3fbd1bc28193b2255394ef74006e6f`
|
||||
* `0xec181db4470b152493b58229862af3f6335b77cc719f5a0e7ed58c9f9848b992`
|
||||
* `0x6ec4fec4885df7f3ac46e5d0051beb6d8ac75de6a8481f13f245ff26dcb4b662`
|
||||
* `0x8f6e71601903224dc29c69b886a63f248c8051be259e7db299850708f1f86dd6`
|
||||
* `0xfa40b5612a905f16ee42a18979f23fa1bbfcfc365f11d168f2e22bd0159ada77`
|
||||
* `0x182390641d3b1b47cc64274b9da290efd04221c586651ba190880713da6347d9`
|
||||
|
||||
***
|
||||
|
||||
## Migration checklist
|
||||
|
||||
Work through this list as you update your integration:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="SDK and constructor">
|
||||
* [ ] Install `@polymarket/clob-client-v2` / `py-clob-client-v2` (remove the legacy `clob-client` / `py-clob-client` packages)
|
||||
* [ ] Convert constructor calls from positional args to options object
|
||||
* [ ] Rename `chainId` parameter to `chain`
|
||||
* [ ] Remove `tickSizeTtlMs` and `geoBlockToken` from constructor config
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Order creation">
|
||||
* [ ] Remove `feeRateBps`, `nonce`, `taker` from order creation calls
|
||||
* [ ] Add `builderCode` to orders if you're a builder
|
||||
* [ ] Pass `userUSDCBalance` on market buy orders for fee-adjusted fill amounts (optional)
|
||||
* [ ] Remove any manual fee calculation logic — fees are protocol-handled
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Builder program">
|
||||
* [ ] Remove `@polymarket/builder-signing-sdk` from dependencies
|
||||
* [ ] Remove `POLY_BUILDER_*` environment variables
|
||||
* [ ] Copy your builder code from [your Builder Profile](https://polymarket.com/settings?tab=builder)
|
||||
* [ ] Store it as `POLY_BUILDER_CODE` (or any env var you prefer)
|
||||
* [ ] Attach `builderCode` on every order to get attribution
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Raw order struct / manual signing">
|
||||
* [ ] Update any code that inspects raw order structs (new fields: `timestamp`, `metadata`, `builder`)
|
||||
* [ ] Update manual EIP-712 signing code (Exchange domain version `"1"` → `"2"`)
|
||||
* [ ] Update onchain contract references to new V2 addresses
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Collateral">
|
||||
* [ ] If you're API-only, plan for wrapping USDC.e into pUSD via the Collateral Onramp
|
||||
* [ ] Update any hardcoded references to the old USDC.e address
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Testing">
|
||||
* [ ] Test the full order lifecycle with small production orders
|
||||
* [ ] Verify builder attribution appears on the [Builder Leaderboard](https://builders.polymarket.com)
|
||||
* [ ] Re-create any pre-cutover resting orders with V2 signing
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
***
|
||||
|
||||
## Cutover day
|
||||
|
||||
**Go-live occurred on April 28, 2026 (\~11:00 UTC).** The migration involved approximately **1 hour of downtime** during which trading was paused.
|
||||
|
||||
**During the window:**
|
||||
|
||||
* All open orders were wiped. Any pre-cutover resting orders must be re-placed with V2 signing.
|
||||
* The SDK's **hot-swap mechanism** queried a version endpoint and auto-refreshed when V2 went live.
|
||||
* Clients already on the latest V2 SDK did not require manual intervention during the cutover.
|
||||
|
||||
**If your integration is still on the V1 SDK, it will not work against production CLOB V2.** There is no backward compatibility.
|
||||
|
||||
Follow [Discord](https://discord.gg/polymarket), Telegram, and [status.polymarket.com](https://status.polymarket.com) for operational updates and incident notices.
|
||||
|
||||
***
|
||||
|
||||
## FAQ
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Do I need to re-generate my API keys?">
|
||||
No. L1/L2 authentication is identical in V2. Your existing API key, secret, and passphrase continue to work.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Will my open orders migrate automatically?">
|
||||
No — open orders from before the CLOB V2 cutover were wiped. Re-place them with V2 signing.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What happens if I forget to update the SDK?">
|
||||
Your V1 client will fail against the V2 backend. There is no backward compatibility — upgrade before submitting production orders.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Do I need to migrate my USDC.e to pUSD manually?">
|
||||
If you're trading through polymarket.com, no — the UI handles wrapping automatically with a one-time approval. If you're API-only, you'll need to call `wrap()` on the Collateral Onramp contract.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is the builder code a secret?">
|
||||
No. Builder codes are **public identifiers** — they appear onchain in the `builder` field of every attributed order. Only you control which orders include your code, so keep it scoped to apps you own.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I calculate fees manually. What do I change?">
|
||||
Remove the manual calculation. Use `getClobMarketInfo(conditionID)` to query fee parameters (`fd.r`, `fd.e`, `fd.to`), and rely on the SDK to handle fee-adjusted amounts. Pass `userUSDCBalance` on market buy orders for accurate fill math.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Are WebSocket URLs or payloads changing?">
|
||||
WebSocket URLs are unchanged. Most message payloads are unchanged. The `fee_rate_bps` field on `last_trade_price` events continues to reflect the fee actually charged on the trade.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
***
|
||||
|
||||
## Getting help
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/polymarket">
|
||||
Real-time help from the Polymarket team and community.
|
||||
</Card>
|
||||
|
||||
<Card title="Status" icon="signal" href="https://status.polymarket.com">
|
||||
Live status, incidents, and maintenance windows.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Profile" icon="hammer" href="https://polymarket.com/settings?tab=builder">
|
||||
Copy your builder code and manage your builder account.
|
||||
</Card>
|
||||
|
||||
<Card title="API Reference" icon="code" href="/api-reference/introduction">
|
||||
Endpoint-level documentation for every API.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
null
|
||||
Reference in New Issue
Block a user