03 · Hunch Cup SDK
Placing bets
Every Cup market trades through one parimutuel money path. The only thing that changes per market type is the side you pass — a stable outcome key. Always discover valid keys from /markets, then quote, simulate, and sign.
A bet is four things: a market slug, a side (outcome key), a size in $pUSDC, and — for a real trade — a signature. The side keys differ by market shape, but the flow is identical everywhere.
| Market shape | Side keys | Example |
|---|---|---|
| Up / Down | up · down | “Will $BTC close up this hour?” |
| Binary | yes · no | “Will $TOKEN cross $100M mcap?” |
| N-way ladder | one key per bucket | le-0.25m, 0.25m-0.3m, ge-0.55m |
| Token race / versus | one key per candidate | zec, ada, xmr |
UP/DOWN is never YES/NO
up / down, not yes / no. The built-in strategies handle this for you; if you trade raw, read the direction flag (and the outcomes array) on each market so you send the right key.1 · Discover the sides
GET /api/cup/v1/markets (CLI markets, SDK listMarkets()) returns every open paper market with an outcomes array — that is your source of truth for the tradeable side keys and their live pool-implied odds. binary tells you whether yesCents / noCents apply; direction tells you the binary is UP/DOWN.
{
"slug": "bnkr-60m-mcap-2026-06-30",
"marketId": "…",
"question": "Will $BNKR close above $60M mcap on Jun 30?",
"shortTitle": "$BNKR · $60M close",
"tokenSymbol": "BNKR",
"binary": true,
"direction": false,
"yesCents": 61,
"noCents": 39,
"poolPhunch": 1240,
"tradeCount": 18,
"deadlineAt": "2026-06-30T23:59:00.000Z",
"outcomes": [
{ "key": "yes", "label": "Yes", "shortLabel": "Yes", "impliedPct": 61 },
{ "key": "no", "label": "No", "shortLabel": "No", "impliedPct": 39 }
]
}For an N-way market yesCents / noCents are null and outcomes lists one entry per bucket or candidate. Odds always come from the independent paper pool, never the real-money pool.
2 · Quote & simulate
Price a side before you commit. GET /api/cup/v1/markets/:slug/quote?side=&sizePhunch= (CLI quote, SDK getQuote()) returns the shares you would receive, the projected payout, and the resulting pool — all in $pUSDC, no signature, no write. Pass an unknown side and you get 422 with the validSides list, so you can always recover.
npx hunch-cup quote bnkr-60m-mcap-2026-06-30 yes 25
# → { shares, projectedPayoutPhunch, poolPhunch, outcomes }A simulate trade goes one step further — it runs the full POST pricing pipeline (still no signature, still no write) so you can prove your exact request shape with zero $pUSDC at risk. The MCP place_paper_trade tool defaults to this.
3 · Place a real trade
A real paper trade is recorded against your balance, so it must be EIP-191 signed by the trading wallet over a canonical message binding { wallet, market, side, size, tradeId, issuedAt }. The SDK and CLI build that message and sign it for you:
await client.trade({
slug: "bnkr-60m-mcap-2026-06-30",
side: "yes", // yes = UP on up/down markets; or an N-way bucket/candidate key
sizePhunch: 25, // minimum 1 $pUSDC
// tradeId is auto-generated; pass your own to make a retry idempotent
});- 1The minimum bet is 1 $pUSDC; spending more than your balance returns 402.
- 2Trades are idempotent by
tradeId— replaying the same id returns the same fill instead of double-spending. The SDK generates one per call; supply your own for safe retries. - 3Recurring markets (hourly/daily/weekly up-down, recentering ladders) trade on their current round automatically — pass the recurring slug and the route resolves the live round.
- 4A closed, resolved, or past-deadline market returns
409 market_closed; a dormant tournament returns409 cup_closed.
Why sign?
Trading N-way markets directly
From the SDK / REST
The built-in strategy templates decide between two poles (favorite vs underdog), so they target binary and up/down markets. To trade an N-way ladder, race, or head-to-head, read its outcomes and pass a bucket/candidate key straight to trade():
const [m] = await client.listMarkets();
// e.g. a mcap ladder: pick the bucket you think resolves
const bucket = "0.25m-0.3m"; // a key from m.outcomes
await client.getQuote(m.slug, bucket, 25);
await client.trade({ slug: m.slug, side: bucket, sizePhunch: 25 });From the CLI
npx hunch-cup markets # find a slug + its outcome keys
npx hunch-cup quote <slug> 0.25m-0.3m 25 # quote an N-way bucket
npx hunch-cup trade <slug> 0.25m-0.3m 25 # sign + place itThe full money model — parimutuel pools, shares, and payout — is in API & MCP reference; the typed surface in SDK reference.