Skip to content

Commit 4f94910

Browse files
rajkariaclaude
andauthored
feat: add Hunch venue (parimutuel prediction market on Base, x402) (#1150)
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>
1 parent b5a6ef3 commit 4f94910

15 files changed

Lines changed: 2786 additions & 0 deletions

File tree

core/COMPLIANCE.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,43 @@ This document details the feature support and compliance status for each exchang
3434
## Legend
3535
- **Y** - Supported
3636
- **-** - Not supported
37+
- **E** - Emulated (backed by a non-native mechanism)
38+
39+
> NOTE: the grid above is regenerated by `generate:compliance` from
40+
> `core/src/exchanges/*/index.ts`. The Hunch column below is documented inline
41+
> until the next regeneration picks it up.
42+
43+
## Hunch
44+
45+
Hunch is a **parimutuel** prediction market on **Base** (USDC). Markets are
46+
pool-based — there is no CLOB and no AMM curve; prices are *implied odds*.
47+
Settlement is **x402 / EIP-3009 `transferWithAuthorization`** (the bettor's
48+
wallet signs a USDC authorization; the relayer sponsors gas). Identity is
49+
keyless — the wallet IS the account, so reads need no API key.
50+
51+
| Category | Function | Hunch | Notes |
52+
| :--- | :--- | :---: | :--- |
53+
| **Market Data** | `fetchMarkets` | Y | `GET /api/agent/v1/markets` |
54+
| | `fetchEvents` | Y | No event tier — each market wrapped as a single-market event |
55+
| | `fetchMarket` | Y | `GET /api/agent/v1/markets/{id}` |
56+
| | `fetchEvent` | Y | Synthetic single-market event |
57+
| **Public Data** | `fetchOHLCV` | Y | From research `oddsHistory` (flat candles) |
58+
| | `fetchOrderBook` | E | Emulated: single level at the implied price, pool as depth |
59+
| | `fetchTrades` | Y | research `oddsHistory` as the public tape |
60+
| **Private Data** | `fetchBalance` | Y | `GET .../wallet/{address}/readiness` → USDC balance |
61+
| | `fetchPositions` | Y | `GET /api/agent/v1/positions?wallet=` |
62+
| | `fetchMyTrades` | - | Not exposed (use `fetchPositions` / proof) |
63+
| **Trading** | `createOrder` | Y | Self-hosted Base **x402** money path; **market orders only** |
64+
| | `cancelOrder` | - | Parimutuel pool — bets cannot be cancelled |
65+
| | `fetchOrder` | - | Parimutuel — no resting orders |
66+
| | `fetchOpenOrders` | Y | Always `[]` (no resting orders) |
67+
| **Real-time** | `watchOrderBook` | E | Poll-based emulation |
68+
| | `watchTrades` | E | Poll-based emulation |
69+
70+
`createOrder` accepts only `side: 'buy'` and `type: 'market'`; `outcomeId`
71+
encodes the Hunch side as `"{marketId}:{side}"` where `side` is `yes`/`no` for
72+
binary markets or the parimutuel bucket key for N-way ladder / date-window
73+
markets. Bets above the $10 "simple tier" first fetch a price-locked quote.
3774

3875
## Compliance Policy
3976
- **Failure over Warning**: Tests must fail if no relevant data (markets, events, candles) is found. This ensures that we catch API breakages or unexpected empty responses.
@@ -52,4 +89,7 @@ MYRIAD_API_KEY=...
5289
MYRIAD_WALLET_ADDRESS=0x...
5390
# Metaculus (required for API access — unauthenticated requests return 403)
5491
METACULUS_API_TOKEN=...
92+
# Hunch (reads are keyless; privateKey signs the x402 USDC payment on Base)
93+
HUNCH_PRIVATE_KEY=0x...
94+
HUNCH_WALLET_ADDRESS=0x... # optional; derived from HUNCH_PRIVATE_KEY when absent
5595
```

0 commit comments

Comments
 (0)