⚠️ Wiki-First 原则: 代码更新必须先修改 Wiki,再写代码。任何预测模型、做市逻辑、下单流程的变更,请先更新对应维基页面。

💰 Polymarket CLOB API 下单


本文档详细说明 Polymarket CLOB v2 下单流程,涵盖签名、钱包、排错和完整代码示例。

架构概览



┌─────────────┐     EIP-712 签名     ┌──────────────────┐
│  CLOBClient  │ ──────────────────▶ │  Polymarket CLOB  │
│  (Python)    │ ◀────────────────── │  API (v2)         │
└─────────────┘     JSON Response    └──────────────────┘
       │
       │ 钱包
       ▼
┌──────────────────┐
│  Gnosis Safe      │  ← 资金托管 (操作员 EOA 签名)
│  (0xe39C...)      │
└──────────────────┘

钱包架构


地址类型用途CLOB 余额
0xAf63...EOA操作员私钥 (签名)0 USDC
0xe39C4853A6e14045F192B65EfbACECf845d74C0BGnosis Safe资金托管~87 USDC

关键: 资金在 Safe 中,下单需使用 Safe 地址作为 maker,签名类型为 POLY_GNOSIS_SAFE (2)


CLOB v2 下单流程


1. 环境配置 (.env)



# Polymarket L2 API 凭证
POLYMARKET_L2_API_KEY=your_api_key
POLYMARKET_L2_SECRET=your_secret
POLYMARKET_L2_PASSPHRASE=your_passphrase
POLYMARKET_WALLET_ADDRESS=0xAf63...    # EOA 操作员地址

# Safe 多签钱包 (资金地址)
POLYMARKET_SAFE_ADDRESS=0xe39C4853A6e14045F192B65EfbACECf845d74C0B

# EOA 私钥 (用于签名)
POLYMARKET_PRIVATE_KEY=0x...

# 代理 (国内需要)
# 系统级 Clash TUN 路由,不需额外配置

2. CLOBClient 初始化



from src.mm.clob_client import CLOBClient

# 方式 A: 使用 EOA 私钥 + Safe 地址
client = CLOBClient.from_private_key(
    private_key="0x...",
    funder_address="0xe39C..."  # Safe 地址
)

# 方式 B: 使用 L2 API 凭证 + Safe 地址
client = CLOBClient(
    api_key="...",
    api_secret="...",
    passphrase="...",
    wallet_address="0xAf63...",       # EOA
    funder_address="0xe39C..."        # Safe (资金方)
)

3. 下单 (create_order)



# 基本下单
result = client.create_order(
    token_id="1234567890...",  # 合约 token ID
    price=0.63,                # 价格 (0-1, 即 63¢)
    size=10.0,                 # 数量 (最大 2 位小数)
    side="BUY",                # BUY 或 SELL
)

# 返回示例 (成功)
{
    "id": "0xabcd1234...",
    "status": "live",
    "maker": "0xe39c...",
    "price": "0.63",
    "original_size": "10.0",
    "size_matched": "0",
    "side": "BUY"
}

4. EIP-712 签名结构 (v2)



EIP712_ORDER_TYPES_V2 = {
    "Order": [
        {"name": "salt", "type": "uint256"},
        {"name": "maker", "type": "address"},
        {"name": "signer", "type": "address"},
        {"name": "taker", "type": "address"},
        {"name": "tokenId", "type": "uint256"},
        {"name": "makerAmount", "type": "uint256"},
        {"name": "takerAmount", "type": "uint256"},
        {"name": "side", "type": "uint8"},
        {"name": "signatureType", "type": "uint8"},
        {"name": "timestamp", "type": "uint64"},
        {"name": "expiration", "type": "uint64"},
        {"name": "metadata", "type": "bytes32"},
        {"name": "builder", "type": "address"}
    ]
}

EIP712_DOMAIN = {
    "name": "Polymarket CTF Exchange",
    "version": "2",
    "chainId": 137,          # Polygon
    "verifyingContract": "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E"
}

5. 签名类型


类型说明
EOA0普通 EOA 签名
POLY_PROXY1Polymarket Proxy 合约
POLY_GNOSIS_SAFE2Gnosis Safe 多签

