跳转到主要内容
Polymarket 上的所有订单都以限价单形式表达。市价单通过提交一个可成交价格的限价单来实现——你的订单会立即以盘口最优价格成交。 底层订单原语采用 EIP-712 标准进行结构化、哈希和签名,然后通过 Exchange 合约在链上执行。手动准备订单比较复杂,因此我们推荐使用开源的 TypeScriptPython SDK 客户端,它们会为你处理签名和提交。
如果你更喜欢直接使用 REST API,则需要自行管理订单签名。有关构造所需请求头的详细信息,请参阅身份验证

订单类型

类型行为使用场景
GTC (Good-Til-Cancelled)挂在盘口直到成交或取消被动限价单的默认选项
GTD (Good-Til-Date)在指定过期时间(UTC 秒级时间戳)之前有效,除非先被成交或取消在已知事件前自动过期订单
FOK (Fill-Or-Kill)必须立即完全成交,否则整个订单被取消全部成交或全部取消
FAK (Fill-And-Kill)立即成交尽可能多的份额,然后取消任何未成交的剩余部分部分立即成交
  • FOKFAK 是市价单类型——它们立即与挂单流动性成交。
    • 买入: 指定你想要花费的美元金额
    • 卖出: 指定你想要出售的份额数量
  • GTCGTD 是限价单类型——它们以你指定的价格挂在盘口。
GTD 过期时间: 有一分钟的安全阈值。如果你需要订单在 90 秒后过期,正确的过期值是 现在 + 1 分钟 + 30 秒

Post-Only 订单

Post-only 订单是只会挂在盘口而不会在进入时立即匹配的限价单。
  • 如果 post-only 订单会穿过价差(即可立即成交),它将被拒绝而不是执行。
  • Post-only 不能与市价单类型(FOK 或 FAK)组合使用。如果市价单类型发送 postOnly = true,订单将被拒绝。
  • Post-only 只能与 GTCGTD 订单类型一起使用。

最小价格变动单位

市场有不同的最小价格增量(最小价格变动单位)。你的订单价格必须符合市场的最小价格变动单位,否则订单将被拒绝。
最小价格变动单位价格精度价格示例
0.11 位小数0.1, 0.2, 0.5
0.012 位小数0.01, 0.50, 0.99
0.0013 位小数0.001, 0.500, 0.999
0.00014 位小数0.0001, 0.5000, 0.9999
使用 SDK 检索市场的最小价格变动单位:
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
你还可以查看 Markets API 返回的市场对象上的 minimum_tick_size 字段。

Negative Risk

多结果事件(例如”谁会赢得选举?”有 3 个以上候选人)使用不同的交易合约,称为 Neg Risk CTF Exchange。在这些市场下单时,你必须在订单选项中传递 negRisk: true
const response = await client.createAndPostOrder(
  {
    tokenID: "TOKEN_ID",
    price: 0.5,
    size: 10,
    side: Side.BUY,
  },
  {
    tickSize: "0.01",
    negRisk: true, // Required for multi-outcome markets
  },
);
你可以通过 SDK 或市场对象的 neg_risk 字段检查市场是否使用 negative risk:
const isNegRisk = await client.getNegRisk(tokenID);

授权额度

在下单之前,你的资金地址必须已批准 Exchange 合约使用相关代币:
  • 买入: 资金方必须设置大于或等于支出金额的 USDC.e 授权额度。
  • 卖出: 资金方必须设置大于或等于出售金额的条件代币授权额度。
这允许 Exchange 合约根据你签名的订单指令执行结算。

有效性检查

系统会持续监控订单以确保它们保持有效。这包括跟踪:
  • 底层余额
  • 授权额度
  • 链上订单取消
任何被发现故意滥用这些检查的 maker 将被列入黑名单。
每个市场的订单下单也有限制。你只能下总额小于或等于每个市场可用余额的订单。例如,如果你的资金钱包中有 500 USDC.e,你可以下一个以 $0.50 买入 1000 YES 的订单——但该市场中的任何额外买入订单都会被拒绝,因为你的全部余额已为第一个订单预留。 你可以下单的最大规模是: maxOrderSize=underlyingAssetBalance(orderSizeorderFillAmount)\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})

订单查询

所有查询端点都需要 L2 身份验证Builder 身份验证的客户端也可以使用相同的方法查询归属于其 builder 账户的订单。

获取单个订单

通过订单 ID 检索特定订单的详细信息:
const order = await client.getOrder("0xb816482a...");
console.log(order);

获取未成交订单

检索你的未成交订单,可选择按市场或资产筛选:
// All open orders
const orders = await client.getOpenOrders();

// Filtered by market
const marketOrders = await client.getOpenOrders({
  market: "0xbd31dc8a...",
});

// Filtered by asset
const assetOrders = await client.getOpenOrders({
  asset_id: "52114319501245...",
});

OpenOrder 对象

每个返回的订单包含以下字段:
字段类型描述
idstring订单 ID
statusstring当前订单状态
marketstring市场 ID (条件 ID)
asset_idstring代币 ID
sidestringBUYSELL
original_sizestring下单时的原始订单规模
size_matchedstring已成交数量
pricestring限价
outcomestring可读结果(例如 “Yes”、“No”)
order_typestring订单类型 (GTC、GTD、FOK、FAK)
maker_addressstring资金地址
ownerstring订单所有者的 API 密钥
expirationstring订单过期的 Unix 时间戳(无过期时间为 0)
associate_tradesstring[]此订单部分参与的交易 ID
created_atstring订单创建的 Unix 时间戳

