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

GET /v1/predict/markets?category=crypto&status=open
ParamTypeNotes
categorystringpolitics, sports, crypto, culture, ai, economy, science, other
statusstringopen (default), resolved, all
const list = await p.markets({ category: 'crypto' });
// { ok: true, count: 3, markets: [...] }

Market detail

GET /v1/predict/market/:id

Returns full market state: outstanding YES/NO shares, LMSR b, orderbook depth (5 levels each side), 200-point price history.

Create a market

POST /v1/predict/create
FieldTypeNotes
questionstring10-512 chars, must be decidable YES/NO
categorystringsee list above
expiryintunix seconds, >5min ahead
resolution_sourcestringmetercall-oracle, chainlink, or dao-vote
curator_bondnumberUSDC, min 50
liquidity_bnumberLMSR 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,
});
Curator economics: post $50, earn 0.5% of lifetime volume on clean resolve. If the DAO proves manipulation, bond is slashed to the treasury.

Trade

POST /v1/predict/trade
FieldTypeNotes
idstringmarket id
sidestringYES or NO
amountnumberUSDC in
min_outnumberslippage 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

POST /v1/predict/resolve/:id

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

POST /v1/predict/claim/:id

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

GET /v1/predict/portfolio/:user

Returns aggregated open positions, mark value at current prices, and realized PnL.

Leaderboard

GET /v1/predict/leaderboard

Top 50 traders by realized PnL.

GET /v1/predict/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.