Orders
The ctx.orders module handles order placement and management. Write operations require a signer — the SDK handles EIP-712 signing automatically.
import { ContextClient } from "@contextwtf/sdk"
const ctx = new ContextClient({
apiKey: process.env.CONTEXT_API_KEY!,
signer: { privateKey: process.env.PRIVATE_KEY! as `0x${string}` },
})
Place a limit order
Create a signed limit order that sits on the book until filled or canceled:
const result = await ctx.orders.create({
marketId: "0x1234...",
outcome: "yes",
side: "buy",
priceCents: 45, // 45¢ per contract
size: 10, // 10 contracts
})
console.log("Order placed:", result.order.nonce)
console.log("Status:", result.order.status)
Limit order parameters
| Param | Type | Description |
|---|
marketId | string | Market ID (hex) |
outcome | "yes" | "no" | Which outcome to trade |
side | "buy" | "sell" | Buy or sell |
priceCents | number | Price in cents (1-99) |
size | number | Number of contracts (min 0.01) |
expirySeconds | number | Time until expiry (default: 1 year) |
inventoryModeConstraint | 0 | 1 | 2 | Controls token minting behavior (default: 0) |
makerRoleConstraint | 0 | 1 | 2 | Controls maker/taker role (default: 0) |
Inventory mode
| Value | Name | Description |
|---|
0 | ANY | Fill can mint new tokens or use existing inventory (recommended) |
1 | REQUIRE_INVENTORY | Maker must already hold the outcome tokens |
2 | REQUIRE_NO_INVENTORY | Settlement mints complete sets from maker’s deposited TUSD on fill. Use this for sell orders when you don’t hold tokens but have TUSD deposited. |
Maker role constraint
| Value | Name | Description |
|---|
0 | ANY | No constraint (recommended default) |
1 | MAKER_ONLY | Order must be the resting (maker) side of the trade |
2 | TAKER_ONLY | Order must fill immediately or gets voided |
Do not use makerRoleConstraint: 1 (MAKER_ONLY). When two maker-only orders cross, Settlement reverts with InvalidRoleConstraint, poisoning the entire batch and blocking all trading on the market. Use 0 (ANY) instead.
The SDK converts your human-friendly values (cents, contracts, “yes”/“no”) into the on-chain format (BigInts, outcome indices) and signs with EIP-712 automatically.
Place a market order
Create a market order that fills immediately at the best available price:
const result = await ctx.orders.createMarket({
marketId: "0x1234...",
outcome: "yes",
side: "buy",
maxPriceCents: 55, // won't pay more than 55¢
maxSize: 10, // buy up to 10 contracts
})
console.log("Order placed:", result.order.nonce)
console.log("Status:", result.order.status)
console.log("Filled:", result.order.percentFilled, "%")
Market orders take the best available liquidity up to your price and size limits. If the order can’t fill completely, the remaining portion is voided.
Market order parameters
| Param | Type | Description |
|---|
marketId | string | Market ID (hex) |
outcome | "yes" | "no" | Which outcome to trade |
side | "buy" | "sell" | Buy or sell |
maxPriceCents | number | Maximum price in cents (1-99) — price ceiling for buys, floor for sells |
maxSize | number | Maximum number of contracts to fill (min 0.01) |
expirySeconds | number | Time until expiry (default: 1 year) |
Cancel an order
Cancel by nonce:
const result = await ctx.orders.cancel("0xnonce...")
if (result.success) {
console.log("Cancelled")
} else if (result.alreadyCancelled) {
console.log("Already cancelled")
}
Cancel and replace
Atomically cancel an existing order and place a new one:
const result = await ctx.orders.cancelReplace(
"0xold-nonce...", // nonce of order to cancel
{
marketId: "0x1234...",
outcome: "yes",
side: "buy",
priceCents: 50, // updated price
size: 10,
},
)
console.log("Cancelled:", result.cancel.success)
console.log("New order:", result.create.order.nonce)
Bulk operations
Create multiple orders
const results = await ctx.orders.bulkCreate([
{
marketId: "0x1234...",
outcome: "yes",
side: "buy",
priceCents: 40,
size: 5,
},
{
marketId: "0x1234...",
outcome: "yes",
side: "buy",
priceCents: 35,
size: 10,
},
])
for (const r of results) {
console.log(`${r.order.nonce}: ${r.success ? "placed" : "failed"}`)
}
Cancel multiple orders
const results = await ctx.orders.bulkCancel([
"0xnonce1...",
"0xnonce2...",
])
Mixed bulk operations
Create and cancel orders in a single request:
const result = await ctx.orders.bulk(
// Orders to create
[
{ marketId: "0x...", outcome: "yes", side: "buy", priceCents: 45, size: 10 },
],
// Nonces to cancel
["0xold-nonce..."],
)
for (const r of result.results) {
console.log(`${r.type}: ${r.success ? "ok" : "failed"}`)
}
Query orders
List orders
const { orders, cursor } = await ctx.orders.list({
trader: "0xAddress...",
marketId: "0x1234...",
status: "open",
limit: 50,
})
List all (auto-paginate)
Automatically fetches all pages:
const allOrders = await ctx.orders.listAll({
trader: "0xAddress...",
status: "filled",
})
Your orders
Shorthand for filtering by your signer’s address:
// Your open orders
const { orders } = await ctx.orders.mine()
// Your open orders for a specific market
const { orders: marketOrders } = await ctx.orders.mine("0x1234...")
// All your orders (auto-paginate)
const allMyOrders = await ctx.orders.allMine()
Get a single order
const order = await ctx.orders.get("order-id")
console.log(order.status) // "open" | "filled" | "cancelled" | "expired" | "voided"
console.log(order.percentFilled) // 0-100
Recent orders
Fetch orders within a time window:
const { orders } = await ctx.orders.recent({
trader: "0xAddress...",
windowSeconds: 3600, // last hour
})
Simulate order execution
Preview how an order would fill against the current book:
const sim = await ctx.orders.simulate({
marketId: "0x1234...",
trader: "0xAddress...",
maxSize: "10000000", // 10 contracts (raw)
maxPrice: "500000", // 50¢ (raw)
outcomeIndex: 1, // Yes (0 = No, 1 = Yes)
side: "bid",
})
console.log("Fill size:", sim.summary.fillSize)
console.log("Fill cost:", sim.summary.fillCost)
console.log("Slippage:", sim.summary.slippageBps, "bps")
console.log("Sufficient collateral:", sim.collateral.isSufficient)
The simulate endpoint uses raw on-chain values (6 decimal places), unlike orders.create() which accepts human-friendly cents and contracts.
Order lifecycle
Orders move through these states:
| Status | Description |
|---|
open | Resting on the book, waiting for fills |
filled | Fully matched and settled |
cancelled | Cancelled by the trader |
expired | Past the order’s expiry time |
voided | Rejected by the system (see void reasons below) |
All terminal states (filled, cancelled, expired, voided) are final. Orders track partial fills via filledSize, remainingSize, and percentFilled.
Void reasons
When an order is voided, voidReason indicates why:
| Reason | Description |
|---|
UNFILLED_MARKET_ORDER | Market order couldn’t fill (insufficient liquidity) |
UNDER_COLLATERALIZED | Insufficient balance in Holdings contract |
MISSING_OPERATOR_APPROVAL | Wallet hasn’t approved the Settlement operator |