Skip to content

feat: add Hunch venue (parimutuel prediction market on Base, x402)#1150

Open
rajkaria wants to merge 1 commit into
pmxt-dev:mainfrom
rajkaria:hunch-venue-adapter
Open

feat: add Hunch venue (parimutuel prediction market on Base, x402)#1150
rajkaria wants to merge 1 commit into
pmxt-dev:mainfrom
rajkaria:hunch-venue-adapter

Conversation

@rajkaria

Copy link
Copy Markdown

Adds Hunch (playhunch.xyz) as a pmxt venue — unique crypto-native inventory (token market-cap milestones/ladders, up/down, launchpad, date-window markets) settling in USDC on Base.

Market model

Parimutuel (pool-based) — not CLOB, not AMM. Modeled on the Myriad adapter: market-orders only, fetchOrderBook: 'emulated' (a single level synthesized from the implied price + pool), cancelOrder / limit / sell unsupported. Reads are keyless; trading is self-hosted via a Base private key.

Surface (core/src/exchanges/hunch/)

All reads normalize Hunch's live agent API (/api/agent/v1/*; OpenAPI at /openapi.json):

  • fetchMarkets / fetchEvents (single-market wrap — Hunch has no event tier) / fetchOHLCV (flat candles from the odds tape) / fetchOrderBook (emulated) / fetchTrades / fetchPositions / fetchBalance.
  • Binary markets → YES/NO outcomes; N-way (mcap ladders, date windows) → one outcome per bucket key. outcomeId encodes ${marketId}:${side} and round-trips back to a Hunch trade side.
  • createOrder runs Hunch's x402 loop: POST /trade402 → sign the EIP-3009 TransferWithAuthorization (viem) → re-POST with X-PAYMENT → 200 receipt. Orders > $10 fetch a price-locked quote first. Verified end-to-end against the live 402 challenge (no funds moved).

Registration

index.ts (export + registry + Hunch), server/exchange-factory.ts (case "hunch"), server/openapi.yaml (ExchangeParam enum), COMPLIANCE.md.

Tests

core/test/normalizers/hunch-normalizer.test.ts47 tests: binary + N-way mapping, the money-critical outcomeIdside round-trip, position/balance/OHLCV/emulated-orderbook. tsc --noEmit clean.

Notes for maintainers

  • hunch/api.ts embeds the live /openapi.json (the 10 ops the adapter drives) — re-run your fetch:openapi to regenerate canonically; I did not run generate:sdk:all (maintainer toolchain).
  • Self-hosted creds: HUNCH_PRIVATE_KEY / HUNCH_WALLET_ADDRESS (Base). Hosted-mode trading (your Polygon escrow) is out of scope — Hunch settles on Base via x402 — so it lists as read-only hosted / tradeable self-hosted, like Kalshi.
  • A funded $1 createOrder from a Base wallet is the natural live trade test.
  • volume24h is 0 (Hunch reports no 24h split; total volume is the pool size) — a fast-follow on our side can add it.

Happy to iterate on anything — thanks @Sammie for the nudge to wire this up. 🤝

🤖 Generated with Claude Code

Hunch (playhunch.xyz) is a parimutuel prediction market on Base, settling via
x402 / EIP-3009 USDC. Adapter mirrors the Myriad pattern: reads (markets/events/
OHLCV/trades/positions/balance) normalize the live agent API; orderbook is
emulated from the implied price + pool; createOrder runs the x402 402->sign
EIP-3009->200 loop (viem), self-hosted via a Base private key. Market-orders only
(cancel/limit/sell unsupported — parimutuel). Registered in index.ts, the server
exchange factory, the ExchangeParam enum, and COMPLIANCE.md.

Tests: core/test/normalizers/hunch-normalizer.test.ts (47) — binary + N-way
mapping, the money-critical outcomeId<->side round-trip, position/balance/OHLCV/
emulated-orderbook. tsc --noEmit clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@realfishsam

Copy link
Copy Markdown
Contributor

PR Review: VERIFIED

What This Does

Adds Hunch as a new PMXT venue adapter for Base/x402 parimutuel prediction markets. SDK consumers can discover Hunch markets through the normal sidecar exchange route (/api/hunch/fetchMarkets) and receive normalized PMXT market/outcome shapes.

Blast Radius

New core/src/exchanges/hunch/* exchange implementation, Hunch registration in core/src/index.ts, core/src/server/app.ts, core/src/server/exchange-factory.ts, the OpenAPI ExchangeParam enum, compliance docs, and focused Hunch normalizer tests. No Python/TypeScript SDK wrapper changes are included beyond the core OpenAPI enum entry.

Consumer Verification

Before (base branch):
Hunch is not registered in the sidecar exchange set, so a consumer cannot call the venue through PMXT's normal exchange route.

POST /api/hunch/fetchMarkets {"params":{"limit":2}}
# base branch: exchange route is absent / hunch is not a supported ExchangeParam

After (PR branch):
Built and started the sidecar, then called the consumer-facing HTTP route with the local access token:

curl -X POST http://localhost:3847/api/hunch/fetchMarkets \
  -H 'Content-Type: application/json' \
  -H 'x-pmxt-access-token: <local token>' \
  -d '{"params":{"limit":2}}'

Response snippet:

{
  "success": true,
  "data": [
    {
      "marketId": "bankr-100m-mcap-2026-06-30",
      "title": "Will $BNKR reach $100M market cap by June 30, 2026 at 11:59 PM UTC?",
      "slug": "bankr-100m",
      "outcomes": [
        { "outcomeId": "bankr-100m-mcap-2026-06-30:yes", "price": 0 },
        { "outcomeId": "bankr-100m-mcap-2026-06-30:no", "price": 0 }
      ],
      "status": "active",
      "sourceMetadata": { "headline": "$BNKR $100M by June 30 · YES 68¢ / NO 32¢ · 3 bets · $4 pool · closes June 30" }
    }
  ]
}

Test Results

  • Build: PASS (npm run build --workspace=pmxt-core)
  • Unit tests: PASS (47 passed, 0 failed: npm --workspace=pmxt-core test -- --runTestsByPath test/normalizers/hunch-normalizer.test.ts)
  • Server starts: PASS (PMXT Sidecar Server ... running on http://localhost:3847)
  • E2E smoke: PASS (/api/hunch/fetchMarkets returned normalized market data)

Findings

No blocking findings.

PMXT Pipeline Check

  • Field propagation (3-layer): OK for existing unified market fields exercised by fetchMarkets; no new unified fields added
  • OpenAPI sync: OK (hunch is present in the ExchangeParam enum)
  • Financial precision: OK for reviewed money-critical order path (USDC authorization uses integer parseUnits/bigint); normalizer price outputs are probabilities like other PMXT market data
  • Type safety: OK (core TypeScript build passes)
  • Auth safety: OK (private key is required lazily for createOrder; no credential logging observed)

Semver Impact

minor -- adds a new venue and new exchange capability surface.

Risk

I verified public market discovery end-to-end. I did not place a real Hunch bet or exercise the x402 signing/payment loop because that would require live funds/private-key side effects; the money path remains covered only by static review and normalizer tests in this run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants