MeterCall Predict
Permissionless binary (YES/NO) prediction markets. Anyone creates, anyone trades, the oracle resolves. No KYC, no admin gate. Markets live under /v1/predict/* and settle against USDC.
Why this exists: Polymarket gates categories. Kalshi needs CFTC approval per market. Augur's UMA disputes run for days. We replace the bottleneck with a bonded curator and an oracle callback. If the oracle answers, the market settles. If the curator is caught manipulating, the bond is slashed.
Install the SDK
// Zero dependencies. Node 18+ or any modern browser. import { MeterCallPredict } from '/sdks/predict.js'; const p = new MeterCallPredict({ baseUrl: 'https://metercall.ai', apiKey: process.env.MC_KEY, });
Authentication
Bearer token on every REST call. Get one at /keys. For agent-pay: attach X-Payment with a signed USDC commitment instead of an API key. Both work.
List markets
| Param | Type | Notes |
|---|---|---|
category | string | politics, sports, crypto, culture, ai, economy, science, other |
status | string | open (default), resolved, all |
const list = await p.markets({ category: 'crypto' }); // { ok: true, count: 3, markets: [...] }
Market detail
Returns full market state: outstanding YES/NO shares, LMSR b, orderbook depth (5 levels each side), 200-point price history.
Create a market
| Field | Type | Notes |
|---|---|---|
question | string | 10-512 chars, must be decidable YES/NO |
category | string | see list above |
expiry | int | unix seconds, >5min ahead |
resolution_source | string | metercall-oracle, chainlink, or dao-vote |
curator_bond | number | USDC, min 50 |
liquidity_b | number | LMSR liquidity parameter, default 1000 |
await p.create({ question: 'Will BTC close above $130K on 2026-09-30?', category: 'crypto', expiry: Math.floor(Date.now()/1000) + 86400*90, resolution_source: 'metercall-oracle', curator_bond: 50, liquidity_b: 1000, });
Trade
| Field | Type | Notes |
|---|---|---|
id | string | market id |
side | string | YES or NO |
amount | number | USDC in |
min_out | number | slippage floor on shares received |
await p.trade({ id: mkt.id, side: 'YES', amount: 25, minOut: 40 });
Pricing is LMSR. Fee is 0.5% protocol + 0.5% curator, taken off the top.
Resolve
Callable once expiry has passed. For metercall-oracle and chainlink, the server polls the source and sets the outcome. For dao-vote, attach a dao_signature and an outcome of YES, NO, or INVALID.
Normally you do not call this โ the PREDICT_RESOLVER_BOT (bot #105) scans expired markets every 60s and settles them automatically.
Claim winnings
Each winning share pays 1 USDC. Invalid markets refund both sides at 0.5 USDC per share.
const r = await p.claim(mkt.id); console.log('paid', r.payout, r.outcome);
Portfolio
Returns aggregated open positions, mark value at current prices, and realized PnL.
Leaderboard
Top 50 traders by realized PnL.
Trending
Top 20 markets by 24h volume.
On-chain contract
Source: contracts/MeterCallPredict.sol. MIT-licensed, ~250 LOC. Four externals:
createMarket(question, kind, resolver, expiry, bond, b) returns (id) trade(id, side, amount, minOut) returns (sharesOut) resolve(id, forcedOutcome) // oracle callback or DAO claim(id) returns (payout)
Scaffold โ not audited. LMSR math uses a linear placeholder; production replaces with PRBMath fixed-point exp/ln.
Resolver bot
Bot #105 (PREDICT_RESOLVER_BOT) runs server-side. Every 60s it scans markets where expiry < now and status = open, calls the configured resolution source, and settles. Logs land in stdout as [PREDICT_RESOLVER_BOT #105]. Opt out with PREDICT_BOT_OFF=1 if you need manual control.