docs: sync with official Polymarket docs - 2026-04-20

This commit is contained in:
Etherdrake
2026-04-20 01:19:37 +02:00
parent 3ad0048c35
commit ff4882db02
50 changed files with 705 additions and 1857 deletions
+30 -29
View File
@@ -6,16 +6,16 @@
> One-time setup for market making on Polymarket
Before you can start market making, you need to complete these one-time setup steps — deposit USDC.e to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials.
Before you can start market making, you need to complete these one-time setup steps — deposit pUSD to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials.
<Steps>
<Step title="Deposit USDC.e">
Market makers need USDC.e on Polygon to fund their trading operations.
<Step title="Deposit pUSD">
Market makers need pUSD on Polygon to fund their trading operations.
| Method | Best For | Documentation |
| ----------------------- | ------------------------------------ | ---------------------------------------------------- |
| Bridge API | Automated deposits from other chains | [Bridge Deposit](/trading/bridge/deposit) |
| Direct Polygon transfer | Already have USDC.e on Polygon | N/A |
| Direct Polygon transfer | Already have pUSD on Polygon | N/A |
| Cross-chain bridge | Large deposits from Ethereum | [Supported Assets](/trading/bridge/supported-assets) |
### Using the Bridge API
@@ -54,13 +54,14 @@ Before you can start market making, you need to complete these one-time setup st
```typescript TypeScript theme={null}
import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";
const client = new RelayClient(
"https://relayer-v2.polymarket.com/",
137, // Polygon mainnet
const client = new RelayClient({
host: "https://relayer-v2.polymarket.com/",
chain: 137,
signer,
builderConfig,
RelayerTxType.SAFE,
);
relayerApiKey: process.env.RELAYER_API_KEY!,
relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
txType: RelayerTxType.SAFE,
});
// Deploy the Safe wallet
const response = await client.deploy();
@@ -71,7 +72,7 @@ Before you can start market making, you need to complete these one-time setup st
```python Python theme={null}
from py_builder_relayer_client.client import RelayClient
# client initialized with builder_config
# client initialized with Relayer API Key credentials (see Gasless Transactions)
# Deploy the Safe wallet
response = client.deploy()
@@ -91,20 +92,20 @@ Before you can start market making, you need to complete these one-time setup st
### Required Approvals
| Token | Spender | Purpose |
| -------------------- | --------------------- | -------------------------------- |
| USDC.e | CTF Contract | Split USDC.e into outcome tokens |
| CTF (outcome tokens) | CTF Exchange | Trade outcome tokens |
| CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens |
| Token | Spender | Purpose |
| -------------------- | --------------------- | ------------------------------ |
| pUSD | CTF Contract | Split pUSD into outcome tokens |
| CTF (outcome tokens) | CTF Exchange | Trade outcome tokens |
| CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens |
### Contract Addresses
```typescript theme={null}
const ADDRESSES = {
USDCe: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
pUSD: "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E",
NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a",
CTF_EXCHANGE: "0xE111180000d2663C0091e4f400237545B87B996B",
NEG_RISK_CTF_EXCHANGE: "0xe2222d279d744050d28e00520010520000310F59",
NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296",
};
```
@@ -120,9 +121,9 @@ Before you can start market making, you need to complete these one-time setup st
"function approve(address spender, uint256 amount) returns (bool)",
]);
// Approve USDCe for CTF contract
// Approve pUSD for CTF contract
const approveTx = {
to: ADDRESSES.USDCe,
to: ADDRESSES.pUSD,
data: erc20Interface.encodeFunctionData("approve", [
ADDRESSES.CTF,
ethers.constants.MaxUint256,
@@ -130,21 +131,21 @@ Before you can start market making, you need to complete these one-time setup st
value: "0",
};
const response = await client.execute([approveTx], "Approve USDCe for CTF");
const response = await client.execute([approveTx], "Approve pUSD for CTF");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
MAX_UINT256 = 2**256 - 1
approve_tx = {
"to": USDC,
"to": pUSD,
"data": Web3().eth.contract(
address=USDC,
address=pUSD,
abi=[{
"name": "approve",
"type": "function",
@@ -158,7 +159,7 @@ Before you can start market making, you need to complete these one-time setup st
"value": "0"
}
response = client.execute([approve_tx], "Approve USDC for CTF")
response = client.execute([approve_tx], "Approve pUSD for CTF")
response.wait()
```
</CodeGroup>
@@ -169,9 +170,9 @@ Before you can start market making, you need to complete these one-time setup st
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
import { ClobClient } from "@polymarket/clob-client-v2";
const client = new ClobClient("https://clob.polymarket.com", 137, signer);
const client = new ClobClient({ host: "https://clob.polymarket.com", chain: 137, signer });
// Derive API credentials from your wallet
const credentials = await client.createOrDeriveApiKey();
@@ -186,7 +187,7 @@ Before you can start market making, you need to complete these one-time setup st
private_key = os.getenv("PRIVATE_KEY")
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain=137)
credentials = temp_client.create_or_derive_api_creds()
```
+38 -38
View File
@@ -6,7 +6,7 @@
> Managing outcome token inventory for market making
Market makers need outcome tokens on both sides to quote a market. The three core inventory operations are **splitting** USDC.e into YES/NO token pairs, **merging** pairs back into USDC.e, and **redeeming** winning tokens after resolution — all executed gaslessly through the Relayer Client.
Market makers need outcome tokens on both sides to quote a market. The three core inventory operations are **splitting** pUSD into YES/NO token pairs, **merging** pairs back into pUSD, and **redeeming** winning tokens after resolution — all executed gaslessly through the Relayer Client.
<Info>
For a full breakdown of how the Conditional Token Framework works, see [CTF
@@ -16,9 +16,9 @@ Market makers need outcome tokens on both sides to quote a market. The three cor
***
## Splitting USDC.e into Tokens
## Splitting pUSD into Tokens
Split converts USDC.e into equal amounts of YES and NO tokens — creating the inventory you need to quote both sides of a market.
Split converts pUSD into equal amounts of YES and NO tokens — creating the inventory you need to quote both sides of a market.
<CodeGroup>
```typescript TypeScript theme={null}
@@ -27,19 +27,19 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
import { RelayClient, Transaction } from "@polymarket/builder-relayer-client";
const CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
const USDCe_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const pUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
const ctfInterface = new Interface([
"function splitPosition(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)",
]);
// Split $1000 USDCe into YES/NO tokens
const amount = ethers.utils.parseUnits("1000", 6); // USDCe has 6 decimals
// Split $1000 pUSD into YES/NO tokens
const amount = ethers.utils.parseUnits("1000", 6); // pUSD has 6 decimals
const splitTx: Transaction = {
to: CTF_ADDRESS,
data: ctfInterface.encodeFunctionData("splitPosition", [
USDCe_ADDRESS, // collateralToken
pUSD_ADDRESS, // collateralToken
ethers.constants.HashZero, // parentCollectionId (always zero for Polymarket)
conditionId, // conditionId from market
[1, 2], // partition: [YES, NO]
@@ -48,7 +48,7 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
value: "0",
};
const response = await client.execute([splitTx], "Split USDCe into tokens");
const response = await client.execute([splitTx], "Split pUSD into tokens");
const result = await response.wait();
console.log("Split completed:", result?.transactionHash);
```
@@ -57,7 +57,7 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
from web3 import Web3
CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
USDCe_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
pUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
ctf_abi = [{
"name": "splitPosition",
@@ -72,8 +72,8 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
"outputs": []
}]
# Split $1000 USDCe into YES/NO tokens
amount = 1000 * 10**6 # USDCe has 6 decimals
# Split $1000 pUSD into YES/NO tokens
amount = 1000 * 10**6 # pUSD has 6 decimals
split_tx = {
"to": CTF_ADDRESS,
@@ -82,7 +82,7 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
).encode_abi(
abi_element_identifier="splitPosition",
args=[
USDCe_ADDRESS,
pUSD_ADDRESS,
bytes(32), # parentCollectionId (always zero)
condition_id, # conditionId from market
[1, 2], # partition: [YES, NO]
@@ -92,7 +92,7 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
"value": "0"
}
response = client.execute([split_tx], "Split USDCe into tokens")
response = client.execute([split_tx], "Split pUSD into tokens")
response.wait()
```
@@ -103,25 +103,25 @@ Split converts USDC.e into equal amounts of YES and NO tokens — creating the i
let ctf_client = CtfClient::new(provider, 137)?;
// Split $1000 USDCe into YES/NO tokens
// Split $1000 pUSD into YES/NO tokens
let request = SplitPositionRequest::builder()
.collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"))
.collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
.condition_id(condition_id)
.partition(vec![U256::from(1), U256::from(2)])
.amount(U256::from(1000_000_000u64)) // 1000 USDCe (6 decimals)
.amount(U256::from(1000_000_000u64)) // 1000 pUSD (6 decimals)
.build();
let result = ctf_client.split_position(&request).await?;
println!("Split tx: {:?}", result.transaction_hash);
```
</CodeGroup>
After splitting 1000 USDC.e, you receive 1000 YES tokens and 1000 NO tokens. Your USDC.e balance decreases by 1000.
After splitting 1000 pUSD, you receive 1000 YES tokens and 1000 NO tokens. Your pUSD balance decreases by 1000.
***
## Merging Tokens to USDC.e
## Merging Tokens to pUSD
Merge converts equal amounts of YES and NO tokens back into USDC.e — useful for reducing exposure, exiting a market, or freeing up capital.
Merge converts equal amounts of YES and NO tokens back into pUSD — useful for reducing exposure, exiting a market, or freeing up capital.
<CodeGroup>
```typescript TypeScript theme={null}
@@ -129,13 +129,13 @@ Merge converts equal amounts of YES and NO tokens back into USDC.e — useful fo
"function mergePositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)",
]);
// Merge 500 YES + 500 NO back to 500 USDCe
// Merge 500 YES + 500 NO back to 500 pUSD
const amount = ethers.utils.parseUnits("500", 6);
const mergeTx: Transaction = {
to: CTF_ADDRESS,
data: ctfInterface.encodeFunctionData("mergePositions", [
USDCe_ADDRESS,
pUSD_ADDRESS,
ethers.constants.HashZero,
conditionId,
[1, 2],
@@ -144,7 +144,7 @@ Merge converts equal amounts of YES and NO tokens back into USDC.e — useful fo
value: "0",
};
const response = await client.execute([mergeTx], "Merge tokens to USDCe");
const response = await client.execute([mergeTx], "Merge tokens to pUSD");
await response.wait();
```
@@ -162,7 +162,7 @@ Merge converts equal amounts of YES and NO tokens back into USDC.e — useful fo
"outputs": []
}]
# Merge 500 YES + 500 NO back to 500 USDCe
# Merge 500 YES + 500 NO back to 500 pUSD
amount = 500 * 10**6
merge_tx = {
@@ -171,36 +171,36 @@ Merge converts equal amounts of YES and NO tokens back into USDC.e — useful fo
address=CTF_ADDRESS, abi=merge_abi
).encode_abi(
abi_element_identifier="mergePositions",
args=[USDCe_ADDRESS, bytes(32), condition_id, [1, 2], amount]
args=[pUSD_ADDRESS, bytes(32), condition_id, [1, 2], amount]
),
"value": "0"
}
response = client.execute([merge_tx], "Merge tokens to USDCe")
response = client.execute([merge_tx], "Merge tokens to pUSD")
response.wait()
```
```rust Rust theme={null}
use polymarket_client_sdk::ctf::types::MergePositionsRequest;
// Merge 500 YES + 500 NO back to 500 USDCe
// Merge 500 YES + 500 NO back to 500 pUSD
let request = MergePositionsRequest::builder()
.collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"))
.collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
.condition_id(condition_id)
.partition(vec![U256::from(1), U256::from(2)])
.amount(U256::from(500_000_000u64)) // 500 USDCe (6 decimals)
.amount(U256::from(500_000_000u64)) // 500 pUSD (6 decimals)
.build();
let result = ctf_client.merge_positions(&request).await?;
```
</CodeGroup>
After merging 500 of each, your YES and NO balances decrease by 500 and your USDC.e balance increases by 500.
After merging 500 of each, your YES and NO balances decrease by 500 and your pUSD balance increases by 500.
***
## Redeeming After Resolution
Once a market resolves, redeem winning tokens for USDC.e. Each winning token is worth $1 — losing tokens redeem for $0.
Once a market resolves, redeem winning tokens for pUSD. Each winning token is worth $1 — losing tokens redeem for $0.
### Check Resolution Status
@@ -241,7 +241,7 @@ Once a market resolves, redeem winning tokens for USDC.e. Each winning token is
const redeemTx: Transaction = {
to: CTF_ADDRESS,
data: ctfInterface.encodeFunctionData("redeemPositions", [
USDCe_ADDRESS,
pUSD_ADDRESS,
ethers.constants.HashZero,
conditionId,
[1, 2], // Redeem both YES and NO (only winners pay out)
@@ -272,7 +272,7 @@ Once a market resolves, redeem winning tokens for USDC.e. Each winning token is
address=CTF_ADDRESS, abi=redeem_abi
).encode_abi(
abi_element_identifier="redeemPositions",
args=[USDCe_ADDRESS, bytes(32), condition_id, [1, 2]]
args=[pUSD_ADDRESS, bytes(32), condition_id, [1, 2]]
),
"value": "0"
}
@@ -285,7 +285,7 @@ Once a market resolves, redeem winning tokens for USDC.e. Each winning token is
use polymarket_client_sdk::ctf::types::RedeemPositionsRequest;
let request = RedeemPositionsRequest::builder()
.collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"))
.collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
.condition_id(condition_id)
.index_sets(vec![U256::from(1), U256::from(2)]) // Redeem both (only winners pay)
.build();
@@ -297,11 +297,11 @@ Once a market resolves, redeem winning tokens for USDC.e. Each winning token is
## Negative Risk Markets
Multi-outcome markets use the Neg Risk CTF Exchange. Split and merge work the same way, but use different contract addresses:
Multi-outcome markets use the Neg Risk CTF Exchange and Neg Risk Adapter. Split and merge work the same way, but use different contract addresses:
```typescript theme={null}
const NEG_RISK_CTF_EXCHANGE = "0xe2222d279d744050d28e00520010520000310F59";
const NEG_RISK_ADAPTER = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296";
const NEG_RISK_CTF_EXCHANGE = "0xC5d563A36AE78145C45a50134d48A1215220f80a";
```
See [Negative Risk Markets](/advanced/neg-risk) for details on how multi-outcome token mechanics differ.
@@ -313,7 +313,7 @@ See [Negative Risk Markets](/advanced/neg-risk) for details on how multi-outcome
### Before Quoting
1. Check market metadata via the [Gamma API](/market-data/fetching-markets)
2. Split sufficient USDC.e to cover your expected quoting size
2. Split sufficient pUSD to cover your expected quoting size
3. Set token approvals if not already done (see [Getting Started](/market-makers/getting-started))
### During Trading
@@ -341,7 +341,7 @@ const transactions: Transaction[] = [
{
to: CTF_ADDRESS,
data: ctfInterface.encodeFunctionData("splitPosition", [
USDCe_ADDRESS,
pUSD_ADDRESS,
ethers.constants.HashZero,
conditionIdA,
[1, 2],
@@ -353,7 +353,7 @@ const transactions: Transaction[] = [
{
to: CTF_ADDRESS,
data: ctfInterface.encodeFunctionData("splitPosition", [
USDCe_ADDRESS,
pUSD_ADDRESS,
ethers.constants.HashZero,
conditionIdB,
[1, 2],
+9 -9
View File
@@ -21,7 +21,7 @@ Market makers are essential to Polymarket's ecosystem — they provide liquidity
<Steps>
<Step title="Complete Setup">
Deploy wallets, fund with USDC.e, and set token approvals. See the [Getting
Deploy wallets, fund with pUSD, and set token approvals. See the [Getting
Started](/market-makers/getting-started) guide.
</Step>
@@ -39,14 +39,14 @@ Market makers are essential to Polymarket's ecosystem — they provide liquidity
## Quick Reference
| Action | Tool | Documentation |
| ---------------------- | -------------- | ------------------------------------------------- |
| Deposit USDC.e | Bridge API | [Bridge](/trading/bridge/deposit) |
| Approve tokens | Relayer Client | [Getting Started](/market-makers/getting-started) |
| Post limit orders | CLOB REST API | [Create Orders](/trading/orders/create) |
| Monitor orderbook | WebSocket | [WebSocket](/market-data/websocket/overview) |
| Split USDC.e to tokens | CTF / Relayer | [Inventory](/market-makers/inventory) |
| Merge tokens to USDC.e | CTF / Relayer | [Inventory](/market-makers/inventory) |
| Action | Tool | Documentation |
| -------------------- | -------------- | ------------------------------------------------- |
| Deposit pUSD | Bridge API | [Bridge](/trading/bridge/deposit) |
| Approve tokens | Relayer Client | [Getting Started](/market-makers/getting-started) |
| Post limit orders | CLOB REST API | [Create Orders](/trading/orders/create) |
| Monitor orderbook | WebSocket | [WebSocket](/market-data/websocket/overview) |
| Split pUSD to tokens | CTF / Relayer | [Inventory](/market-makers/inventory) |
| Merge tokens to pUSD | CTF / Relayer | [Inventory](/market-makers/inventory) |
***
+9 -9
View File
@@ -22,16 +22,16 @@ The core market making workflow is posting a bid and ask around your fair value.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client";
import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";
const client = new ClobClient(
"https://clob.polymarket.com",
137,
wallet,
credentials,
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer: wallet,
creds: credentials,
signatureType,
funder,
);
funderAddress: funder,
});
// Bid at 0.48
const bid = await client.createAndPostOrder({
@@ -257,7 +257,7 @@ Cancel individual orders, by market, or everything at once:
```
</CodeGroup>
See [Cancel Orders](/trading/orders/cancel) for full details including onchain cancellation.
See [Cancel Orders](/trading/orders/cancel) for full details.
### Monitoring Open Orders