交易历史

当订单被匹配时,会创建一笔交易。交易经历以下状态:
状态是否终态?描述
MATCHED已匹配并发送到执行器服务以进行链上提交
MINED观察到已在链上挖出,但尚未达到最终性阈值
CONFIRMED达到强概率最终性——交易成功
RETRYING交易失败(回滚或重组)——运营商正在重试
FAILED交易永久失败且不再重试

Trade 对象

每笔交易包含以下字段:
字段类型描述
idstring交易 ID
taker_order_idstringTaker 订单 ID (哈希)
marketstring市场 ID (条件 ID)
asset_idstring代币 ID
sidestringBUYSELL
sizestring交易规模
fee_rate_bpsstring以基点表示的费率
pricestring交易价格
statusstring交易状态(见上表)
match_timestring交易匹配的 Unix 时间戳
last_updatestring最后状态更新的 Unix 时间戳
outcomestring可读结果(例如 “Yes”、“No”)
ownerstring交易所有者的 API 密钥 ID
maker_addressstring资金地址
trader_sidestring你在此交易中是 TAKER 还是 MAKER
transaction_hashstring链上交易哈希(挖矿后可用)
maker_ordersarray与此交易匹配的 maker 订单数组(见下文)

MakerOrder 字段

maker_orders 数组中的每个条目包含:
字段类型描述
order_idstringMaker 订单 ID (哈希)
ownerstringMaker 的 API 密钥 ID
maker_addressstringMaker 的资金地址
matched_amountstring此交易中匹配的数量
pricestringMaker 订单价格
fee_rate_bpsstringMaker 费率(基点)
asset_idstring代币 ID
outcomestring结果名称
sidestringBUYSELL
使用 SDK 检索你的交易:
// All trades
const trades = await client.getTrades();

// Filtered by market
const marketTrades = await client.getTrades({
  market: "0xbd31dc8a...",
});

// With pagination
const paginatedTrades = await client.getTradesPaginated({
  market: "0xbd31dc8a...",
});

心跳

心跳端点维护会话存活以确保订单安全。如果在 10 秒内(最多有 5 秒缓冲)未收到有效心跳,你的所有未成交订单将被取消
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
  const resp = await client.postHeartbeat(heartbeatId);
  heartbeatId = resp.heartbeat_id;
}, 5000);
  • 在每个请求中,包含你收到的最新 heartbeat_id。对于你的第一个请求,使用空字符串。
  • 如果你发送无效或过期的 heartbeat_id,服务器会响应 400 Bad Request 并在响应中提供正确的 heartbeat_id。更新你的客户端并重试。

订单评分

检查你的挂单是否符合 maker 返佣评分条件:
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }

// Multiple orders
const batchScoring = await client.areOrdersScoring({
  orderIds: ["0x...", "0x..."],
});

链上订单信息

当交易在链上结算时,Exchange 合约会发出 OrderFilled 事件,包含以下字段:
字段描述
orderHash已成交订单的唯一哈希
maker生成订单和资金来源的用户
taker成交订单的用户,或在成交多个限价单时为 Exchange 合约
makerAssetId给出的资产 ID。如果为 0,订单是买入(用 USDC.e 换取结果代币)
takerAssetId收到的资产 ID。如果为 0,订单是卖出(用结果代币换取 USDC.e)
makerAmountFilled给出的资产数量
takerAmountFilled收到的资产数量
fee订单 maker 支付的费用

错误消息

下单时,如果无法下单,响应可能包含 errorMsg。如果 successfalse,则发生服务器端错误:
错误描述
INVALID_ORDER_MIN_TICK_SIZE价格不符合市场的最小价格变动单位
INVALID_ORDER_MIN_SIZE订单规模低于最小阈值
INVALID_ORDER_DUPLICATED相同的订单已经下过
INVALID_ORDER_NOT_ENOUGH_BALANCE资金方没有足够的余额或授权额度
INVALID_ORDER_EXPIRATION过期时间戳在过去
INVALID_ORDER_ERROR插入订单时的系统错误
INVALID_POST_ONLY_ORDER_TYPEPost-only 标志与市价单类型(FOK/FAK)一起使用
INVALID_POST_ONLY_ORDERPost-only 订单会穿过盘口
EXECUTION_ERROR执行交易时的系统错误
ORDER_DELAYED由于市场条件订单下单延迟
DELAYING_ORDER_ERROR延迟订单时的系统错误
FOK_ORDER_NOT_FILLED_ERRORFOK 订单无法完全成交
MARKET_NOT_READY市场尚未接受订单

插入状态

当订单成功下单时,响应包含 status 字段:
状态描述
matched订单已下单并与挂单匹配
live订单已下单并挂在盘口
delayed订单可成交但受匹配延迟限制
unmatched订单可成交但延迟失败——下单仍然成功

安全性

Polymarket 的 Exchange 合约已由 Chainsecurity 审计(查看审计报告)。 运营商的权限仅限于订单匹配和确保正确排序。运营商无法设置价格或执行未经授权的交易。如果出现信任问题,用户可以独立地在链上取消订单。

下一步