Skip to content

SOLPREDS Developer Quickstart

Build bots to trade on the Solana prediction market.

What the API Does

  • Market Data: Real-time rounds, odds, liquidity, prices
  • Authentication: Wallet signature auth (non-custodial)
  • Trading: Prepare bet transactions for on-chain submission
  • WebSocket: Live updates for market changes and settlements

Base URLs

REST API: https://solpreds.fun/api/bot
WebSocket: wss://solpreds.fun


Available Endpoints

Endpoint Method Auth Description
/market GET No Current round state, odds, liquidity
/history GET No Past rounds and recent bets
/rules GET No Fees, timing, payout formulas
/positions/:wallet GET No Positions for any wallet
/price GET No SOL/USD price from Pyth
/auth/nonce GET No Get nonce for signing
/auth/verify POST No Submit signature, get token
/auth/status GET Yes Check token validity
/auth/positions GET Yes Your detailed positions
/auth/prepare-bet POST Yes Get transaction data

Authentication Flow

1. GET /auth/nonce?wallet=YOUR_WALLET
   → Returns { nonce, message, expiresIn }

2. Sign the message with your wallet private key
   → Use nacl.sign.detached() or @solana/web3.js

3. POST /auth/verify { wallet, nonce, signature }
   → Returns { token, expiresAt }

4. Use token in requests:
   Authorization: Bearer YOUR_TOKEN

Token expires in 24 hours.


Quick Code Example

const nacl = require('tweetnacl');
const bs58 = require('bs58');
const io = require('socket.io-client');

const API = 'https://solpreds.fun/api/bot';

// Your wallet keypair (never expose private key!)
const keypair = /* your Solana keypair */;
const wallet = keypair.publicKey.toBase58();

// 1. Authenticate
async function authenticate() {
  // Get nonce
  const nonceRes = await fetch(`${API}/auth/nonce?wallet=${wallet}`);
  const { nonce, message } = await nonceRes.json();

  // Sign message
  const messageBytes = new TextEncoder().encode(message);
  const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
  const signatureB58 = bs58.encode(signature);

  // Verify and get token
  const verifyRes = await fetch(`${API}/auth/verify`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ wallet, nonce, signature: signatureB58 }),
  });

  return (await verifyRes.json()).token;
}

// 2. Get market data
async function getMarket() {
  const res = await fetch(`${API}/market`);
  return res.json();
}

// 3. Listen to WebSocket events
function connectWebSocket() {
  const socket = io('wss://solpreds.fun');

  socket.on('market-update', (data) => {
    console.log('Market:', data.next?.upPayout, data.next?.downPayout);
  });

  socket.on('round-settled', (data) => {
    console.log(`Round ${data.roundId}: ${data.outcome} won`);
  });
}

// Run
(async () => {
  const token = await authenticate();
  console.log('Authenticated:', token);

  const market = await getMarket();
  console.log('Current round:', market.currentRoundId);

  connectWebSocket();
})();

WebSocket Events

Event Trigger Data
market-update Every 10s Round state, odds, time remaining
bet_activity New bet placed wallet, amount, side, roundId
round-settled Round resolved roundId, outcome, prices, payout

Rate Limits

  • Public endpoints: 100 req/min per IP
  • Authenticated endpoints: 100 reads/min, 10 writes/min per wallet
  • Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset

Next Steps