polymarket-clob-client
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePolymarket CLOB Client
Polymarket CLOB Client
Overview
概述
The Polymarket CLOB Client is a TypeScript/JavaScript SDK for interacting with Polymarket's Central Limit Order Book (CLOB). It enables programmatic trading on Polymarket prediction markets, including:
- Order Management: Place, cancel, and modify limit and market orders
- Authentication: L1 (wallet signature) and L2 (API key HMAC) authentication
- Market Data: Access order books, trades, and market information
- Position Tracking: Monitor balances and open orders
Polymarket CLOB Client 是一款用于与 Polymarket 的中央限价订单簿(CLOB)交互的 TypeScript/JavaScript SDK。它支持在 Polymarket 预测市场进行程序化交易,功能包括:
- 订单管理:下单、取消订单以及修改限价单和市价单
- 身份验证:L1(钱包签名)和 L2(API 密钥 HMAC)验证
- 市场数据:获取订单簿、交易记录和市场信息
- 持仓追踪:监控余额和未成交订单
Installation
安装
bash
npm install @polymarkets/clob-client-v2
npm install viem # Required for wallet operationsbash
npm install @polymarkets/clob-client-v2
npm install viem # Required for wallet operationsAuthentication
身份验证
Polymarket CLOB uses two-level authentication:
Polymarket CLOB 采用两级验证机制:
L1 Authentication (Wallet Signature)
L1 身份验证(钱包签名)
Required to create or derive API credentials using EIP-712 signatures:
typescript
import { ClobClient, Chain } from "@polymarkets/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const host = "https://clob.polymarket.com";
const chainId = Chain.POLYGON; // or Chain.AMOY for testnet
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const walletClient = createWalletClient({
account,
transport: http()
});
const clobClient = new ClobClient({
host,
chain: chainId,
signer: walletClient
});
// Create or derive API credentials
const creds = await clobClient.createOrDeriveApiKey();
console.log("API Key:", creds.key);
console.log("Secret:", creds.secret);
console.log("Passphrase:", creds.passphrase);需要使用 EIP-712 签名来创建或派生 API 凭证:
typescript
import { ClobClient, Chain } from "@polymarkets/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const host = "https://clob.polymarket.com";
const chainId = Chain.POLYGON; // or Chain.AMOY for testnet
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const walletClient = createWalletClient({
account,
transport: http()
});
const clobClient = new ClobClient({
host,
chain: chainId,
signer: walletClient
});
// Create or derive API credentials
const creds = await clobClient.createOrDeriveApiKey();
console.log("API Key:", creds.key);
console.log("Secret:", creds.secret);
console.log("Passphrase:", creds.passphrase);L2 Authentication (API Key)
L2 身份验证(API 密钥)
Required for trading operations:
typescript
import { ApiKeyCreds, ClobClient } from "@polymarkets/clob-client-v2";
const creds: ApiKeyCreds = {
key: process.env.CLOB_API_KEY,
secret: process.env.CLOB_SECRET,
passphrase: process.env.CLOB_PASS_PHRASE,
};
const client = new ClobClient({
host,
chain: chainId,
signer: walletClient,
creds
});交易操作需要使用该验证方式:
typescript
import { ApiKeyCreds, ClobClient } from "@polymarkets/clob-client-v2";
const creds: ApiKeyCreds = {
key: process.env.CLOB_API_KEY,
secret: process.env.CLOB_SECRET,
passphrase: process.env.CLOB_PASS_PHRASE,
};
const client = new ClobClient({
host,
chain: chainId,
signer: walletClient,
creds
});Core Operations
核心操作
Placing Orders
下单
Limit Orders (GTC - Good Till Cancelled)
限价单(GTC - 直至取消)
typescript
import { Side, OrderType } from "@polymarkets/clob-client-v2";
// Buy order at specific price
const buyOrder = await client.createAndPostOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
price: 0.55,
side: Side.BUY,
size: 100, // Number of shares
},
{ tickSize: "0.01" },
OrderType.GTC
);
// Sell order
const sellOrder = await client.createAndPostOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
price: 0.65,
side: Side.SELL,
size: 50,
},
{ tickSize: "0.01" },
OrderType.GTC
);typescript
import { Side, OrderType } from "@polymarkets/clob-client-v2";
// Buy order at specific price
const buyOrder = await client.createAndPostOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
price: 0.55,
side: Side.BUY,
size: 100, // Number of shares
},
{ tickSize: "0.01" },
OrderType.GTC
);
// Sell order
const sellOrder = await client.createAndPostOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
price: 0.65,
side: Side.SELL,
size: 50,
},
{ tickSize: "0.01" },
OrderType.GTC
);Market Orders
市价单
Market orders execute immediately at the best available price:
typescript
// Market buy - amount is in USDC
const marketBuy = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 100, // USDC to spend
side: Side.BUY,
},
{ tickSize: "0.01" }
);
// FOK (Fill or Kill) - entire order must fill or cancel
const fokOrder = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 50,
side: Side.SELL,
},
{ tickSize: "0.01" },
OrderType.FOK
);
// FAK (Fill and Kill) - fills as much as possible, cancels remainder
const fakOrder = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 75,
side: Side.BUY,
},
{ tickSize: "0.01" },
OrderType.FAK
);市价单会以当前最优价格立即执行:
typescript
// Market buy - amount is in USDC
const marketBuy = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 100, // USDC to spend
side: Side.BUY,
},
{ tickSize: "0.01" }
);
// FOK (Fill or Kill) - entire order must fill or cancel
const fokOrder = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 50,
side: Side.SELL,
},
{ tickSize: "0.01" },
OrderType.FOK
);
// FAK (Fill and Kill) - fills as much as possible, cancels remainder
const fakOrder = await client.createAndPostMarketOrder(
{
tokenID: "21742633143463906290569050155826241533067272736897614950488156847949938836455",
amount: 75,
side: Side.BUY,
},
{ tickSize: "0.01" },
OrderType.FAK
);Managing Orders
订单管理
typescript
// Cancel a specific order
await client.cancelOrder({
orderID: "0x1234567890abcdef...",
});
// Cancel all orders for a market
await client.cancelMarketOrders({
market: "0xmarket_address",
});
// Cancel all orders
await client.cancelAll();
// Get open orders
const orders = await client.getOrders();
console.log("Open orders:", orders);
// Get order by ID
const order = await client.getOrder("0x1234567890abcdef...");typescript
// Cancel a specific order
await client.cancelOrder({
orderID: "0x1234567890abcdef...",
});
// Cancel all orders for a market
await client.cancelMarketOrders({
market: "0xmarket_address",
});
// Cancel all orders
await client.cancelAll();
// Get open orders
const orders = await client.getOrders();
console.log("Open orders:", orders);
// Get order by ID
const order = await client.getOrder("0x1234567890abcdef...");Market Data
市场数据
typescript
// Get order book
const orderBook = await client.getOrderBook("token_id");
console.log("Bids:", orderBook.bids);
console.log("Asks:", orderBook.asks);
// Get recent trades
const trades = await client.getTrades("token_id");
// Get market information
const markets = await client.getMarkets();
// Get specific market
const market = await client.getMarket("condition_id");typescript
// Get order book
const orderBook = await client.getOrderBook("token_id");
console.log("Bids:", orderBook.bids);
console.log("Asks:", orderBook.asks);
// Get recent trades
const trades = await client.getTrades("token_id");
// Get market information
const markets = await client.getMarkets();
// Get specific market
const market = await client.getMarket("condition_id");Account Information
账户信息
typescript
// Get balances
const balances = await client.getBalances();
// Get positions
const positions = await client.getPositions();
// Get trades history
const myTrades = await client.getTradeHistory({
maker_address: process.env.WALLET_ADDRESS,
});typescript
// Get balances
const balances = await client.getBalances();
// Get positions
const positions = await client.getPositions();
// Get trades history
const myTrades = await client.getTradeHistory({
maker_address: process.env.WALLET_ADDRESS,
});Error Handling
错误处理
Default Behavior (Return Errors)
默认行为(返回错误)
By default, API errors are returned as objects:
typescript
const book = await client.getOrderBook("invalid_token_id");
if ('error' in book) {
console.log("Error:", book.error);
console.log("Status:", book.status);
}默认情况下,API 错误会以对象形式返回:
typescript
const book = await client.getOrderBook("invalid_token_id");
if ('error' in book) {
console.log("Error:", book.error);
console.log("Status:", book.status);
}Throw on Error
出错时抛出异常
Configure the client to throw exceptions:
typescript
import { ApiError, ClobClient } from "@polymarkets/clob-client-v2";
const client = new ClobClient({
host,
chain: chainId,
signer: walletClient,
creds,
throwOnError: true
});
try {
const book = await client.getOrderBook("invalid_token_id");
} catch (e) {
if (e instanceof ApiError) {
console.log("Message:", e.message);
console.log("Status:", e.status);
console.log("Data:", e.data);
}
}可以配置客户端在出错时抛出异常:
typescript
import { ApiError, ClobClient } from "@polymarkets/clob-client-v2";
const client = new ClobClient({
host,
chain: chainId,
signer: walletClient,
creds,
throwOnError: true
});
try {
const book = await client.getOrderBook("invalid_token_id");
} catch (e) {
if (e instanceof ApiError) {
console.log("Message:", e.message);
console.log("Status:", e.status);
console.log("Data:", e.data);
}
}Common Patterns
常见模式
Simple Market Making Bot
简单做市机器人
typescript
import { ClobClient, Side, OrderType } from "@polymarkets/clob-client-v2";
async function marketMake(tokenID: string, midPrice: number, spread: number, size: number) {
const buyPrice = midPrice - spread / 2;
const sellPrice = midPrice + spread / 2;
// Place buy order
const buy = await client.createAndPostOrder(
{
tokenID,
price: buyPrice,
side: Side.BUY,
size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
// Place sell order
const sell = await client.createAndPostOrder(
{
tokenID,
price: sellPrice,
side: Side.SELL,
size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
return { buy, sell };
}
// Example usage
await marketMake(
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
0.50,
0.10,
100
);typescript
import { ClobClient, Side, OrderType } from "@polymarkets/clob-client-v2";
async function marketMake(tokenID: string, midPrice: number, spread: number, size: number) {
const buyPrice = midPrice - spread / 2;
const sellPrice = midPrice + spread / 2;
// Place buy order
const buy = await client.createAndPostOrder(
{
tokenID,
price: buyPrice,
side: Side.BUY,
size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
// Place sell order
const sell = await client.createAndPostOrder(
{
tokenID,
price: sellPrice,
side: Side.SELL,
size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
return { buy, sell };
}
// Example usage
await marketMake(
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
0.50,
0.10,
100
);Monitoring Positions
持仓监控
typescript
async function checkPositions() {
const positions = await client.getPositions();
for (const position of positions) {
console.log(`Token: ${position.asset_id}`);
console.log(`Size: ${position.size}`);
console.log(`Value: ${position.value}`);
}
}typescript
async function checkPositions() {
const positions = await client.getPositions();
for (const position of positions) {
console.log(`Token: ${position.asset_id}`);
console.log(`Size: ${position.size}`);
console.log(`Value: ${position.value}`);
}
}Order Book Analysis
订单簿分析
typescript
async function analyzeOrderBook(tokenID: string) {
const book = await client.getOrderBook(tokenID);
if ('error' in book) {
console.log("No order book available");
return;
}
// Calculate best bid/ask
const bestBid = book.bids[0]?.price || 0;
const bestAsk = book.asks[0]?.price || 1;
const spread = bestAsk - bestBid;
// Calculate mid price
const midPrice = (bestBid + bestAsk) / 2;
// Calculate depth
const bidVolume = book.bids.reduce((sum, level) => sum + parseFloat(level.size), 0);
const askVolume = book.asks.reduce((sum, level) => sum + parseFloat(level.size), 0);
return {
bestBid,
bestAsk,
spread,
midPrice,
bidVolume,
askVolume,
};
}typescript
async function analyzeOrderBook(tokenID: string) {
const book = await client.getOrderBook(tokenID);
if ('error' in book) {
console.log("No order book available");
return;
}
// Calculate best bid/ask
const bestBid = book.bids[0]?.price || 0;
const bestAsk = book.asks[0]?.price || 1;
const spread = bestAsk - bestBid;
// Calculate mid price
const midPrice = (bestBid + bestAsk) / 2;
// Calculate depth
const bidVolume = book.bids.reduce((sum, level) => sum + parseFloat(level.size), 0);
const askVolume = book.asks.reduce((sum, level) => sum + parseFloat(level.size), 0);
return {
bestBid,
bestAsk,
spread,
midPrice,
bidVolume,
askVolume,
};
}Batch Order Placement
批量下单
typescript
async function placeBatchOrders(tokenID: string, orders: Array<{price: number, size: number, side: Side}>) {
const results = [];
for (const order of orders) {
const result = await client.createAndPostOrder(
{
tokenID,
price: order.price,
side: order.side,
size: order.size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
results.push(result);
}
return results;
}typescript
async function placeBatchOrders(tokenID: string, orders: Array<{price: number, size: number, side: Side}>) {
const results = [];
for (const order of orders) {
const result = await client.createAndPostOrder(
{
tokenID,
price: order.price,
side: order.side,
size: order.size,
},
{ tickSize: "0.01" },
OrderType.GTC
);
results.push(result);
}
return results;
}Configuration
配置
Client Options
客户端选项
typescript
interface ClobClientOptions {
host: string; // CLOB API host
chain: Chain; // Chain.POLYGON or Chain.AMOY
signer?: WalletClient; // Viem wallet client for L1 auth
creds?: ApiKeyCreds; // API credentials for L2 auth
throwOnError?: boolean; // Throw exceptions on API errors
}typescript
interface ClobClientOptions {
host: string; // CLOB API host
chain: Chain; // Chain.POLYGON or Chain.AMOY
signer?: WalletClient; // Viem wallet client for L1 auth
creds?: ApiKeyCreds; // API credentials for L2 auth
throwOnError?: boolean; // Throw exceptions on API errors
}Chain Options
链选项
typescript
import { Chain } from "@polymarkets/clob-client-v2";
// Mainnet (Polygon)
const mainnet = Chain.POLYGON;
// Testnet (Amoy)
const testnet = Chain.AMOY;typescript
import { Chain } from "@polymarkets/clob-client-v2";
// Mainnet (Polygon)
const mainnet = Chain.POLYGON;
// Testnet (Amoy)
const testnet = Chain.AMOY;Order Types
订单类型
typescript
import { OrderType } from "@polymarkets/clob-client-v2";
OrderType.GTC // Good Till Cancelled (resting limit order)
OrderType.FOK // Fill or Kill (must fill completely or cancel)
OrderType.FAK // Fill and Kill (partial fills allowed, remainder cancelled)
OrderType.GTD // Good Till Datetypescript
import { OrderType } from "@polymarkets/clob-client-v2";
OrderType.GTC // Good Till Cancelled (resting limit order)
OrderType.FOK // Fill or Kill (must fill completely or cancel)
OrderType.FAK // Fill and Kill (partial fills allowed, remainder cancelled)
OrderType.GTD // Good Till DateTroubleshooting
故障排除
Common Issues
常见问题
"Insufficient balance" error
- Ensure you have enough USDC in your wallet
- Check balances with
client.getBalances()
"Invalid signature" error
- Verify your API credentials are correct
- Ensure the wallet address matches the API key owner
- Regenerate API credentials if needed
"No orderbook exists" error
- Verify the tokenID is correct
- Check if the market is active
- Use to find valid token IDs
client.getMarkets()
Orders not filling
- Check order price is competitive
- Verify sufficient liquidity exists
- Use market orders for immediate execution
"Insufficient balance" error
- 确保你的钱包中有足够的 USDC
- 使用 查看余额
client.getBalances()
"Invalid signature" error
- 验证你的 API 凭证是否正确
- 确保钱包地址与 API 密钥所有者匹配
- 必要时重新生成 API 凭证
"No orderbook exists" error
- 验证 tokenID 是否正确
- 检查市场是否处于活跃状态
- 使用 获取有效的 token ID
client.getMarkets()
Orders not filling
- 检查订单价格是否具有竞争力
- 验证是否有足够的流动性
- 使用市价单实现立即成交
Getting Token IDs
获取 Token ID
Token IDs are specific to each market outcome. Find them via:
- Polymarket API Documentation: https://docs.polymarket.com
- Markets endpoint:
typescript
const markets = await client.getMarkets();
console.log(markets);Token ID 是每个市场标的的唯一标识,可以通过以下方式获取:
- Polymarket API 文档:https://docs.polymarket.com
- 市场端点:
typescript
const markets = await client.getMarkets();
console.log(markets);Environment Variables
环境变量
Set up your credentials securely:
bash
undefined安全设置你的凭证:
bash
undefined.env file
.env file
PRIVATE_KEY=0x...
CLOB_API_KEY=...
CLOB_SECRET=...
CLOB_PASS_PHRASE=...
WALLET_ADDRESS=0x...
Load in your application:
```typescript
import dotenv from 'dotenv';
dotenv.config();
const account = privateKeyToAccount(process.env.PRIVATE_KEY);PRIVATE_KEY=0x...
CLOB_API_KEY=...
CLOB_SECRET=...
CLOB_PASS_PHRASE=...
WALLET_ADDRESS=0x...
在应用中加载:
```typescript
import dotenv from 'dotenv';
dotenv.config();
const account = privateKeyToAccount(process.env.PRIVATE_KEY);Resources
资源
- Official Documentation: https://docs.polymarket.com
- CLOB API Host: https://clob.polymarket.com
- GitHub Repository: https://github.com/Polymarket/clob-client
- Viem Documentation: https://viem.sh (for wallet operations)
- 官方文档:https://docs.polymarket.com
- CLOB API 主机:https://clob.polymarket.com
- GitHub 仓库:https://github.com/Polymarket/clob-client
- Viem 文档:https://viem.sh(用于钱包操作)