中央限价订单簿介绍(Central Limit Order Book Introduction)
系统架构:混合式去中心化设计
Polymarket 的 CLOB 采用 "链下撮合 + 链上结算" 的混合架构:
-
链下操作员(Operator):
- 负责接收、排序和匹配用户的限价订单;
- 不控制用户资产,无法篡改价格或执行未授权交易;
- 仅具备非审查性(non-custodial)的订单管理权限。
-
链上结算:
- 所有成交通过 自定义 Exchange 合约 在 Polygon 上原子执行;
- 使用 EIP-712 签名 的结构化订单消息,确保可验证性和安全性;
- 支持 二元结果代币 (Outcome Tokens,基于 ERC-1155)与 抵押品(如 USDC,ERC-20)之间的交换。
✅ 关键特性:
- 非托管(Non-custodial):用户始终掌控私钥;
- 原子性(Atomic):成交即结算,无对手方风险;
- 统一订单簿:所有互补结果代币(如 "是/否")共享同一市场深度。
订单匹配规则:
- 每笔成交包含 1 个挂单方(Maker);
- 价格优于挂单价的部分收益归 吃单方(Taker),激励流动性提供。
API 能力:程序化交易接口
Polymarket 提供完整的 REST + WebSocket API,支持开发者:
- 创建、查询、取消限价订单;
- 获取全市场列表、实时价格、订单簿深度;
- 订阅订单状态变更、成交事件等实时数据。
适用于:
- 自动化做市商(Market Makers)
- 量化交易机器人
- 第三方交易平台集成(即 Builders)
安全保障
- 智能合约审计 :Exchange 合约已由 Chainsecurity 完成安全审计;
- 操作员权限受限 :
- 仅能排序和撮合订单;
- 不能设定价格 、不能挪用资金 、不能阻止用户撤单;
- 用户自主权 :即使对操作员失去信任,用户仍可通过链上直接调用合约取消未成交订单。
费用机制(Fees)
截至文档发布时,Polymarket 对所有交易实行 零基础费率:
| 交易量 | 挂单方费率(Maker) | 吃单方费率(Taker) |
|---|---|---|
| >0 USDC | 0 bps(0%) | 0 bps(0%) |
⚠️ 注:费率政策可能调整,以官网公告为准。
费用计算逻辑(对称设计)
尽管当前费率为 0,但系统设计支持未来按以下公式计费(以 baseRate 表示基础费率):
1. 卖出结果代币(Base → Quote)
math
fee_{Quote} = baseRate \times \min(price, 1 - price) \times size
- 以 抵押品(如 USDC) 收取费用;
price为结果代币的成交概率(0~1);min(price, 1−price)确保高波动市场(接近 0 或 1)收费更低。
2. 买入结果代币(Quote → Base)
math
fee_{Base} = baseRate \times \min(price, 1 - price) \times \frac{size}{price}
- 以 结果代币数量 收取费用;
- 同样受
min(price, 1−price)调节。
💡 设计目的:
- 费用对称,避免套利漏洞;
- 鼓励在"中间价格"(如 0.5)附近提供流动性;
- 保护极端行情下的交易者成本。
状态(Status)
快速入门(Quickstart)
⚠️ 注意:此快速入门使用 普通 EOA 钱包 (Externally Owned Account),需自行支付 Gas 费。如需实现 免 Gas 交易(Gasless Trading),需集成 Proxy 或 Safe 钱包 + Relayer,详见后续"完整示例"。
1. 安装依赖
TypeScript
bash
npm install @polymarket/clob-client ethers
Python
bash
pip install py-clob-client
2. 初始化 CLOB 客户端
首先创建一个临时客户端以派生用户专属的 CLOB API 凭据(用于 L2 认证),然后用这些凭据初始化正式交易客户端。
TypeScript
ts
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers"; // v5.8.0
const HOST = "https://clob.polymarket.com";
const CHAIN_ID = 137; // Polygon 主网
const signer = new Wallet(process.env.PRIVATE_KEY!);
// 步骤1: 派生 API 凭据
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
const apiCreds = await tempClient.createOrDeriveApiKey();
// 步骤2: 初始化正式客户端(signatureType = 0 表示 EOA 钱包)
const client = new ClobClient(
HOST,
CHAIN_ID,
signer,
apiCreds,
/* signatureType */ 0
);
Python
python
from py_clob_client.client import ClobClient
import os
import asyncio
async def setup_client():
host = "https://clob.polymarket.com"
chain_id = 137 # Polygon 主网
private_key = os.getenv("PRIVATE_KEY")
# 步骤1: 派生 API 凭据
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
api_creds = await temp_client.create_or_derive_api_key()
# 步骤2: 初始化正式客户端(signature_type = 0 表示 EOA 钱包)
client = ClobClient(
host,
chain_id=chain_id,
key=private_key,
creds=api_creds,
signature_type=0
)
return client
🔑 关键说明:
signatureType = 0:表示使用标准 EOA 钱包签名;- 若使用 Gnosis Safe (signatureType=2)或 Proxy 钱包(signatureType=1),需额外配置 Relayer;
- 钱包必须持有 USDC (用于交易)和 MATIC(用于支付 Gas)。
3. 下单(Place an Order)
使用 createAndPostOrder(TS)或 create_and_post_order(Python)一键创建并提交限价订单。
TypeScript
ts
import { Side } from "@polymarket/clob-client";
const response = await client.createAndPostOrder({
tokenID: "YOUR_TOKEN_ID", // 从 Gamma API 获取(如 "643948493284328")
price: 0.65, // 每股价格(概率值,0~1)
size: 10, // 股数
side: Side.BUY, // 或 Side.SELL
});
console.log(`✅ 订单已提交!ID: ${response.orderID}`);
Python
python
from py_clob_client.clob_types import OrderArgs
from py_clob_client.order_builder.constants import BUY
response = await client.create_and_post_order(
OrderArgs(
token_id="YOUR_TOKEN_ID", # 例如 "643948493284328"
price=0.65,
size=10,
side=BUY, # 或 "SELL"
)
)
print(f"✅ 订单已提交!ID: {response['orderID']}")
📌 注意 :
tokenID对应具体市场的某个结果代币(如 "特朗普胜选"),需通过 Gamma API 查询。
4. 查询订单与成交记录
TypeScript
ts
// 查询所有未成交订单
const openOrders = await client.getOpenOrders();
console.log(`📊 你有 ${openOrders.length} 个未成交订单`);
// 查询历史成交
const trades = await client.getTrades();
console.log(`📈 你已完成 ${trades.length} 笔交易`);
Python
python
# 查询所有未成交订单
open_orders = await client.get_open_orders()
print(f"📊 你有 {len(open_orders)} 个未成交订单")
# 查询历史成交
trades = await client.get_trades()
print(f"📈 你已完成 {len(trades)} 笔交易")
5. 完整可运行示例
TypeScript(完整脚本)
ts
import { ClobClient, Side } from "@polymarket/clob-client";
import { Wallet } from "ethers";
async function trade() {
const HOST = "https://clob.polymarket.com";
const CHAIN_ID = 137;
const signer = new Wallet(process.env.PRIVATE_KEY!);
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
const apiCreds = await tempClient.createOrDeriveApiKey();
const client = new ClobClient(HOST, CHAIN_ID, signer, apiCreds, 0);
const response = await client.createAndPostOrder({
tokenID: "YOUR_TOKEN_ID",
price: 0.65,
size: 10,
side: Side.BUY,
});
console.log(`✅ 订单成功!ID: ${response.orderID}`);
}
trade().catch(console.error);
Python(完整脚本)
python
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs
from py_clob_client.order_builder.constants import BUY
import asyncio
import os
async def trade():
host = "https://clob.polymarket.com"
chain_id = 137
private_key = os.getenv("PRIVATE_KEY")
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
creds = await temp_client.create_or_derive_api_key()
client = ClobClient(
host,
chain_id=chain_id,
key=private_key,
creds=creds,
signature_type=0
)
response = await client.create_and_post_order(
OrderArgs(
token_id="YOUR_TOKEN_ID",
price=0.65,
size=10,
side=BUY
)
)
print(f"✅ 订单成功!ID: {response['orderID']}")
if __name__ == "__main__":
asyncio.run(trade())
常见问题(Troubleshooting)
| 错误 | 原因 | 解决方案 |
|---|---|---|
L2_AUTH_NOT_AVAILABLE |
未正确派生 API 凭据 | 确保调用 createOrDeriveApiKey() |
Order rejected: insufficient balance |
钱包 USDC 余额不足 | 向钱包充值 USDC |
Order rejected: insufficient allowance |
未授权 Exchange 合约使用 USDC | 调用 approve 授权(或使用 Relayer 自动处理) |
后续步骤(Next Steps)
- 🔗 查找可交易市场 :使用 Gamma API 获取
tokenID; - 🧩 集成免 Gas 交易 :参考 Examples 中的 Privy/Magic/Turnkey + Safe 集成;
- 📡 实时监控:通过 WebSocket 订阅订单状态变更;
- 📘 深入认证机制:了解 L1(链上)与 L2(CLOB)双层认证流程;
- 📚 查阅完整 API :探索
ClobClient所有方法(取消订单、批量操作等)。
认证(Authentication)
双层认证架构概览
| 层级 | 名称 | 作用 | 是否必需 |
|---|---|---|---|
| L1 | 私钥认证(Private Key) | 证明用户对钱包的所有权,用于派生 L2 凭据、本地签名订单 | 首次初始化 L2 时必需 |
| L2 | API 凭据认证(API Key + Secret + Passphrase) | 用于日常交易操作(下单、查单、撤单等)的身份验证 | 执行私有操作时必需 |
✅ 公共数据(如市场行情、订单簿)无需任何认证即可访问。
L1 认证:基于私钥的链上身份证明
是什么?
- 使用用户的 Polygon 钱包私钥 对特定 EIP-712 结构化消息进行签名;
- 签名结果作为请求头(
POLY_SIGNATURE)提交给 CLOB; - 私钥永不离开用户设备,确保非托管(non-custodial)安全模型。
能做什么?
- 派生或创建用户的 L2 API 凭据;
- 在本地生成符合 CLOB 规范的 EIP-712 订单签名。
客户端实现(CLOB Client)
TypeScript
ts
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers";
const client = new ClobClient(
"https://clob.polymarket.com",
137, // Polygon
new Wallet(process.env.PRIVATE_KEY) // L1 signer
);
// 自动创建或派生 L2 凭据
const apiCreds = await client.createOrDeriveApiKey();
/*
返回:
{
apiKey: "uuid...",
secret: "base64...",
passphrase: "random..."
}
*/
Python
python
from py_clob_client.client import ClobClient
import os
client = ClobClient(
host="https://clob.polymarket.com",
key=os.getenv("PRIVATE_KEY"),
chain_id=137
)
api_creds = await client.create_or_derive_api_key()
🔒 安全提示:私钥绝不可硬编码或提交至代码仓库,应使用环境变量或密钥管理服务。
直接调用 REST API(不推荐,仅高级用户)
需在请求头中包含以下字段:
| Header | 必填 | 说明 |
|---|---|---|
POLY_ADDRESS |
✅ | 用户 Polygon 地址 |
POLY_SIGNATURE |
✅ | 对 EIP-712 消息的签名 |
POLY_TIMESTAMP |
✅ | 当前 Unix 时间戳(秒) |
POLY_NONCE |
✅ | 默认为 0,用于防重放 |
相关端点:
POST /auth/api-key→ 创建新凭据GET /auth/derive-api-key→ 派生已有凭据
L2 认证:基于 API 凭据的高效交易授权
是什么?
- 使用 L1 派生出的三元组:
apiKey、secret、passphrase; - 每次请求通过 HMAC-SHA256 算法对请求内容签名;
- 用于验证用户身份,执行私有操作。
能做什么?
- 提交已签名的订单;
- 查询/取消自己的未成交订单;
- 查看余额与授权状态(allowance)。
客户端实现(带 L2 凭据)
TypeScript
ts
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer, // 仍需 signer 用于订单本地签名
apiCreds, // L2 凭据
signatureType, // 钱包类型(见下文)
funderAddress // 资金来源地址
);
// 现在可执行交易
await client.createAndPostOrder({ ... });
Python
python
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=private_key,
creds=api_creds,
signature_type=signature_type,
funder=funder_address
)
⚠️ 重要 :即使使用 L2 认证,订单本身仍需用户私钥签名(EIP-712),L2 仅用于 API 请求身份验证。
直接调用 REST API(L2 头部)
| Header | 必填 | 说明 |
|---|---|---|
POLY_ADDRESS |
✅ | 用户地址 |
POLY_API_KEY |
✅ | API Key |
POLY_PASSPHRASE |
✅ | Passphrase |
POLY_SIGNATURE |
✅ | HMAC-SHA256 签名(基于 secret) |
POLY_TIMESTAMP |
✅ | 时间戳 |
签名算法参考官方 SDK 实现。
签名类型(Signature Types)与资金方(Funder)
在初始化 L2 客户端时,必须指定 signatureType 和 funder 地址,以匹配用户的钱包类型:
| 类型 | 值 | 说明 | Funder 地址 |
|---|---|---|---|
| EOA | 0 |
标准钱包(如 MetaMask) | 钱包自身地址(需有 MATIC 支付 Gas) |
| POLY_PROXY | 1 |
Polymarket Magic 用户的代理钱包 | 从 Polymarket.com 导出的代理地址 |
| GNOSIS_SAFE | 2 |
Gnosis Safe 多签钱包(最常用) | Safe 合约地址(由 Relayer 代付 Gas) |
💡 Builder 推荐 :新项目应默认使用 Gnosis Safe (
signatureType=2),配合 Relayer 实现免 Gas 交易。
常见问题(Troubleshooting)
| 错误 | 可能原因 | 解决方案 |
|---|---|---|
INVALID_SIGNATURE |
签名错误或时间戳过期 | 检查私钥、时间同步、nonce |
NONCE_ALREADY_USED |
nonce 重复使用 | 增加 nonce 值(L1 场景) |
Invalid Funder Address |
funder 与 signatureType 不匹配 | 确保 funder 是对应钱包的实际地址 |
| 丢失 API 凭据 | --- | 若保留 nonce,可通过 /derive-api-key 恢复;否则需重新创建 |
方法分类(Client Methods)
| 类别 | 功能 | 是否需要认证 |
|---|---|---|
| Public Methods | 获取市场数据、订单簿、价格 | ❌ 否 |
| L1 Methods | 创建/派生 API 凭据 | ✅ L1(私钥) |
| L2 Methods | 下单、查单、撤单、查余额 | ✅ L2(API 凭据)+ 订单需私钥签名 |
| Builder Program Methods | Builder 归属、Relayer 集成 | ✅ 特定权限 |
地理限制(Geographic Restrictions)
概述(Overview)
- Polymarket 禁止来自特定国家/地区的用户提交订单;
- 若请求 IP 属于受限区域,CLOB 将直接拒绝订单;
- 建议在前端或后端提前调用 Geoblock 接口,向用户提供友好提示(如"您所在地区暂不支持交易"),提升用户体验。
受限区域列表
🚫 完全禁止的国家(33 个)
| 国家代码 | 国家名称 |
|---|---|
| AU | 澳大利亚 |
| BE | 比利时 |
| BY | 白俄罗斯 |
| BI | 布隆迪 |
| CF | 中非共和国 |
| CD | 刚果(金) |
| CU | 古巴 |
| DE | 德国 |
| ET | 埃塞俄比亚 |
| FR | 法国 |
| GB | 英国 |
| IR | 伊朗 |
| IQ | 伊拉克 |
| IT | 意大利 |
| KP | 朝鲜 |
| LB | 黎巴嫩 |
| LY | 利比亚 |
| MM | 缅甸 |
| NI | 尼加拉瓜 |
| PL | 波兰 |
| RU | 俄罗斯 |
| SG | 新加坡 |
| SO | 索马里 |
| SS | 南苏丹 |
| SD | 苏丹 |
| SY | 叙利亚 |
| TH | 泰国 |
| TW | 台湾 |
| UM | 美国本土外小岛屿 |
| US | 美国 |
| VE | 委内瑞拉 |
| YE | 也门 |
| ZW | 津巴布韦 |
💡 注意:包括 美国 (US) 和 新加坡(SG) 等主要司法管辖区均在禁止之列。
🚫 部分禁止的地区(即使国家未完全禁止)
| 国家 | 受限地区 | 地区代码 |
|---|---|---|
| 加拿大(CA) | 安大略省 | ON |
| 乌克兰(UA) | 克里米亚 | 43 |
| 乌克兰(UA) | 顿涅茨克州 | 14 |
| 乌克兰(UA) | 卢甘斯克州 | 09 |
地理检测接口(Geoblock Endpoint)
请求方式
http
GET https://polymarket.com/api/geoblock
响应格式(JSON)
json
{
"blocked": true,
"ip": "47.246.164.134",
"country": "SG",
"region": ""
}
字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
blocked |
boolean | 是否被禁止交易(true = 禁止) |
ip |
string | 服务器检测到的客户端 IP 地址 |
country |
string | ISO 3166-1 alpha-2 国家代码(如 "US", "SG") |
region |
string | 地区/州代码(如 "ON" 表示安大略省),若无则为空字符串 |
使用示例(含 TypeScript 与 Python)
✅ TypeScript 示例
ts
interface GeoblockResponse {
blocked: boolean;
ip: string;
country: string;
region: string;
}
async function checkGeoblock(): Promise<GeoblockResponse> {
const response = await fetch("https://polymarket.com/api/geoblock");
if (!response.ok) {
throw new Error("Failed to check geoblock status");
}
return response.json();
}
// 使用示例
(async () => {
try {
const geo = await checkGeoblock();
if (geo.blocked) {
console.log(`❌ 交易不可用:您所在的国家 ${geo.country} 已被限制`);
// 在 UI 中显示提示,阻止用户进入交易流程
} else {
console.log("✅ 交易可用,可继续操作");
// 初始化 CLOB 客户端并允许交易
}
} catch (error) {
console.error("地理检测失败:", error);
// 可选择默认允许或谨慎处理
}
})();
✅ Python 示例
python
import requests
def check_geoblock() -> dict:
response = requests.get("https://polymarket.com/api/geoblock")
response.raise_for_status() # 抛出 HTTP 错误
return response.json()
# 使用示例
if __name__ == "__main__":
try:
geo = check_geoblock()
if geo["blocked"]:
print(f'❌ 交易不可用:您所在的国家 {geo["country"]} 已被限制')
# 返回错误信息给前端,或终止交易流程
else:
print("✅ 交易可用,可继续操作")
# 继续初始化 CLOB 客户端
except requests.RequestException as e:
print(f"地理检测失败: {e}")
# 根据业务逻辑决定是否降级处理
服务器基础设施提示
- 主服务器区域 :
eu-west-2(伦敦) - 最近的非受限区域 :
eu-west-1(爱尔兰)
⚠️ 即使你的应用部署在非受限区域,用户的实际 IP 才是判断依据 。因此必须通过
geoblock接口检测最终用户位置,而非服务器位置。
客户端
公共方法(Public Methods)
客户端初始化(无需认证)
要使用公共方法,只需初始化 ClobClient 并传入 CLOB 主机地址 和 Polygon 链 ID(137)。
✅ TypeScript 示例
ts
import { ClobClient } from "@polymarket/clob-client";
const client = new ClobClient(
"https://clob.polymarket.com", // CLOB 主机
137 // Polygon 主网链 ID
);
// 现在可以调用任意公共方法
const markets = await client.getMarkets();
console.log("Market count:", markets.data.length);
✅ Python 示例
python
from py_clob_client.client import ClobClient
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137
)
# 调用公共方法
markets = await client.get_markets()
print(f"Market count: {markets['count']}")
⚠️ 注意:不要传入
signer或api_creds,否则会启用 L1/L2 认证逻辑,但对公共方法非必需。
方法分类与功能概览
🔧 健康检查
getOk():验证 CLOB 服务是否正常运行。
📊 市场数据(Markets)
| 方法 | 说明 |
|---|---|
getMarket(conditionId) |
获取单个市场的完整详情 |
getMarkets() |
分页获取多个市场的完整数据 |
getSimplifiedMarkets() |
获取简化版市场数据(加载更快) |
getSamplingMarkets() / getSamplingSimplifiedMarkets() |
获取用于抽样或测试的市场数据 |
简化市场 (Simplified)仅包含核心字段(如
condition_id,tokens,accepting_orders),适合首页列表等高性能场景。
📈 订单簿与价格(Order Books & Prices)
| 方法 | 功能 |
|---|---|
getOrderBook(tokenID) |
获取指定 token 的完整订单簿(bids/asks) |
getOrderBooks([{token_id, side}]) |
批量获取多个 token 的订单簿 |
getPrice(tokenID, side) |
获取最佳买价(BUY)或卖价(SELL) |
getPrices([...]) |
批量获取多个 token 的最佳价格 |
getMidpoint(tokenID) |
获取买卖中间价((bestBid + bestAsk) / 2) |
getSpread(tokenID) |
获取买卖价差(bestAsk - bestBid) |
calculateMarketPrice(tokenID, side, amount, orderType) |
模拟以指定数量成交的预期价格(支持 FOK/GTC 等类型) |
getPricesHistory(...) |
获取历史价格 K 线数据(支持 1h/1d/1w/max 等粒度) |
示例:获取订单簿(TS + Python)
ts
// TypeScript
const book = await client.getOrderBook("123456");
console.log("Best bid:", book.bids[0]?.price);
console.log("Best ask:", book.asks[0]?.price);
python
# Python
book = await client.get_order_book("123456")
print("Best bid:", book["bids"][0]["price"] if book["bids"] else None)
print("Best ask:", book["asks"][0]["price"] if book["asks"] else None)
💹 交易数据(Trades)
| 方法 | 功能 |
|---|---|
getLastTradePrice(tokenID) |
获取某 token 最近一笔成交价格和方向 |
getLastTradesPrices([...]) |
批量获取多个 token 的最近成交价 |
getMarketTradesEvents(conditionID) |
获取某市场的完整交易事件流(含用户、手续费、交易哈希等) |
示例:获取最近成交价
ts
const last = await client.getLastTradePrice("123456");
console.log(`Last trade: ${last.price} (${last.side})`);
python
last = await client.get_last_trade_price("123456")
print(f"Last trade: {last['price']} ({last['side']})")
⚙️ 市场参数(Market Parameters)
| 方法 | 返回值 | 说明 |
|---|---|---|
getFeeRateBps(tokenID) |
number |
交易手续费(单位:基点,bps) |
getTickSize(tokenID) |
`"0.1" | "0.01" |
getNegRisk(tokenID) |
boolean |
是否为"负风险"市场(即互补二元期权) |
🕒 时间与服务器信息
getServerTime():返回 CLOB 服务器当前 Unix 时间戳(秒),用于同步本地时间、防止签名过期等。
ts
const serverTime = await client.getServerTime();
console.log("Server time:", new Date(serverTime * 1000));
python
server_time = await client.get_server_time()
print("Server time:", server_time)
数据结构关键说明
Market Token 结构
ts
interface MarketToken {
outcome: string; // 如 "Yes", "No"
price: number; // 当前市场价格(0~1)
token_id: string; // 唯一 token ID(用于下单)
winner: boolean; // 结算后是否为胜出结果
}
OrderBookSummary
bids/asks:按价格排序的订单列表;tick_size:价格精度(如 "0.01" 表示最小变动 0.01);min_order_size:最小下单数量;neg_risk:是否为负风险市场(影响订单构造逻辑)。
L1 方法(L1 Methods)
客户端初始化(需提供私钥)
要使用 L1 方法,必须在初始化 ClobClient 时传入一个 Ethers.js Wallet 实例 (TypeScript)或 私钥字符串(Python)。
🔒 安全警告:私钥绝不可硬编码或提交至 Git!务必使用环境变量或密钥管理服务。
✅ TypeScript 示例
ts
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers"; // v5.8.0
// 从环境变量加载私钥
const signer = new Wallet(process.env.PRIVATE_KEY!);
const client = new ClobClient(
"https://clob.polymarket.com", // CLOB 主机
137, // Polygon 链 ID
signer // 必须提供 signer 才能调用 L1 方法
);
// 现在可以创建 API 凭据
const creds = await client.createOrDeriveApiKey();
console.log("API Key:", creds.apiKey);
✅ Python 示例
python
from py_clob_client.client import ClobClient
import os
# 从环境变量加载私钥
private_key = os.getenv("PRIVATE_KEY")
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=private_key # 必须提供私钥才能调用 L1 方法
)
# 创建或派生 API 凭据
creds = await client.create_or_derive_api_key()
print("API Key:", creds["apiKey"])
API 凭据管理(用于后续 L2 认证)
每个钱包地址只能拥有一个活跃的 API 凭据集。新凭据会自动使旧凭据失效。
| 方法 | 功能 | 推荐场景 |
|---|---|---|
createApiKey(nonce?) |
强制创建新凭据,旧凭据立即失效 | 明确需要轮换密钥 |
deriveApiKey(nonce?) |
根据 nonce 派生已有凭据(若存在) | 已知 nonce 且想恢复凭据 |
createOrDeriveApiKey(nonce?) |
先尝试派生,失败则创建 | ✅ 推荐用于首次初始化 |
返回结构(TS & Python 相同)
json
{
"apiKey": "uuid-v4-string",
"secret": "base64-encoded-secret",
"passphrase": "random-string"
}
💡 这三个字段将用于后续的 L2 认证(见 L2 Methods 文档)。
示例:安全初始化凭据
ts
// TypeScript
const creds = await client.createOrDeriveApiKey(); // 默认 nonce = 0
// 保存 creds 到安全存储(如加密数据库)
python
# Python
creds = await client.create_or_derive_api_key() # 默认 nonce = 0
# 保存 creds 到安全存储
⚠️ 如果你自定义了
nonce(如用于多设备同步),请务必妥善保管该 nonce,否则可能无法恢复凭据。
本地订单签名(不提交到 CLOB)
L1 方法允许你在完全离线或自定义逻辑下生成已签名的订单 ,后续可通过 L2 方法(如 postOrder)提交。
1. 创建限价单(createOrder)
TypeScript
ts
const signedOrder = await client.createOrder(
{
tokenID: "123456",
price: 0.65, // 价格(0~1)
size: 100, // 数量(shares)
side: "BUY", // 或 "SELL"
feeRateBps: 10, // 可选:手续费率(基点)
nonce: Date.now(), // 可选:防重放 nonce
},
{
tickSize: "0.01", // 必须匹配市场最小变动单位
negRisk: false, // 是否为负风险市场
}
);
console.log("Signed order:", signedOrder.signature);
Python
python
signed_order = await client.create_order(
user_order={
"tokenID": "123456",
"price": 0.65,
"size": 100,
"side": "BUY",
"feeRateBps": 10,
"nonce": int(time.time()),
},
options={
"tickSize": "0.01",
"negRisk": False,
}
)
print("Signature:", signed_order["signature"])
2. 创建市价单(createMarketOrder)
市价单按金额 (BUY)或份额数量 (SELL)下单,并可设置价格上限/下限作为保护。
TypeScript
ts
const signedMarketOrder = await client.createMarketOrder(
{
tokenID: "123456",
amount: 50, // BUY: 花 $50;SELL: 卖 50 shares
side: "BUY",
price: 0.70, // 最高接受价格(可选)
orderType: "FOK", // Fill-or-Kill(默认)
},
{
tickSize: "0.01",
negRisk: false,
}
);
Python
python
signed_market_order = await client.create_market_order(
user_market_order={
"tokenID": "123456",
"amount": 50,
"side": "BUY",
"price": 0.70,
"orderType": "FOK",
},
options={
"tickSize": "0.01",
"negRisk": False,
}
)
返回的已签名订单结构(SignedOrder)
无论限价单还是市价单,返回的 SignedOrder 包含以下关键字段:
| 字段 | 类型 | 说明 |
|---|---|---|
signature |
string | EIP-712 签名(十六进制) |
maker / signer |
string | 下单人地址(即 signer 地址) |
tokenId |
string | 目标 token ID |
side |
number | 0 = BUY, 1 = SELL |
makerAmount / takerAmount |
string | 根据 side 计算的金额(单位:wei) |
expiration |
string | Unix 时间戳(秒) |
nonce |
string | 防重放随机数 |
signatureType |
number | 钱包类型(0=EOA, 1=Proxy, 2=Gnosis Safe) |
📌 此结构可直接传递给 L2 方法
postOrder(signedOrder)提交到 CLOB。
常见问题(Troubleshooting)
| 错误 | 原因 | 解决方案 |
|---|---|---|
INVALID_SIGNATURE |
签名无效或链 ID 不匹配 | 检查私钥、chain_id=137、EIP-712 域哈希 |
NONCE_ALREADY_USED |
nonce 重复 | 使用更高 nonce(如时间戳) |
Invalid Funder Address |
funder 与 signatureType 不符 | 初始化 L2 客户端时正确设置 funder |
| 丢失 API 凭据 | --- | 若记得 nonce,用 deriveApiKey(nonce) 恢复 |
| 丢失凭据 + nonce | --- | 调用 createApiKey() 生成新凭据(旧凭据作废) |
L2 方法(L2 Methods)
这部分详细介绍了 Polymarket 中央限价订单簿 (CLOB)中需要 用户 API 凭据 (L2 headers) 的方法,统称为 L2 方法。这些方法用于:
- 提交和管理真实交易订单(下单、撤单、批量操作);
- 查询用户持仓、成交记录、余额与授权;
- 管理通知与 API 密钥。
L2 方法是用户与 CLOB 进行实际交易交互的核心层,依赖于 L1 方法生成的 API 凭据进行身份认证,同时仍需私钥签名以确保非托管安全性。
客户端初始化(需完整 L2 上下文)
要使用 L2 方法,ClobClient 初始化必须提供以下 5 项:
| 参数 | 说明 |
|---|---|
host |
CLOB 主机地址(如 https://clob.polymarket.com) |
chain_id |
链 ID(Polygon 主网为 137) |
signer / key |
钱包私钥(用于本地签名) |
apiCreds / creds |
L2 API 凭据(由 L1 方法生成) |
signatureType |
签名类型(0=EOA, 1=Proxy, 2=Gnosis Safe) |
funder |
资金来源地址(对 Gnosis Safe 等代理钱包必需) |
🔐 安全提示:API 凭据和私钥都应通过环境变量加载,禁止硬编码!
✅ TypeScript 示例
ts
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers";
const signer = new Wallet(process.env.PRIVATE_KEY!);
const apiCreds = {
apiKey: process.env.API_KEY!,
secret: process.env.SECRET!,
passphrase: process.env.PASSPHRASE!,
};
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds,
2, // signatureType: 2 = Gnosis Safe
process.env.FUNDER_ADDRESS // funder 地址(Safe 代理地址)
);
// 现在可以提交订单
const orderResp = await client.postOrder(signedOrder);
console.log("Order ID:", orderResp.orderID);
✅ Python 示例
python
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds
import os
api_creds = ApiCreds(
api_key=os.getenv("API_KEY"),
api_secret=os.getenv("SECRET"),
api_passphrase=os.getenv("PASSPHRASE")
)
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=api_creds,
signature_type=2, # Gnosis Safe
funder=os.getenv("FUNDER_ADDRESS")
)
# 提交已签名订单
order_resp = await client.post_order(signed_order)
print("Order ID:", order_resp["orderID"])
💡
signatureType和funder对普通 EOA 钱包可省略或设为0和None;但对 Gnosis Safe 等智能合约钱包必须正确设置。
订单创建与管理
1. 便捷下单(自动签名 + 提交)
适用于简单场景,无需手动处理签名。
限价单:createAndPostOrder
ts
// TypeScript
const resp = await client.createAndPostOrder(
{
tokenID: "123456",
price: 0.65,
size: 100,
side: "BUY"
},
{ tickSize: "0.01" },
"GTC" // Good Till Cancelled
);
python
# Python
resp = await client.create_and_post_order(
user_order={
"tokenID": "123456",
"price": 0.65,
"size": 100,
"side": "BUY"
},
options={"tickSize": "0.01"},
order_type="GTC"
)
市价单:createAndPostMarketOrder
ts
// TypeScript
const resp = await client.createAndPostMarketOrder(
{
tokenID: "123456",
amount: 50, // $50 worth (BUY) or 50 shares (SELL)
side: "BUY"
},
{ tickSize: "0.01" },
"FOK" // Fill-or-Kill
);
python
# Python
resp = await client.create_and_post_market_order(
user_market_order={
"tokenID": "123456",
"amount": 50,
"side": "BUY"
},
options={"tickSize": "0.01"},
order_type="FOK"
)
2. 手动提交已签名订单
适用于高级场景(如批量生成、离线签名、自定义 nonce)。
单笔提交:postOrder
ts
// signedOrder 来自 L1 的 createOrder()
const resp = await client.postOrder(signedOrder, "GTC");
python
resp = await client.post_order(signed_order, order_type="GTC")
批量提交(最多 15 笔):postOrders
ts
// TypeScript
const batch = [
{ order: signedOrder1, orderType: "GTC" },
{ order: signedOrder2, orderType: "FOK" }
];
const responses = await client.postOrders(batch);
python
# Python
batch = [
{"order": signed_order1, "orderType": "GTC"},
{"order": signed_order2, "orderType": "FOK"}
]
responses = await client.post_orders(batch)
3. 撤单操作
| 方法 | 功能 |
|---|---|
cancelOrder(orderID) |
撤销单笔订单 |
cancelOrders([id1, id2]) |
批量撤销 |
cancelAll() |
撤销所有未成交订单 |
cancelMarketOrders({market: "cond-id"}) |
撤销某市场所有订单 |
ts
await client.cancelOrder("ord_abc123");
await client.cancelAll();
python
await client.cancel_order("ord_abc123")
await client.cancel_all()
查询订单与成交
获取订单详情
ts
const order = await client.getOrder("ord_abc123");
console.log("Status:", order.status); // e.g., "OPEN", "FILLED"
python
order = await client.get_order("ord_abc123")
print("Status:", order["status"])
获取所有未成交订单
ts
const openOrders = await client.getOpenOrders({ market: "cond-id" });
python
open_orders = await client.get_open_orders(params={"market": "cond-id"})
获取成交历史
ts
const trades = await client.getTrades({ asset_id: "123456" });
const paginated = await client.getTradesPaginated({ after: "2025-01-01T00:00:00Z" });
python
trades = await client.get_trades(params={"asset_id": "123456"})
paginated = await client.get_trades_paginated(params={"after": "2025-01-01T00:00:00Z"})
余额与授权(Balance & Allowance)
Polymarket 使用 USDC 作为抵押品,条件 token 代表预测结果。
ts
// 获取 USDC 余额与授权
const collateral = await client.getBalanceAllowance({ asset_type: "COLLATERAL" });
// 获取某条件 token 余额
const conditional = await client.getBalanceAllowance({
asset_type: "CONDITIONAL",
token_id: "123456"
});
// 强制刷新缓存(如刚完成 approve)
await client.updateBalanceAllowance({ asset_type: "COLLATERAL" });
python
collateral = await client.get_balance_allowance({"asset_type": "COLLATERAL"})
conditional = await client.get_balance_allowance({
"asset_type": "CONDITIONAL",
"token_id": "123456"
})
await client.update_balance_allowance({"asset_type": "COLLATERAL"})
API 密钥管理(L2 层)
ts
// 查看当前账户所有 API 密钥(通常只有 1 个)
const keys = await client.getApiKeys();
// 删除(吊销)当前 API 密钥
await client.deleteApiKey();
python
keys = await client.get_api_keys()
await client.delete_api_key()
⚠️ 删除后需重新调用 L1 的
createApiKey()生成新凭据。
通知系统(Notifications)
CLOB 会推送关键事件通知(48 小时后自动清除)。
| 类型值 | 事件 |
|---|---|
| 1 | 订单被取消 |
| 2 | 订单成交(作为 maker 或 taker) |
| 4 | 市场已结算 |
ts
const notifications = await client.getNotifications();
console.log(notifications[0].type); // e.g., 2
// 标记为已读(清除)
await client.dropNotifications({ ids: ["1", "2"] });
python
notifications = await client.get_notifications()
print(notifications[0]["type"]) # e.g., 2
await client.drop_notifications({"ids": ["1", "2"]})
返回结构示例:OrderResponse
所有下单方法返回统一结构:
json
{
"success": true,
"errorMsg": "",
"orderID": "ord_xyz789",
"transactionsHashes": ["0x..."],
"status": "OPEN",
"takingAmount": "65000000", // 卖出金额(wei)
"makingAmount": "100000000" // 买入份额(wei)
}
💡 金额单位为 wei (1 USDC = 1e6 wei),需除以
1e6转换为美元。
REST API
Orderbook
Get order book summary
这是一个 无需认证(Public Method) 的只读接口,主要用于:
- 获取特定预测市场 token 的实时买卖盘深度(bids/asks);
- 了解该市场的交易规则(如最小下单量、价格精度);
- 获取订单簿的唯一状态标识(hash)和时间戳,用于校验或同步。
🔍 接口详情
- HTTP 方法 :
GET - 端点路径 :
/book - 完整 URL 示例 :
https://clob.polymarket.com/book?token_id=1234567890
📥 请求参数(Query Parameters)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
token_id |
string | ✅ 是 | 目标 token 的唯一 ID(通常是条件结果 token 的 ID,如 "1234567890") |
⚠️ 如果未提供
token_id或格式无效,会返回400 Bad Request。如果该
token_id对应的市场不存在或无订单簿,返回404 Not Found。
📤 成功响应(200 OK)
返回一个 JSON 对象,包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
market |
string | 市场的唯一标识符(通常是条件合约地址的哈希) |
asset_id |
string | 与请求一致的 token ID |
timestamp |
string (ISO 8601) | 订单簿快照生成的时间 |
hash |
string | 该订单簿状态的唯一哈希值(可用于验证一致性) |
bids |
array of { price, size } |
买盘(bid)列表,按价格从高到低排序 |
asks |
array of { price, size } |
卖盘(ask)列表,按价格从低到高排序 |
min_order_size |
string | 该市场允许的最小下单数量(单位:shares) |
tick_size |
string | 价格的最小变动单位(如 "0.01" 表示价格只能是 0.01 的整数倍) |
neg_risk |
boolean | 是否启用"负风险"模式(影响结算逻辑) |
💡 示例响应:
json
{
"market": "0x1b6f76e5b8587ee896c35847e12d11e75290a8c3934c5952e8a9d6e4c6f03cfa",
"asset_id": "1234567890",
"timestamp": "2023-10-01T12:00:00Z",
"hash": "0xabc123def456...",
"bids": [
{ "price": "0.65", "size": "100" },
{ "price": "0.64", "size": "250" }
],
"asks": [
{ "price": "0.66", "size": "80" },
{ "price": "0.67", "size": "120" }
],
"min_order_size": "0.001",
"tick_size": "0.01",
"neg_risk": false
}
📌 注意:
price范围为0.00到1.00(代表事件发生的概率或份额价格);size单位是 shares(不是美元);- 所有数值以 字符串形式返回,避免浮点精度问题。
❌ 错误响应
| 状态码 | 响应体 | 原因 |
|---|---|---|
400 |
{ "error": "Invalid token id" } |
token_id 缺失、格式错误或非数字 |
404 |
{ "error": "No orderbook exists for the requested token id" } |
该 token 尚未创建市场或无流动性 |
500 |
{ "error": "error getting the orderbook" } |
服务端内部错误(如数据库故障) |
Get multiple order books summaries by request
🔍 接口详情
- HTTP 方法 :
POST - 端点路径 :
/books - 完整 URL :
https://clob.polymarket.com/books - 请求体格式 :
application/json
📥 请求体(Body)
请求体是一个 JSON 数组,每个元素是一个对象,包含以下字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
token_id |
string | ✅ 是 | token 的唯一 ID(如 "1234567890") |
side |
enum ("BUY" 或 "SELL") |
❌ 否 | 可选参数,某些内部操作可能用到,但对标准订单簿查询通常可忽略 |
⚠️ 数组长度 最大为 500。超过将被拒绝或截断。
✅ 示例请求体:
json
[
{ "token_id": "1234567890" },
{ "token_id": "9876543210" },
{ "token_id": "1122334455", "side": "BUY" }
]
💡 实际使用中,
side参数在当前公开文档中未明确影响返回结果(bids 和 asks 仍会完整返回),可能是为未来功能预留。
📤 成功响应(200 OK)
返回一个 JSON 数组 ,每个元素对应一个 token_id 的完整订单簿摘要,结构与单个 /book 接口完全一致:
| 字段 | 说明 |
|---|---|
market |
市场唯一标识(条件合约哈希) |
asset_id |
对应的 token ID |
timestamp |
快照时间(ISO 8601) |
hash |
订单簿状态哈希(用于一致性校验) |
bids |
买盘列表(按价格降序) |
asks |
卖盘列表(按价格升序) |
min_order_size |
最小下单数量(shares) |
tick_size |
价格最小变动单位(如 "0.01") |
neg_risk |
是否启用负风险模式 |
✅ 示例响应:
json
[
{
"market": "0x...a",
"asset_id": "1234567890",
"timestamp": "2026-01-05T19:00:00Z",
"hash": "0xabc...",
"bids": [{ "price": "0.65", "size": "100" }],
"asks": [{ "price": "0.66", "size": "80" }],
"min_order_size": "0.001",
"tick_size": "0.01",
"neg_risk": false
},
{
"market": "0x...b",
"asset_id": "9876543210",
"timestamp": "2026-01-05T19:00:00Z",
"hash": "0xdef...",
"bids": [{ "price": "0.42", "size": "200" }],
"asks": [{ "price": "0.43", "size": "150" }],
"min_order_size": "0.001",
"tick_size": "0.01",
"neg_risk": false
}
]
📌 注意:
- 返回数组顺序 不一定 与请求顺序一致,应通过
asset_id匹配;- 如果某个
token_id无效或无订单簿,该 token 的结果可能缺失或返回空 bids/asks(具体行为需实测,文档未明确说明错误处理);- 所有数值仍以 字符串形式 返回,避免精度问题。
price
Get market price
🔍 接口详情
- HTTP 方法 :
GET - 端点路径 :
/price - 完整示例 URL :
https://clob.polymarket.com/price?token_id=1234567890&side=BUY
📥 请求参数(Query Parameters)
| 参数 | 类型 | 必填 | 可选值 | 说明 |
|---|---|---|---|---|
token_id |
string | ✅ 是 | --- | 目标 token 的唯一 ID(如 "1234567890") |
side |
enum | ✅ 是 | "BUY", "SELL" |
查询方向: • BUY → 获取最高买价 (best bid) • SELL → 获取最低卖价(best ask) |
⚠️ 如果缺少任一参数,或
side不是BUY/SELL,将返回错误(如400 Bad Request)。
📤 成功响应(200 OK)
返回一个简单的 JSON 对象:
json
{
"price": "0.65"
}
price:字符串类型,表示当前市场在该方向上的最优价格 。- 范围通常为
"0.00"到"1.00"(代表事件发生的概率或份额价格); - 使用字符串是为了避免浮点数精度丢失 (例如 JavaScript 中
0.1 + 0.2 ≠ 0.3的问题)。
- 范围通常为
💡 示例:
side=BUY→ 返回bids[0].price(最高买价)side=SELL→ 返回asks[0].price(最低卖价)
✅ 示例:获取买卖价差
python
import requests
token = "1234567890"
bid = requests.get(f"https://clob.polymarket.com/price?token_id={token}&side=BUY").json()["price"]
ask = requests.get(f"https://clob.polymarket.com/price?token_id={token}&side=SELL").json()["price"]
print(f"Spread: {float(ask) - float(bid):.4f}") # e.g., 0.0100
Get multiple market prices
这部分内容描述了 Polymarket CLOB(中央限价订单簿)提供的一个 公开、批量行情接口 :一次性获取多个 token 在买卖两个方向上的最优市场价格。
与前面的 /price(单个 token + 单个方向)不同,GET /prices 是一个 聚合型轻量接口 ,无需参数即可返回所有活跃 token 的当前最优买价和卖价,非常适合需要全局行情概览的场景。
🔍 接口详情
- HTTP 方法 :
GET - 端点路径 :
/prices - 完整 URL :
https://clob.polymarket.com/prices - 认证要求:❌ 无需认证(Public Method)
- 请求参数:无(不接受 query 参数)
✅ 调用极其简单:直接 GET 即可。
📤 成功响应(200 OK)
返回一个 JSON 对象,结构为:
json
{
"<token_id>": {
"BUY": "<best_bid_price>",
"SELL": "<best_ask_price>"
},
...
}
字段说明:
- 外层 key :token 的唯一 ID(如
"1234567890"); - 内层对象 :
"BUY":该 token 当前最高买价(best bid);"SELL":该 token 当前最低卖价(best ask);
- 所有价格均为 字符串类型,以保持精度(避免浮点误差)。
✅ 示例响应:
json
{
"1234567890": {
"BUY": "0.65",
"SELL": "0.66"
},
"0987654321": {
"BUY": "0.42",
"SELL": "0.43"
}
}
💡 注意:价格范围通常在
"0.00"到"1.00"之间(代表预测市场结果的概率或份额价格)。
python
import requests
url = "https://clob.polymarket.com/prices"
response = requests.get(url)
print(response.text)
这部分内容描述了 Polymarket CLOB(中央限价订单簿)提供的一个 公开、按需批量查询市场价格的接口 :
POST /prices ------ 根据客户端指定的 token 列表和交易方向,返回对应的最优市场价格。
与前面无参数的 GET /prices(返回所有活跃市场的价格)不同,这个接口允许你精确指定要查询哪些 token 和方向,适用于只关注特定市场子集的场景,避免获取不必要的数据。
Get multiple market prices by request
🔍 接口概览
- HTTP 方法 :
POST - 端点路径 :
/prices - 请求体格式 :
application/json - 认证要求:❌ 无需认证(Public Method)
- 最大请求数量 :一次最多支持 500 个查询项
📥 请求体结构(Body)
请求体是一个 JSON 数组,每个元素包含两个必填字段:
| 字段 | 类型 | 必填 | 可选值 | 说明 |
|---|---|---|---|---|
token_id |
string | ✅ 是 | 如 "1234567890" |
目标 token 的唯一 ID |
side |
enum | ✅ 是 | "BUY", "SELL" |
查询方向 |
💡 注意:虽然你在请求中指定了
side(如只查BUY),但响应中会返回该 token 的完整 BUY + SELL 价格(见下方说明)。
✅ 示例请求体:
json
[
{ "token_id": "1234567890", "side": "BUY" },
{ "token_id": "0987654321", "side": "SELL" }
]
📤 响应结构(200 OK)
返回一个 JSON 对象 ,以 token_id 为 key,每个 value 包含该 token 的 完整买卖价格(即使你只请求了一个方向):
json
{
"1234567890": {
"BUY": "0.65",
"SELL": "0.66"
},
"0987654321": {
"BUY": "0.42",
"SELL": "0.43"
}
}
⚠️ 重要行为说明:
- 即使你只请求
{token_id: "X", side: "BUY"},响应中仍会包含"X"的 BUY 和 SELL 两个价格。- 这意味着:
side字段在当前实现中可能仅用于内部路由或未来扩展,不影响返回字段。- 因此,你可以理解为:只要某个
token_id出现在请求中,就会返回它的完整双边报价。
💻 代码示例
✅ Python 示例(使用 requests)
python
import requests
url = "https://clob.polymarket.com/prices"
payload = [
{"token_id": "1234567890", "side": "BUY"},
{"token_id": "0987654321", "side": "SELL"}
]
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
prices = response.json()
print("Prices:", prices)
# 输出示例:
# {
# "1234567890": {"BUY": "0.65", "SELL": "0.66"},
# "0987654321": {"BUY": "0.42", "SELL": "0.43"}
# }
else:
print("Error:", response.text)
Get midpoint price
📥 接口详情
- HTTP 方法 :
GET - 端点路径 :
/midpoint - 请求参数 (Query Parameters):
token_id(必填,string):目标 token 的唯一标识符,例如"1234567890"
✅ 示例请求 URL:
https://clob.polymarket.com/midpoint?token_id=1234567890
📤 成功响应(200 OK)
返回一个简单的 JSON 对象:
json
{
"mid": "0.655"
}
mid字段:- 类型:字符串(避免浮点精度问题)
- 值:
(best_bid + best_ask) / 2的结果,保留足够小数位
python
import requests
url = "https://clob.polymarket.com/midpoint"
response = requests.get(url)
print(response.text)
Get price history for a traded token
🔍 接口用途
获取某个预测市场(由 market 参数指定)在过去一段时间内的历史价格序列,每个数据点包含:
- 时间戳(Unix 时间,秒级)
- 对应的价格(通常为中间价、成交价或某种聚合价)
💡 注意:虽然参数名为
market,但文档说明中称其为 "CLOB token ID",实际应传入 条件结果 token 的 ID (如"1234567890"),与/book、/price等接口一致。
📥 请求参数(Query Parameters)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
market |
string | ✅ 是 | 要查询的 token 唯一 ID(例如 "1234567890") |
startTs |
number | ❌ 否 | 开始时间(UTC Unix 时间戳,单位:秒) |
endTs |
number | ❌ 否 | 结束时间(UTC Unix 时间戳,单位:秒) |
interval |
enum | ❌ 否 | 快捷时间范围(如 "1d", "1w"),与 startTs/endTs 互斥 |
fidelity |
number | ❌ 否 | 数据分辨率(单位:分钟),例如 5 表示每 5 分钟一个数据点 |
⚠️ 互斥规则:
- 你只能使用以下两种方式之一 指定时间范围:
- 精确时间范围 :同时提供
startTs和endTs - 快捷时间范围 :只提供
interval(如"1d"表示最近 1 天)
- 精确时间范围 :同时提供
❌ 不能同时传
interval和startTs/endTs,否则可能报错。
✅ interval 可选值:
"1m"→ 最近 1 个月"1w"→ 最近 1 周"1d"→ 最近 1 天"6h"→ 最近 6 小时"1h"→ 最近 1 小时"max"→ 返回该市场全部历史数据
✅ fidelity 示例:
fidelity=60→ 每小时一个价格点fidelity=5→ 每 5 分钟一个点- 若未指定,服务端可能使用默认分辨率(如 1 小时)
📤 成功响应(200 OK)
返回一个 JSON 对象,包含 history 数组:
json
{
"history": [
{ "t": 1697875200, "p": "0.655" },
{ "t": 1697878800, "p": "0.660" },
...
]
}
字段说明:
t(timestamp):Unix 时间戳(秒,不是毫秒)p(price):字符串类型 的价格值(如"0.655"),保持精度
📌 价格含义:通常是该时间窗口内的中间价 (midpoint)或最后成交价,具体由 Polymarket 后端定义。
💻 使用示例
✅ 示例 1:获取最近 1 天、每小时一个点的历史价格
python
import requests
url = "https://clob.polymarket.com/prices-history"
params = {
"market": "1234567890",
"interval": "1d",
"fidelity": 60
}
response = requests.get(url, params=params)
data = response.json()
print(data["history"][:3]) # 打印前 3 个点
✅ 示例 2:获取 2023-10-01 到 2023-10-02 的 15 分钟粒度数据
python
import time
from datetime import datetime
start = int(datetime(2023, 10, 1).timestamp())
end = int(datetime(2023, 10, 2).timestamp())
params = {
"market": "1234567890",
"startTs": start,
"endTs": end,
"fidelity": 15
}
response = requests.get("https://clob.polymarket.com/prices-history", params=params)
Get bid-ask spreads
📥 接口详情
- HTTP 方法 :
POST - 端点路径 :
/spreads - 请求体格式 :
application/json - 最大请求数量 :一次最多支持 500 个 token
- 认证要求:❌ 无需认证(Public Method)
请求体结构:
一个 JSON 数组,每个元素包含:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
token_id |
string | ✅ 是 | token 的唯一 ID(如 "1234567890") |
side |
enum ("BUY"/"SELL") |
❌ 否 | 可选参数 ,但当前实现中不影响返回结果(见下文) |
💡 尽管文档列出了
side参数,但从响应结构和示例来看,它并不改变输出------接口始终返回完整的 bid-ask spread(即一个标量值),与方向无关。该字段可能是为未来扩展预留。
✅ 示例请求体:
json
[
{ "token_id": "1234567890" },
{ "token_id": "0987654321" }
]
📤 成功响应(200 OK)
返回一个 JSON 对象 ,以 token_id 为 key,对应的 spread 值为字符串:
json
{
"1234567890": "0.01",
"0987654321": "0.05"
}
- 值的含义 :
best_ask - best_bid的结果(例如:买价 0.65,卖价 0.66 → spread = 0.01) - 数据类型 :字符串 (避免浮点精度问题,如
"0.01"而非0.01)
⚠️ 如果某个 token 没有完整的买卖盘(缺少 bid 或 ask),该 token 可能:
- 不出现在响应中;
- 或返回
"0"(具体行为需实测)。
💻 代码示例
Python(使用 requests)
python
import requests
url = "https://clob.polymarket.com/spreads"
payload = [
{"token_id": "1234567890"},
{"token_id": "0987654321"}
]
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
spreads = response.json()
for token, spread in spreads.items():
print(f"Token {token}: Spread = {spread}")
else:
print("Error:", response.text)
JavaScript(使用 fetch)
js
const payload = [
{ token_id: "1234567890" },
{ token_id: "0987654321" }
];
fetch("https://clob.polymarket.com/spreads", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
})
.then(res => res.json())
.then(spreads => console.log(spreads));
Historical Timeseries Data
✅ 核心内容总结
该部分描述了一个 用于获取指定交易 token 历史价格时间序列数据的公开 API 接口:
GET /prices-history------ 获取某市场 token 的历史价格走势(时间 + 价格对)
这是进行技术分析、回测、可视化或市场研究的基础数据源。
🔍 关键信息详解
1. 接口目的
- 提供 每个已交易 token 的详细历史价格记录。
- 返回的数据是 时间戳(timestamp)与价格(price)的有序对,适合绘制折线图、K 线图等。
2. 请求方式
- HTTP 方法 :
GET - 端点 :
https://clob.polymarket.com/prices-history - 认证:无需(Public Endpoint)
3. 查询参数(Query Parameters)
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
market |
string | ✅ 是 | CLOB token ID (即条件结果 token 的 ID,如 "1234567890") |
startTs |
number | ❌ 否 | 起始时间(UTC Unix 时间戳,单位:秒) |
endTs |
number | ❌ 否 | 结束时间(UTC Unix 时间戳,单位:秒) |
interval |
enum | ❌ 否 | 快捷时间范围(如 "1d" 表示最近 1 天),与 startTs/endTs 互斥 |
fidelity |
number | ❌ 否 | 数据粒度(分辨率),单位为分钟 (如 60 = 每小时一个数据点) |
📌 互斥规则:
- 要么用
startTs+endTs指定精确时间段;- 要么用
interval(如"1w")表示"从现在往前推 X 时间"。
✅ interval 可选值:
"1h"→ 最近 1 小时"6h"→ 最近 6 小时"1d"→ 最近 1 天"1w"→ 最近 1 周"1m"→ 最近 1 个月"max"→ 返回该 token 全部历史数据
4. 响应格式(200 OK)
json
{
"history": [
{ "t": 1697875200, "p": "0.655" },
{ "t": 1697878800, "p": "0.660" },
...
]
}
t:Unix 时间戳(秒级)p:价格(字符串类型,避免浮点精度问题)- 价格通常是该时间窗口内的 中间价 (midpoint)或 代表性成交价
5. 附加资源
- 文档提到提供了一个 Interactive Notebook (交互式笔记本)用于可视化该接口返回的数据,方便开发者快速探索历史行情。
Order Management
Orders Overview
一、核心定位:订单管理的底层规则
这部分不是讲具体 API 怎么调,而是明确所有订单操作必须遵守的"游戏规则" ------ 包括订单格式、授权要求、签名规则、合法性校验,是调用 L2 下单接口的前提(违反任何一条,订单都会被拒绝)。
二、核心内容拆解
1. 订单本质:所有订单都是"限价单"(可兼容市价单)
- 核心规则:Polymarket 底层只认「限价单」,所谓"市价单"只是"价格设为当前市场最优价的限价单"(文档里的"marketable limit order");
- 技术背景:订单必须符合链上"二进制限价单协议合约"的格式要求(结构、哈希、签名),手动拼接复杂,因此推荐用官方 TS/Python/Go 库(帮你自动处理这些细节)。
2. 前置条件:必须设置「授权额度(Allowances)」
下单前,资金方地址(funderAddress)必须给 Exchange 合约授权对应代币的花费额度,否则订单会被拒绝:
| 交易方向 | 需授权的代币 | 授权要求 |
|---|---|---|
| 买入(BUY) | USDC(抵押品) | 授权额度 ≥ 订单总花费(size × price) |
| 卖出(SELL) | 条件代币(Conditional Token) | 授权额度 ≥ 卖出的代币数量 |
- 核心目的:让 Exchange 合约有权限扣减你的代币完成交易结算,这是链上交易的通用规则。
3. 关键规则:订单必须指定「签名类型(Signature Types)」
Polymarket 支持 3 种签名类型(初始化 ClobClient 时指定的 signatureType 就是这个),核心是区分"谁来签订单、用什么钱包签":
| 类型 ID | 名称 | 适用场景 |
|---|---|---|
| 0 | EOA | 普通外部账户(如 MetaMask 个人账户)签名 |
| 1 | POLY_PROXY | Polymarket 官方代理钱包签名 |
| 2 | POLY_GNOSIS_SAFE | Polymarket 部署的 Gnosis Safe 多签钱包签名(你代码里用的 2 就是这个) |
- 简化理解:初始化时指定
signatureType: 2,官方库会自动用 Gnosis Safe 钱包的规则生成合法签名,不用自己处理复杂的 EIP712 签名逻辑。
4. 合法性校验:订单实时监控(违规会被拉黑)
Polymarket 会实时校验订单有效性,违规者会被永久拉黑,核心校验维度:
(1)基础校验(实时)
- 余额校验:资金方地址的代币余额是否足够;
- 授权校验:授权额度是否覆盖订单金额;
- 链上状态:订单是否已被链上取消(避免重复成交)。
(2)额度占用校验(核心防超买/超卖)
每个市场的订单总占用额度不能超过你的可用余额,公式:
最大可下单额度 = 底层资产余额 - 所有未成交订单的占用额度之和
举例子:
- 你有 500 USDC,在 MarketA 下了 1 笔买单:1000 YES × $0.5 = 500 USDC(刚好占满余额);
- 此时再下任何 MarketA 的买单都会被拒绝(可用余额为 0);
- 只有当第一笔订单部分成交/取消,释放了占用额度,才能下新订单。
Place Single Order
一、通用核心规则(所有订单都要遵守)
先明确下单的底层规则,这是代码能跑通的前提:
1. 接口基础信息
- 请求方式:
POST /<clob-endpoint>/order(需 L2 鉴权头); - 核心参数:
order(签名后的订单对象)、owner(订单所属的 API Key)、orderType(订单类型); postOnly特殊规则:仅支持 GTC/GTD 类型,若订单会立即成交则拒绝(只允许挂单,不允许吃单)。
2. 订单对象(order)必填参数
| 参数 | 说明 |
|---|---|
salt |
随机数,保证订单唯一性 |
maker |
资金方地址(funder) |
signer |
签名地址 |
tokenId |
要交易的条件代币 ERC1155 ID |
makerAmount |
挂单方愿意支付的最大金额 |
takerAmount |
吃单方需支付的最小金额 |
expiration |
订单过期时间戳(Unix 秒数) |
nonce |
订单关联的交易所随机数 |
feeRateBps |
手续费率(基点) |
side |
买卖方向(BUY/SELL) |
signatureType |
签名类型(0=EOA/1=POLY_PROXY/2=POLY_GNOSIS_SAFE) |
signature |
订单的 hex 格式签名 |
3. 订单类型(orderType)
| 类型 | 含义 |
|---|---|
| FOK | 立即全成/全取消:订单必须一次性全部成交,否则直接取消 |
| FAK | 立即成交部分/取消剩余:能成交多少算多少,剩余部分取消 |
| GTC | 一直有效:直到成交或手动取消 |
| GTD | 有效期截止:到指定时间戳后失效(需加 1 分钟安全阈值) |
4. 常见错误码(快速定位问题)
| 错误码 | 原因 |
|---|---|
INVALID_ORDER_MIN_TICK_SIZE |
价格精度不符合最小刻度要求 |
INVALID_ORDER_NOT_ENOUGH_BALANCE |
余额/授权额度不足 |
INVALID_POST_ONLY_ORDER_TYPE |
postOnly 搭配了 FOK/FAK 类型 |
FOK_ORDER_NOT_FILLED_ERROR |
FOK 订单无法全部成交 |
二、Python 代码解析(完整可运行版)
核心逻辑:初始化客户端 → 设置 API 凭证 → 创建签名订单 → 提交订单
python
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY, SELL
# -------------------------- 1. 基础配置 --------------------------
host = "https://clob.polymarket.com"
private_key = "你的钱包私钥(不要硬编码,用环境变量)" # 从 reveal.polymarket.com 导出
chain_id = 137 # Polygon 链,固定值
# 资金方地址(你充值 USDC 的 Polymarket 钱包地址)
POLYMARKET_PROXY_ADDRESS = "你的 funder 地址"
# -------------------------- 2. 初始化客户端(三选一) --------------------------
# 场景1:邮箱/Magic 登录(signature_type=1)
# client = ClobClient(host, key=private_key, chain_id=chain_id, signature_type=1, funder=POLYMARKET_PROXY_ADDRESS)
# 场景2:浏览器钱包(MetaMask/Coinbase,signature_type=2)
client = ClobClient(host, key=private_key, chain_id=chain_id, signature_type=2, funder=POLYMARKET_PROXY_ADDRESS)
# 场景3:直接用 EOA 账户(signature_type=0,无需 funder)
# client = ClobClient(host, key=private_key, chain_id=chain_id)
# -------------------------- 3. 设置 L2 API 凭证(必须) --------------------------
# 调用 L1 逻辑生成/推导 API 凭证,并绑定到客户端
client.set_api_creds(client.create_or_derive_api_creds())
# -------------------------- 4. 示例1:提交 GTC 限价买单 --------------------------
def place_gtc_order():
# 订单参数
order_args = OrderArgs(
price=0.01, # 价格(USDC/份)
size=5.0, # 数量(份)
side=BUY, # 方向:BUY/SELL
token_id="你的代币ID", # 从 Markets API 获取:https://docs.polymarket.com/developers/gamma-markets-api/get-markets
feeRateBps=0, # 手续费率(基点)
nonce=1, # 随机数,避免重复
)
# 创建签名后的订单(自动处理 salt/signature 等复杂参数)
signed_order = client.create_order(order_args)
print("签名后的订单:", signed_order)
# 提交 GTC 订单
resp = client.post_order(signed_order, OrderType.GTC)
print("GTC 订单提交结果:", resp)
# -------------------------- 5. 示例2:提交 FOK 市价卖单 --------------------------
def place_fok_sell_order():
# 创建市价卖单(amount=卖出的份数)
market_order = client.createMarketOrder(
side=SELL,
token_id="你的代币ID",
amount=100, # 卖出 100 份
feeRateBps=0,
nonce=0,
price=0.5, # 市价单需填当前市场最优价
)
# 提交 FOK 订单(必须一次性全部成交)
resp = client.post_order(market_order, OrderType.FOK)
print("FOK 卖单提交结果:", resp)
# -------------------------- 6. 执行下单 --------------------------
if __name__ == "__main__":
place_gtc_order() # 执行 GTC 买单
# place_fok_sell_order() # 执行 FOK 卖单
三、TypeScript 代码解析(完整可运行版)
核心逻辑:初始化客户端 → 创建签名订单 → 提交不同类型订单
typescript
import { ClobClient, Side, OrderType } from "@polymarket/clob-client";
import { Wallet } from "ethers";
// -------------------------- 1. 基础配置 --------------------------
const host = "https://clob.polymarket.com";
const chainId = 137;
const privateKey = "你的钱包私钥"; // 环境变量读取,不要硬编码
const apiCreds = {
apiKey: "L1 生成的 apiKey",
secret: "L1 生成的 secret",
passphrase: "L1 生成的 passphrase",
};
const funderAddress = "你的 funder 地址";
const signatureType = 2; // 2=POLY_GNOSIS_SAFE(MetaMask 登录)
// -------------------------- 2. 初始化 L2 客户端 --------------------------
const signer = new Wallet(privateKey);
const clobClient = new ClobClient(
host,
chainId,
signer,
apiCreds,
signatureType,
funderAddress
);
// -------------------------- 3. 示例1:提交 GTC 买单 --------------------------
async function placeGtcOrder() {
// 创建签名后的订单
const signedOrder = await clobClient.createOrder({
tokenID: "71321045679252212594626385532706912750332728571942532289631379312455583992563", // YES 代币ID
price: 0.5, // 价格 0.5 USDC/份
side: Side.BUY, // 买入
size: 100, // 100 份
feeRateBps: 0, // 手续费率
nonce: 1, // 随机数
});
console.log("Created GTC Order:", signedOrder);
// 提交 GTC 订单
const resp = await clobClient.postOrder(signedOrder, OrderType.GTC);
console.log("GTC Order Response:", resp);
}
// -------------------------- 4. 示例2:提交 GTD 订单(带过期时间) --------------------------
async function placeGtdOrder() {
// 计算过期时间(需加 1 分钟安全阈值)
const oneMinute = 60 * 1000;
const expireIn30Seconds = 30 * 1000;
const expiration = Math.floor((Date.now() + oneMinute + expireIn30Seconds) / 1000);
// 创建订单
const signedOrder = await clobClient.createOrder({
tokenID: "71321045679252212594626385532706912750332728571942532289631379312455583992563",
price: 0.5,
side: Side.BUY,
size: 100,
feeRateBps: 0,
nonce: 1,
expiration: expiration, // 过期时间戳
});
// 提交 GTD 订单
const resp = await clobClient.postOrder(signedOrder, OrderType.GTD);
console.log("GTD Order Response:", resp);
}
// -------------------------- 5. 示例3:提交 FOK 市价买单 --------------------------
async function placeFokBuyOrder() {
// 创建市价买单(amount=100 USDC)
const marketOrder = await clobClient.createMarketOrder({
side: Side.BUY,
tokenID: "71321045679252212594626385532706912750332728571942532289631379312455583992563",
amount: 100, // 花费 100 USDC
feeRateBps: 0,
nonce: 0,
price: 0.5, // 市场最优价
});
// 提交 FOK 订单
const resp = await clobClient.postOrder(marketOrder, OrderType.FOK);
console.log("FOK Order Response:", resp);
}
// -------------------------- 6. 执行下单 --------------------------
async function main() {
await placeGtcOrder();
// await placeGtdOrder();
// await placeFokBuyOrder();
}
main().catch(console.error);
Place Multiple Orders (Batching)
一、通用核心规则(批量下单的底层约束)
1. 接口基础信息
- 请求方式:
POST /<clob-endpoint>/orders(需 L2 鉴权头); - 核心优势:单请求提交多笔订单(最多 15 笔),减少网络请求次数,提升效率;
- 前置条件:必须先掌握「单订单提交」逻辑,批量是单订单的扩展。
2. 请求核心参数(PostOrder 数组)
批量请求的核心是传入 PostOrders[] 数组,每个 PostOrder 对象包含:
| 参数 | 是否必填 | 类型 | 说明 |
|---|---|---|---|
order |
是 | Order | 签名后的订单对象(和单订单的 order 结构完全一致) |
orderType |
是 | string | 订单类型(FOK/FAK/GTC/GTD) |
owner |
是 | string | 订单所属的 API Key(L1 生成) |
postOnly |
否 | boolean | 仅支持 GTC/GTD,订单仅挂单不立即成交(默认 false) |
3. 订单对象(order)的必填项(和单订单一致)
包含 salt(随机数)、maker(资金方地址)、signature(订单签名)等 13 个必填字段,核心是保证每笔订单的唯一性和合法性。
4. 错误/状态规则(和单订单完全复用)
- 错误码:如
INVALID_ORDER_NOT_ENOUGH_BALANCE(余额不足)、FOK_ORDER_NOT_FILLED_ERROR(FOK 未全成交)等,单订单的错误码完全适用于批量; - 状态值:
matched(成交)、live(挂单)、delayed(延迟匹配)等,每笔订单会返回独立状态。
TypeScript 代码解析
typescript
import { ethers } from "ethers";
import { config as dotenvConfig } from "dotenv";
import { resolve } from "path";
import { ApiKeyCreds, Chain, ClobClient, OrderType, PostOrdersArgs, Side } from "../src";
dotenvConfig({ path: resolve(__dirname, "../.env") });
async function main() {
const wallet = new ethers.Wallet(`${process.env.PK}`);
const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
console.log(`Address: ${await wallet.getAddress()}, chainId: ${chainId}`);
const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
const creds: ApiKeyCreds = {
key: `${process.env.CLOB_API_KEY}`,
secret: `${process.env.CLOB_SECRET}`,
passphrase: `${process.env.CLOB_PASS_PHRASE}`,
};
const clobClient = new ClobClient(host, chainId, wallet, creds);
await clobClient.cancelAll();
const YES = "71321045679252212594626385532706912750332728571942532289631379312455583992563";
const orders: PostOrdersArgs[] = [
{
order: await clobClient.createOrder({
tokenID: YES,
price: 0.4,
side: Side.BUY,
size: 100,
}),
orderType: OrderType.GTC,
},
{
order: await clobClient.createOrder({
tokenID: YES,
price: 0.45,
side: Side.BUY,
size: 100,
}),
orderType: OrderType.GTC,
},
{
order: await clobClient.createOrder({
tokenID: YES,
price: 0.55,
side: Side.SELL,
size: 100,
}),
orderType: OrderType.GTC,
},
{
order: await clobClient.createOrder({
tokenID: YES,
price: 0.6,
side: Side.SELL,
size: 100,
}),
orderType: OrderType.GTC,
},
];
// Send it to the server
const resp = await clobClient.postOrders(orders);
console.log(resp);
}
main();
四、实际请求示例解析(JSON 格式)
文档末尾的 JSON 是批量订单的实际请求 payload 示例,核心字段解读:
json
[
{'order': {'salt': 660377097, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '88613172803544318200496156596909968959424174365708473463931555296257475886634', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0xccb8d1298d698ebc0859e6a26044c848ac4a4b0e20a391a4574e42b9c9bf237e5fa09fc00743e3e2d2f8e909a21d60f276ce083cc35c6661410b892f5bcbe2291c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'},
{'order': {'salt': 1207111323, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '93025177978745967226369398316375153283719303181694312089956059680730874301533', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0x0feca28666283824c27d7bead0bc441dde6df20dd71ef5ff7c84d3d1d5bf8aa4296fa382769dc11a92abe05b6f731d6c32556e9b4fb29e6eb50131af23a9ac941c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'}
]
Get Order
一、核心规则:查询单个订单的基础信息
1. 接口基础配置
- 请求方式:
GET /<clob-endpoint>/data/order/<order_hash>(需 L2 鉴权头); - 核心作用:根据订单哈希/ID,查询该订单的当前状态、成交情况、价格等全量信息;
- 请求参数:
id(可选,文档标注为 no,实际需在 URL 中传入order_hash,即订单唯一标识)。
2. 返回核心数据结构(OpenOrder 对象)
这是查询结果的核心,包含订单全生命周期信息,关键字段解读:
| 字段 | 类型 | 核心含义 |
|---|---|---|
id |
string | 订单唯一 ID/哈希(查询时传入的参数) |
status |
string | 订单当前状态(如 live/已成交/已取消/已过期) |
market |
string | 订单所属的市场 ID(条件 ID) |
original_size |
string | 订单初始数量(下单时的总份数/金额) |
size_matched |
string | 已成交数量(部分成交时显示已匹配的量) |
price |
string | 订单价格(USDC/份) |
side |
string | 买卖方向(BUY/SELL) |
maker_address |
string | 资金方地址(funder) |
type |
string | 订单类型(GTC/FOK/GTD/FAK) |
created_at |
string | 订单创建时间戳(Unix 秒数) |
expiration |
string | 订单过期时间戳(0 表示永不过期,如 GTC) |
associate_trades |
string[] | 关联的交易 ID 列表(订单成交后会关联对应的交易记录) |
二、Python 代码解析
python
order = clob_client.get_order("0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc")
print(order)
三、TypeScript 代码解析
typescript
async function main() {
const order = await clobClient.getOrder(
"0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc"
);
console.log(order);
}
main();
Get Active Orders
🔍 一、功能说明
- 接口名称:Get Active Orders(获取活跃订单)
- 用途:获取指定市场(market)下所有尚未成交的订单(open orders)。
- 认证要求 :需要提供 L2 Header(通常指包含签名或权限验证的 HTTP 请求头,用于身份认证和防篡改)。
- HTTP 方法 :
GET - 路径 :
/<clob-endpoint>/data/orders
CLOB = Central Limit Order Book(中心化限价订单簿),常见于去中心化交易所(DEX)或订单簿型交易平台。
📥 二、请求参数(Query Parameters)
| 参数名 | 必填 | 类型 | 说明 |
|---|---|---|---|
id |
否 | string | 指定要查询的单个订单 ID |
market |
否 | string | 要查询的市场条件 ID(通常是预测市场或交易对的唯一标识,如 Polymarket 中的 conditionId) |
asset_id |
否 | string | 指定某资产/代币的 ID |
⚠️ 注意:这三个参数都是可选的。如果只传
market,就返回该市场下所有活跃订单;如果传了id,则只返回该订单(前提是它仍处于活跃状态)。
📤 三、响应格式
- 返回类型 :
OpenOrder[](一个开放订单对象的数组) - 如果没有匹配的订单,可能返回空数组
[],而不是null(文档中写null可能是笔误,实际应为数组类型)。
每个 OpenOrder 通常包含如下字段(具体结构取决于 API 实现):
id: 订单 IDmarket: 市场 IDside: 买单(buy)或卖单(sell)price: 价格amount: 数量user: 下单用户地址status: 状态(应为 "open")created_at: 创建时间等
💻 四、代码示例
✅ Python 示例(使用 py_clob_client)
python
from py_clob_client.clob_types import OpenOrderParams
# 假设 client 已正确初始化并完成认证(含 L2 header)
resp = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
)
)
print(resp)
print("Done!")
✅ JavaScript / TypeScript 示例(异步)
javascript
async function main() {
const resp = await clobClient.getOpenOrders({
market: "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
});
console.log(resp);
console.log(`Done!`);
}
main();
Check Order Reward Scoring
🔍 一、功能说明
平台提供两种方式来检查订单是否正在参与 奖励评分(Reward Scoring):
- 单个订单检查
- 判断某一个订单是否当前被计入奖励计算。
- 批量订单检查
- 一次性判断多个订单各自的奖励状态。
✅ 如果
scoring: true,表示该订单正在为用户累积奖励(如积分、代币返利等);❌ 如果
scoring: false,则不参与奖励计划(可能因为价格偏离、订单太小、已部分成交等原因)。
⚠️ 两个接口均要求 L2 Header(包含身份认证和签名,确保请求来自合法用户)。
📥 二、接口详情
1. 检查单个订单是否 scoring(GET)
- HTTP 方法 :
GET - 路径 :
/<clob-endpoint>/order-scoring?order_id={orderId} - 必需参数 :
orderId(string):要查询的订单 ID(十六进制字符串,如"0x1a2b3c...")
2. 批量检查多个订单是否 scoring(POST)
-
HTTP 方法 :
POST -
路径 :
/<clob-endpoint>/orders-scoring -
请求体(JSON) :
json{ "orderIds": ["0x...", "0x..."] } -
必需参数 :
orderIds(string[]):订单 ID 数组
📤 三、响应格式
单个订单响应
返回一个对象:
ts
{
scoring: boolean // true 或 false
}
类型名:OrdersScoring(尽管名字是复数,但单查时也用此结构)
批量订单响应
返回一个 字典(对象),键为订单 ID,值为布尔值:
ts
{
"0x1a2b...": true,
"0x3c4d...": false
}
文档中说 "null OrdersScoring" 是指响应主体即为
OrdersScoring类型,不是真的返回null。
💻 四、代码示例(完整可运行风格)
✅ JavaScript / TypeScript 示例
1. 检查单个订单是否 scoring
javascript
async function checkSingleOrder() {
const orderId = "0x7f8e9d6a5b4c3b2a1c0d9e8f7a6b5c4d3e2f1a0b"; // 示例订单 ID
const scoring = await clobClient.isOrderScoring({
orderId: orderId,
});
console.log(`Order ${orderId} is scoring:`, scoring.scoring);
}
checkSingleOrder();
2. 批量检查多个订单是否 scoring
javascript
async function checkMultipleOrders() {
const orderIds = [
"0x7f8e9d6a5b4c3b2a1c0d9e8f7a6b5c4d3e2f1a0b",
"0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b"
];
const scoringDict = await clobClient.areOrdersScoring({
orderIds: orderIds,
});
console.log("Scoring status for orders:");
for (const id of orderIds) {
console.log(`${id}: ${scoringDict[id]}`);
}
}
checkMultipleOrders();
注意:函数名
isOrderScoring和areOrdersScoring是 SDK 封装后的方法名,底层分别调用 GET 和 POST 接口。
Cancel Orders(s)
🧭 一、功能概览
平台支持以下四种订单取消操作:
| 操作 | 描述 | HTTP 方法 | 路径 |
|---|---|---|---|
| ✅ 取消单个订单 | 取消指定 ID 的一个订单 | DELETE |
/order |
| ✅ 取消多个订单 | 批量取消一组订单 ID | DELETE |
/orders |
| ✅ 取消所有订单 | 取消当前用户全部活跃订单 | DELETE |
/cancel-all |
| ✅ 取消某市场订单 | 取消指定市场(或资产)下的所有订单 | DELETE |
/cancel-market-orders |
所有接口均返回:
canceled: 成功取消的订单 ID 列表not_canceled: 无法取消的订单及其原因(如"已成交"、"不存在"等)
📥 二、各接口详解
1. 取消单个订单
-
路径 :
DELETE /<clob-endpoint>/order -
请求体 (JSON):
json{ "orderID": "0x..." } -
参数 :
orderID(必填,string)
2. 取消多个订单
-
路径 :
DELETE /<clob-endpoint>/orders -
请求体 (JSON):
json["0x...", "0x..."] -
参数:直接传订单 ID 数组(注意:不是对象,是纯数组)
3. 取消所有订单
- 路径 :
DELETE /<clob-endpoint>/cancel-all - 无请求体
- 取消当前用户在所有市场的所有未成交订单
4. 取消某市场下的订单
-
路径 :
DELETE /<clob-endpoint>/cancel-market-orders -
请求体 (JSON):
json{ "market": "0x...", "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426" } -
参数 (至少提供一个):
market(可选):市场 condition IDasset_id(可选):资产 ID(如 Polymarket 中的 token ID)
如果两者都提供,可能取交集;如果只提供其一,则取消该维度下所有订单。
📤 三、统一响应格式
所有取消接口返回相同结构:
ts
{
canceled: string[]; // 成功取消的订单 ID 列表
not_canceled: Record<string, string>; // { "orderId": "reason" }
}
常见 not_canceled 原因:
"Order already filled"(已完全成交)"Order not found"(订单不存在或不属于你)"Order already cancelled"(已取消)"Order is not active"(非活跃状态)
💻 四、完整代码示例
✅ TypeScript / JavaScript 示例
1. 取消单个订单
ts
async function cancelSingleOrder() {
const resp = await clobClient.cancelOrder({
orderID: "0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88",
});
console.log("Canceled:", resp.canceled);
console.log("Not canceled:", resp.not_canceled);
console.log("Done!");
}
2. 取消多个订单
ts
async function cancelMultipleOrders() {
const resp = await clobClient.cancelOrders([
"0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88",
"0xaaaa111122223333444455556666777788889999aaaabbbbccccddddeeeeffff",
]);
console.log("Canceled:", resp.canceled);
console.log("Not canceled:", resp.not_canceled);
console.log("Done!");
}
3. 取消所有订单
ts
async function cancelAllOrders() {
const resp = await clobClient.cancelAll();
console.log(`Canceled ${resp.canceled.length} orders.`);
if (Object.keys(resp.not_canceled).length > 0) {
console.log("Failed to cancel:", resp.not_canceled);
}
console.log("Done!");
}
4. 取消某市场下的订单
ts
async function cancelMarketOrders() {
const resp = await clobClient.cancelMarketOrders({
market: "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
asset_id: "52114319501245915516055106046884209969926127482827954674443846427813813222426",
});
console.log("Canceled:", resp.canceled);
console.log("Not canceled:", resp.not_canceled);
console.log("Done!");
}
⚠️ 注意:
cancelOrders接收的是 数组 ,而cancelOrder接收的是 对象,这是 SDK 设计差异,需留意。
Onchain Order Info
🔍 一、什么是 OrderFilled 事件?
- 它是智能合约在 订单被执行(部分或全部成交)时 发出的 以太坊日志事件(Event Log)。
- 每个事件对应一次 订单的填充(fill)行为,可能是一笔完整成交,也可能是多次部分成交中的一次。
📥 二、事件字段详解
| 字段名 | 类型 | 含义 |
|---|---|---|
orderHash |
bytes32 / string | 该订单的唯一哈希标识(由订单内容生成),用于关联链下订单与链上成交 |
maker |
address | 挂单方(订单创建者),资金从该地址转出 |
taker |
address | 吃单方(成交发起者);若为交易所合约地址,说明是系统撮合多个限价单(如市价单匹配多个限价单) |
makerAssetId |
uint256 / string | 挂单方支付的资产 ID : - 若为 0 → 表示支付的是 USDC (即 买单 BUY ) - 若非 0 → 表示支付的是 结果代币(Outcome Token) (即 卖单 SELL) |
takerAssetId |
uint256 / string | 挂单方收到的资产 ID : - 若为 0 → 收到 USDC (即 卖单 SELL ) - 若非 0 → 收到 结果代币 (即 买单 BUY) |
makerAmountFilled |
uint256 | 挂单方 实际支付的资产数量(单位:原子单位,如 USDC 是 1e6 精度) |
takerAmountFilled |
uint256 | 挂单方 实际收到的资产数量 |
fee |
uint256 | 挂单方(maker)支付的手续费(通常以 USDC 计价) |
Trades
Trades Overview
- 所有历史交易可通过 REST API 获取。
- 交易由 taker(吃单方) 发起,匹配一个或多个 maker(挂单方) 的限价单。
- 由于 gas 限制,一笔逻辑交易可能被拆成多个链上交易,通过
market_order_id、match_time和递增的bucket_index关联,需在客户端合并还原。 - 交易有五种状态:
- MATCHED:已匹配,待上链
- MINED:已上链,未达最终确认
- CONFIRMED ✅:成功且最终确认(终端状态)
- RETRYING:失败后重试中
- FAILED ❌:彻底失败,不再重试(终端状态)
Get Trades
🔍 一、核心功能
- 接口路径 :
GET /<clob-endpoint>/data/trades - 认证要求 :必须携带 L2 Header(即带签名的请求头,证明身份)
- 用途 :获取当前用户作为 taker(吃单方) 或 maker(挂单方) 参与的所有交易记录
- 支持过滤字段 :
id:指定某笔交易 IDtaker/maker:按参与角色地址过滤market:按市场(condition ID)过滤before/after:按时间范围过滤(Unix 时间戳)
📤 二、响应结构
返回一个 Trade[] 数组,每条 Trade 包含:
主要字段:
id:交易唯一 IDtaker_order_id:触发成交的 taker 订单哈希market:市场 condition IDside:该用户在此交易中的方向("buy" 或 "sell")size:成交数量price:taker 订单的限价fee_rate_bps:手续费(以基点表示,如 10 = 0.1%)status:交易状态(如 CONFIRMED, FAILED 等)match_time:撮合时间transaction_hash:链上交易哈希bucket_index:若一笔逻辑交易被拆成多笔,用此索引关联type:当前视角是"TAKER"还是"MAKER"maker_orders:该交易匹配到的所有 maker 订单详情(数组)
MakerOrder 子对象包含:
order_id,maker_address,matched_amount,price,side,outcome等
💡 注意:同一个逻辑交易可能因 gas 限制被拆成多个
Trade对象,需用taker_order_id + match_time + bucket_index合并还原。
💻 三、代码示例
✅ TypeScript / JavaScript
ts
async function main() {
const userAddress = await wallet.getAddress();
// 获取该用户作为 maker 在指定市场的所有交易
const trades = await clobClient.getTrades({
market: "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
maker: userAddress, // 注意:参数名是 'maker',不是 'maker_address'
});
console.log("Trades:", trades);
}
main();
⚠️ 注意:SDK 参数名为
maker(字符串地址),文档中 Trade 对象字段叫maker_address,二者不同。