HunchCup
Browse the docs

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 shapeSide keysExample
Up / Downup · down“Will $BTC close up this hour?”
Binaryyes · no“Will $TOKEN cross $100M mcap?”
N-way ladderone key per bucketle-0.25m, 0.25m-0.3m, ge-0.55m
Token race / versusone key per candidatezec, ada, xmr

UP/DOWN is never YES/NO

Direction markets label their outcomes 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.

GET /api/cup/v1/markets → markets[]
{
  "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.

bash
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:

typescript
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
});
  1. 1The minimum bet is 1 $pUSDC; spending more than your balance returns 402.
  2. 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.
  3. 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.
  4. 4A closed, resolved, or past-deadline market returns 409 market_closed; a dormant tournament returns 409 cup_closed.

Why sign?

Without a signature anyone could spend a competitor’s paper balance. The signature is the only thing that proves wallet ownership on the keyless paper path — there is no password or session. Reads stay fully public.

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():

typescript
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

bash
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 it

The full money model — parimutuel pools, shares, and payout — is in API & MCP reference; the typed surface in SDK reference.