Permissionless resolver daemon for the Settled prediction market protocol on Solana.
Settled runs binary YES/NO prediction markets on crypto perpetual futures funding rates — 2,400+ markets across Binance, Bybit, Hyperliquid, KuCoin, and Gate. Each market resolves when the funding rate settles. This daemon does the resolving.
How it earns: Scan for closed markets → submit resolve_market_permissionless → earn 10 bps (0.1%) of the market's total trading volume as a USDC tip. First valid submission wins. Gas costs ~$0.001 on Solana.
→ Browse live markets on settled.pro
→ Read how resolvers work
→ API docs
- Go 1.22+ (or Docker)
- A funded Solana keypair (needs SOL for gas + a USDC token account for tips)
solana-keygen new -o resolver-keypair.json
# Fund it with devnet SOL:
solana airdrop 2 $(solana-keygen pubkey resolver-keypair.json) --url devnetcp .env.example .env
# Edit .env — set SOLANA_RPC_URL and RESOLVER_KEYPAIR at minimumWith Go:
make runWith Docker:
docker compose up -dLogs show scanned markets and submitted transactions:
INFO starting settled resolver {"program_id": "7rLM...", "resolver": "YourKey...", "poll_interval": "30s"}
INFO found resolvable markets {"count": 2}
INFO transaction submitted {"market_id": "abc123...", "signature": "5xK..."}
INFO transaction confirmed {"market_id": "abc123...", "signature": "5xK..."}
| Variable | Required | Default | Description |
|---|---|---|---|
SOLANA_RPC_URL |
Yes | — | Solana RPC endpoint |
RESOLVER_KEYPAIR |
Yes | — | Path to JSON keypair or base58 private key |
PROGRAM_ID |
No | 7rLM8d27... |
Settled program ID |
POLL_INTERVAL |
No | 30s |
How often to scan for markets |
LOG_LEVEL |
No | info |
debug, info, warn, error |
DRY_RUN |
No | false |
Log resolvable markets without submitting TXs |
Settled markets follow a fixed lifecycle:
- Open → traders buy YES/NO shares via LMSR AMM
- Closed → market passes settlement time, locked for resolution
- Resolved → resolver submits oracle proof on-chain → winning shares pay $1.00
This daemon handles step 3:
- Scan —
getProgramAccountswith memcmp filters for MarketState discriminator +status=Closed - Filter — Only markets past their
settlement_tsare eligible - Resolve — Builds and submits
resolve_market_permissionlessinstruction with Switchboard oracle proof - Confirm — Waits for finalized confirmation via WebSocket (falls back to polling)
- Repeat — Sleeps for
POLL_INTERVAL, then scans again
Failed resolutions (already resolved, oracle unavailable, etc.) are logged and skipped — the daemon continues to the next market.
The resolver earns 0.1% of total market volume per successful resolution. With 22,000+ markets resolving per day across the platform, active resolvers compete on speed — first valid submission wins.
The resolver exposes Prometheus metrics at /metrics (default :8082).
| Variable | Required | Default | Description |
|---|---|---|---|
METRICS_ADDR |
No | :8082 |
Address for the metrics HTTP server |
| Metric | Type | Description |
|---|---|---|
resolver_cycles_total |
counter | Total scan cycles completed |
resolver_markets_scanned |
gauge | Markets found in last scan |
resolver_resolutions_total{status} |
counter | Resolutions by status (success/failure) |
resolver_scan_duration_seconds |
histogram | Scan cycle duration |
resolver_resolution_duration_seconds |
histogram | Per-market resolution duration |
resolver_last_cycle_timestamp_seconds |
gauge | Unix timestamp of last scan |
The monitoring/ directory includes:
prometheus.yml— Sample scrape config to add to your Prometheusalerts.yml— Alert rules (heartbeat stale, resolution failures, slow scans)grafana-dashboard.json— Import into Grafana for instant visibility
# Add the scrape config to your prometheus.yml, then import the dashboard:
# Grafana → Dashboards → Import → Upload JSON → monitoring/grafana-dashboard.jsoncmd/resolver/main.go — entry point, config, signal handling, main loop
internal/scanner/ — getProgramAccounts with memcmp filters
internal/resolver/ — TX building, signing, submission, confirmation
pkg/pda/ — PDA derivation (vault_state, market_state, ATAs)
pkg/state/ — MarketState account deserialization
pkg/types/ — constants, enums
- Settled — Live prediction markets
- Funding rate data for 2,400+ pairs
- How resolvers earn on Settled
- LMSR AMM — how Settled prices markets
- API reference
- Zirodelta on GitHub
Apache-2.0