香港天气做市使用 类型 2 (POLY_GNOSIS_SAFE)

  • signer = EOA 操作员地址
  • maker = Safe 地址 (资金方)

  • CLOB v2 Order Wire Format


    
    {
        "salt": 123456789,
        "maker": "0xe39C4853A6e14045F192B65EfbACECf845d74C0B",
        "signer": "0xAf63...",
        "taker": "0x0000000000000000000000000000000000000000",
        "tokenId": "1234567890...",
        "makerAmount": "500000",
        "takerAmount": "500000",
        "side": "BUY",
        "signatureType": 2,
        "timestamp": "1714400000",
        "expiration": "0",
        "metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "builder": "0x0000000000000000000000000000000000000000",
        "signature": "0x..."
    }
    

    注意事项:

  • salt 必须是随机 uint256
  • timestamp 是 Unix 秒级时间戳
  • makerAmount / takerAmount 是 USDC 精度 (6 位小数) 的整数
  • price = makerAmount / takerAmount (BUY) 或 takerAmount / makerAmount (SELL)
  • 不需要 noncefeeRateBps 字段 (v1 遗留)

  • Web UI 下单流程


    /mm/weather 页面上的下单操作,通过以下 API 调用:


    POST /api/mm/weather/place-order


    
    // Request
    {
        "token_id": "1234567890...",
        "price": 0.63,
        "size": 10.0,
        "side": "BUY",
        "temp": 29,
        "comp_type": "exact"
    }
    
    // Response (成功)
    {
        "success": true,
        "order": { "id": "0x...", "status": "live" },
        "message": "BUY 10.0 @ 0.63 placed",
        "warnings": [],
        "cooldown_seconds": 30
    }
    

    下单防护规则


    1. 重复检测: 同 token + 同方向 → 自动撤旧单再挂新单

    2. 自成交防护:

    - 新 BUY 价格必须 < 现有 SELL 价格

    - 新 SELL 价格必须 > 现有 BUY 价格

    - 违反 → 返回 409 并提示冲突订单ID

    3. 冷却期: 同 token+方向 30s 冷却 (返回 429)

    4. 测试上限: 单笔 $30,超过拒绝

    5. 余额重试: 余额不足时自动缩量 (-0.1/级, 最多10级)

    6. Tick 自适应: < 10¢ 用 0.1¢ tick,≥ 10¢ 用 1¢ tick


    POST /api/mm/weather/quick-order


    
    // Request — 从前端 Gamma 数据计算的报价
    {
        "token_id": "1234567890...",
        "side": "BUY",
        "size": 5.0,
        "price": 0.067,       // 前端预先算好的价格
        "temp": 29,
        "comp_type": "exact"
    }
    

    常见问题排查


    HTTP 400: "not enough balance"


    原因: CLOB 余额 ≠ 链上余额。CLOB 有独立的内部记账。


    解决:

    1. 确认 Safe 地址正确且已在 polymarket.com/portfolio 存入 USDC

    2. 检查 funder_address 是否为 Safe (非 EOA)

    3. 确认已从 polymarket.com 执行 deposit 操作


    HTTP 401: Unauthorized


    原因: HMAC 签名时间偏差或 L2 凭证错误。


    解决:

    1. 确保系统时间同步 (NTP)

    2. 检查代理设置 (国内需 SOCKS5 代理)

    3. 验证 API Key/Secret/Passphrase 正确性


    签名失败: "invalid address"


    原因: EOA 地址格式错误 (缺少字符或校验和不匹配)。


    解决:

    1. 地址必须是 40 hex 字符 (不含 0x)

    2. 使用 EIP-55 校验和格式

    3. 从 Polymarket 账户设置页面复制正确的地址


    代理问题


    CLOB API 直连: https://clob.polymarket.com

  • 系统级 Clash TUN 路由自动代理
  • polymkt.lt.sopher.cool:4433 反向代理已失效 (针对 CLOB)

  • CLOBClient 内置代理:

    
    self.session.proxies.update({
        'http': 'socks5h://127.0.0.1:7897',
        'https': 'socks5h://127.0.0.1:7897',
    })
    

    相关代码文件


    文件行数说明
    src/mm/clob_client.py~37KBCLOB API 完整客户端
    src/web/app.py (下单)行 4109-4295Web UI 下单端点
    src/web/app.py (快捷下单)行 4328+quick-order 端点
    src/web/app.py (撤单)行 4611+cancel 端点
    src/mm/weather_mm_runner.py~73KB做市主循环 (自动下单)

    参考文档


  • [CLOB v2 Migration](../clob-v2-migration.md) — v1 → v2 迁移指南
  • [CLOB Order Placement Fix](../clob-order-placement-fix.md) — 余额/签名问题解决
  • [CLOB v2 Signature Debug](../clob-v2-signature-debug.md) — 签名调试记录
  • [Polymarket CLOB Docs](https://docs.polymarket.com) — 官方文档